Skip to content

Poor performance? #50

@mishoo

Description

@mishoo

Hi folks,

I'm working on a toy project that involves encoding/decoding some binary data, and I happened to notice that using flexi-streams' in-memory streams is much much slower vs. reading/writing from a binary file. Just wondering if there is any reason for this weirdness. Here is a simple test function (it'll output like 50M into a file in /tmp/).

(ql:quickload '("trivial-utf-8" "flexi-streams"))

(defmacro mytime (title &body body)
  `(progn
     (format t "Timing: ~A~%" ,title)
     (time ,@body)))

(defun test-flexi-streams (&optional (filename "/tmp/flexistreams.bin"))
  (let* ((str "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ăşţîâĂŞŢÎÂ")
         (size (trivial-utf-8:utf-8-byte-length str))
         (times 500000)
         (sequence))
    (mytime "write to built-in stream"
      (with-open-file (output filename :element-type '(unsigned-byte 8)
                                       :direction :output
                                       :if-does-not-exist :create
                                       :if-exists :supersede)
        (loop repeat times
              do (trivial-utf-8:write-utf-8-bytes str output))))

    (mytime "write to flexi in-memory stream"
      (let ((output (flexi-streams:make-in-memory-output-stream)))
        (loop repeat times
              do (trivial-utf-8:write-utf-8-bytes str output))
        (setf sequence (flexi-streams:get-output-stream-sequence output))))

    (mytime "read from built-in stream"
      (with-open-file (input filename :element-type '(unsigned-byte 8))
        (loop repeat times
              do (trivial-utf-8:read-utf-8-string input :byte-length size))))

    (mytime "read from in-memory stream"
      (let ((input (flexi-streams:make-in-memory-input-stream sequence)))
        (loop repeat times
              do (trivial-utf-8:read-utf-8-string input :byte-length size))))))

Results here look like this:

Timing: write to built-in stream
Evaluation took:
  0.336 seconds of real time
  0.334568 seconds of total run time (0.291399 user, 0.043169 system)
  99.70% CPU
  601,427,574 processor cycles
  0 bytes consed
  
Timing: write to flexi in-memory stream
Evaluation took:
  2.256 seconds of real time
  2.256795 seconds of total run time (2.256746 user, 0.000049 system)
  [ Real times consist of 0.003 seconds GC time, and 2.253 seconds non-GC time. ]
  [ Run times consist of 0.001 seconds GC time, and 2.256 seconds non-GC time. ]
  100.04% CPU
  4,058,053,884 processor cycles
  134,180,240 bytes consed
  
Timing: read from built-in stream
Evaluation took:
  0.566 seconds of real time
  0.567083 seconds of total run time (0.543763 user, 0.023320 system)
  [ Real times consist of 0.003 seconds GC time, and 0.563 seconds non-GC time. ]
  [ Run times consist of 0.001 seconds GC time, and 0.567 seconds non-GC time. ]
  100.18% CPU
  1,019,238,246 processor cycles
  448,008,624 bytes consed
  
Timing: read from in-memory stream
Evaluation took:
  3.040 seconds of real time
  3.033796 seconds of total run time (3.027243 user, 0.006553 system)
  [ Real times consist of 0.003 seconds GC time, and 3.037 seconds non-GC time. ]
  [ Run times consist of 0.001 seconds GC time, and 3.033 seconds non-GC time. ]
  99.80% CPU
  5,456,326,518 processor cycles
  447,991,600 bytes consed

I'm using SBCL 2.3.9.63-23c796775.

I'm not sure something can be done about it, but if it's possible to improve, I guess a lot of projects will benefit. In my case I'm forced to ditch flexi-streams for now; the difference is so big that if I have the data in memory, I'm better off dumping it into a file and read it back from there, rather than going through in-memory-input-stream.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions