I/O speed in MLton vs. C

Henry Cejtin henry@sourcelight.com
Sat, 16 Jun 2001 01:32:52 -0500


So here are some timings of file input.

    C-fast  C,  getchar() with the right options so that you don't go through
        the insane glibc  thread-safe  code  on  every  character  of  input.
        (Note, this is what I consider as the default C speed.)

    C-slow  Just  like  Prog1,  but  with no magic #defines.  This means that
        every getchar() is a function call (actually several)  instead  of  a
        macro  to  make  sure  that  certain locks are acquired and released.
        Completly insane, but what un-informed people will  get  using  stdio
        out of the box.  In particular, what the shootout people use for gcc.

    MLton-line MLton using TextIO.inputLine, and even using the empty  string
        return  to detect EOF.  The main function returns the number of lines
        and the last line, and the a wrapper function calls  it  a  bunch  of
        times  (to  make the CPU time get measurable without making the files
        so big that caching effects become relevant) and  then  test  command
        line  flags  to  either  just  print  the number of lines or the 10th
        character of the last line read.  (All of this latter is just so that
        MLton can't optimize away the line reading.)

    MLton-char  MLton  using  TextIO.input1.  Again the main function returns
        the number of lines and the last character  and  a  wrapper  function
        calls it a bunch of times and then tests command line flags to either
        just print the number of lines or the last character read.

Here are the read rates of the different programs:

    C-fast          39,651,071 chars/second
    C-slow           5,703,205 chars/second
    MLton-line       7,067,138 chars/second
    MLton-char      21,663,778 chars/second

The moral is that TextIO.inputLine really has to be sped up, but  because  of
the  fact  that they are running gcc without the fast getchar(), we are still
faster than them.  Also TextIO.input1 really should be sped  up  if  possible
since we are almost twice as slow as a sane C getchar function.

In  case  you want to test things yourself, here is the magic you have to use
to get fast getc/getchar/putc/putchar/feof.  I long ago included them  in  my
standard  C  include  file,  although  these are the versions for Red Hat 7.1
(yes, glibc changed a bit and so you have to  adjust  these  files  for  this
world):

/*
 * The following horror is to avoid the goofyness of thread-safe I/O.
 */
#undef getc
#define getc	getc_unlocked
#undef getchar
#define getchar	getchar_unlocked
#undef putc
#define putc	putc_unlocked
#undef putchar
#define putchar	putchar_unlocked
#undef feof
#define	feof	feof_unlocked

and you have this AFTER you have included stdio.h.