[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Chicken-users] Performance of write-char (and I/O in general)
From: |
Jeronimo Pellegrini |
Subject: |
Re: [Chicken-users] Performance of write-char (and I/O in general) |
Date: |
Thu, 25 Mar 2010 12:15:44 -0300 |
User-agent: |
Mutt/1.5.20 (2009-06-14) |
I forgot to mention: this is with git master/HEAD
(4cbc9d250a5f2a60a4526ad1435c13a1d605cef4).
J.
On Thu, Mar 25, 2010 at 11:32:46AM -0300, Jeronimo Pellegrini wrote:
> Hello,
>
> I recently noticed that reading numbers from a file was much
> slower from compiled Chicken using the read procedure than
> if I used fscanf directly from the FFI. (The thread is
> "Getting C file handle from port?").
>
> Anyway, I understand that the standard read procedure will
> perform some checks (is it a port? what is the type of the
> object?) etc. So I made one for myself that just reads numbers
> and bails out if anything goes wrong.
>
> But I'd expect writing to be faster, since there is no need for
> parsing. See this program:
>
> /------- write-file.scm
>
> (define write-char/ffi
> (foreign-lambda* void ((char c)
> (scheme-object port))
> "fprintf(C_port_file(port),\"%c\",c);"))
>
> (define write-file/ffi
> (lambda (port times)
> (let ((a #\a))
> (do ((i 0 (fx+ 1 i)))
> ((fx= i times))
> (assert (char? a))
> (assert (port? port))
> (write-char/ffi #\a port)))))
>
> (define write-file/write-char
> (lambda (port times)
> (do ((i 0 (fx+ 1 i)))
> ((fx= i times))
> (write-char #\a port))))
>
> (let ((args (command-line-arguments)))
> (let ((times (string->number (cadr args)))
> (name (car args)))
> (call-with-output-file name
> (lambda (port)
> (time (write-file/write-char port times))))
> (call-with-output-file name
> (lambda (port)
> (time (write-file/ffi port times))))))
>
> \--------
>
> $ csc -O5 write-file.scm
>
> $ ./write-file tt 30000000
> 5.515 seconds elapsed
> 0.078 seconds in (major) GC
> 0 mutations
> 0 minor GCs
> 114 major GCs
> 0.575 seconds elapsed
> 0 seconds in (major) GC
> 0 mutations
> 0 minor GCs
> 0 major GCs
>
>
> OK, so maybe write-char is slow because it's verifying if the
> character was properly written.
> Let's see what happens if I also do this check in the FFI version:
>
> (define write-char/ffi
> (foreign-lambda* void ((char c)
> (scheme-object port))
> "if (1 != fprintf(C_port_file(port),\"%c\",c)) exit(-1);" ))
>
> Now the FFI version is much slower:
> 3.537 seconds elapsed
> 0 seconds in (major) GC
> 0 mutations
> 0 minor GCs
> 0 major GCs
>
> Eh? A single if, and its test is just an integer comparison! What
> happened?
>
> OK, so I'll dump fprintf and use a probably better suited function --
> fputc.
>
> (define write-char/ffi
> (foreign-lambda* void ((char c)
> (scheme-object port))
> "if (EOF == fputc(c, C_port_file(port))) exit(-1);" ))
>
> And HEY, it's fast!
>
> 0.582 seconds elapsed
> 0 seconds in (major) GC
> 0 mutations
> 0 minor GCs
> 0 major GCs
>
> (Actually, as fast as a C implementation I also made).
>
> So -- what does write-char use internally? And why checking the
> return value of fprintf takes so much more time?
>
> J.
>
>
>
> _______________________________________________
> Chicken-users mailing list
> address@hidden
> http://lists.nongnu.org/mailman/listinfo/chicken-users