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.