I tried writing a biggish string to a string port, and it was very slow. Eg.
(use-modules (ice-9 time)) (let ((str (make-string 100000 #\x))) (call-with-output-string (lambda (port) (time (display str port)))) #f) gives on my poor 333mhz clock utime stime cutime cstime gctime 7.63 7.58 0.05 0.00 0.00 4.17 I struck this trying to use regexp-substitute/global on a file slurped into memory. It was 130k, which is a decent size, but it's well within the realm of reason. I think strports.c st_write ends up doing a realloc and copy every 80 bytes of the block it's writing. It knows the size, but it lets st_flush just grow by 80 bytes at a time. The change below speeds it up from 7 seconds to 10 ms for me. But I don't know if the read side bits of this change are right. Is it supposed to update read_pos, read_end and read_buf_size to be the end of the string, or something? (Of course what would be even nicer would be to avoid big reallocing altogether, like keep a list of chunks and only join them when a get-string call wants the entire block. But that can wait.)
--- strports.c.~1.105.~ 2005-01-28 08:25:34.000000000 +1100 +++ strports.c 2005-02-14 11:20:05.000000000 +1100 @@ -142,18 +142,14 @@ scm_t_port *pt = SCM_PTAB_ENTRY (port); const char *input = (char *) data; - while (size > 0) - { - int space = pt->write_end - pt->write_pos; - int write_len = (size > space) ? space : size; - - memcpy ((char *) pt->write_pos, input, write_len); - pt->write_pos += write_len; - size -= write_len; - input += write_len; - if (write_len == space) - st_flush (port); - } + /* if not enough room for "size" then make that amount and an additional + SCM_WRITE_BLOCK */ + if (size > pt->write_end - pt->write_pos) + st_resize_port (pt, pt->write_pos - pt->write_buf + + size + SCM_WRITE_BLOCK); + + memcpy ((char *) pt->write_pos, input, size); + pt->write_pos += size; } static void
_______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel