[cl-utilities-devel] split-sequence performance problem.

Szymon ssbm2 at o2.pl
Tue May 2 16:29:29 UTC 2006


Hi. I discovered that split-sequence* functions are *SLOW*
when input is a list.

example:

(progn (test-split-list-if)
       (test-nsplit-list-if)
       (test-split-sequence-if))

SPLIT-LIST-IF, Evaluation took:

                 0.012 seconds of real time

                 1,445,888 bytes consed.

NSPLIT-LIST-IF, Evaluation took:

                 0.008 seconds of real time

                 0 bytes consed.

SPLIT-SEQUENCE-IF, Evaluation took:

                 124.586 seconds of real time

                 1,527,328 bytes consed.

example's code:

(defun split-list-if (test list &aux (start list) (end list))
  (loop while (and end (setq start (member-if-not test end)))
        collect (ldiff start (setq end (member-if test start)))))


(defun nsplit-list-if
  (test list &aux (list (member-if-not test list)) result tail)
  (flet ((helper (list)
           (loop for i on list
                 for j = (cdr i)
                 when (funcall test (car j)) do
                 (if (cdr j)
                     (return-from helper (values i j))
                   (progn
                     (rplacd i nil)
                     (return-from helper (values list nil)))))
           (values list nil)))
    (multiple-value-bind (a b) (helper1 list)
      (unless b (return-from nsplit-list-if list))
      (rplacd a nil)
      (setq result (setq list (rplaca b list)))
      (setq list (cdr result)))
    (rplacd result nil)
    (setq tail result)
    (loop (setq list (member-if-not test list))
          (multiple-value-bind (a b) (helper1 list)
            (cond ((null b)
                   (when a (rplacd tail (list a)))
                   (return-from nsplit-list-if result))
                  (t
                   (rplacd a nil)
                   (rplacd tail (setq list (rplaca b list)))
                   (setq list (cdr list))
                   (rplacd (setq tail (cdr tail)) nil)))))))

(defun white-space-p (char)
  (member char '(#\Space #\Newline #\Return #\Tab #\Page)))

(defvar *test-result*)

(defvar *test-data*)

(defun load-test-data ()
  (setq *test-data*
        (with-open-file
         ;; http://www.gutenberg.org/dirs/etext91/alice30.txt
         (stream #P"alice30.txt")
         (loop with char
               while (setq char (read-char stream nil nil))
               collect char))))

(defun test-nsplit-list-if ()
  (load-test-data) (gc)
  (time
   (setq *test-result*
         (nsplit-list-if #'white-space-p *test-data*)))
  (values))

(defun test-split-list-if ()
  (load-test-data) (gc)
  (time
   (setq *test-result*
         (split-list-if #'white-space-p *test-data*)))
  (values))

(defun test-split-sequence-if ()
  (load-test-data) (gc)
  (time
   (setq *test-result*
         (cl-utilities:split-sequence-if
          #'white-space-p
          *test-data*
          :remove-empty-subseqs t)))
  (values))


Regards, Szymon.



More information about the cl-utilities-devel mailing list