chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Chicken-users] Performance of write-char (and I/O in general)


From: Jeronimo Pellegrini
Subject: [Chicken-users] Performance of write-char (and I/O in general)
Date: Thu, 25 Mar 2010 11:32:46 -0300
User-agent: Mutt/1.5.20 (2009-06-14)

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.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]