chicken-users
[Top][All Lists]
Advanced

[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: Jim Ursetto
Subject: Re: [Chicken-users] Performance of write-char (and I/O in general)
Date: Thu, 25 Mar 2010 12:52:49 -0500

gcc is smarter than you think. Compare the assembly output of the two and you will find the fprintf call without the IF check is optimized into an fputc.

-       movl    $97, (%esp)
-       call    _fputc
+       movl    (%edi), %eax
+       movl    4(%eax), %eax
+       movl    %eax, (%esp)
+       call    _fprintf

So you are not measuring what you expect. WRITE-CHAR uses fputc itself, in fact. The issue is that there is much more indirection. There is a procedure call to write-char/port, type checks, a call to write-char-0, and then an indirect call to the actual char writer for that port (a closure stored in a vector). Which happens to be fputc for stream ports like this one. It's the indirection that results in all the overhead.

Jim


On Mar 25, 2010, at 9:32 AM, 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





reply via email to

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