I/O speed

Stephen Weeks MLton@sourcelight.com
Thu, 21 Sep 2000 17:56:22 -0700 (PDT)


> There is a cheat here: MLton is clever enough to never fetch the character,
> and because of that, unless you used an usafe ?.sub, it saved all kinds of
> stuff.  Try a version which counts the number of newlines as well as the number
> of bytes and see what the relative speed id.

You're right.  MLton optimizes away the array sub entirely.  Here are the new
numbers (code and spys below).

		time	rate
gcc		 25.17	39.7
MLton		 63.74	15.7
old MLton	178.71	 5.6

Oh well.  Still worse than 2X slower.  But almost 3X faster than it used to be.

--------------------------------------------------------------------------------
C code
--------------------------------------------------------------------------------
#include <stdio.h>

int main() {
  int ch, bytes, newlines;

	bytes = 0;
	newlines = 0;
	for (;;) {
		bytes++;
		ch = getchar();
		if (ch == EOF)
		      break;
		else if (ch == '\n')
			newlines++;
	}
	fprintf(stderr, "newlines = %d\nbytes = %d\n", newlines, bytes);
}

--------------------------------------------------------------------------------
C spy
--------------------------------------------------------------------------------

0x8048460:      cmpl   $0xa,%eax
0x8048463:      jne    0x8048466
0x8048466:      incl   %ebx
0x8048467:      movl   0x8049604,%edx
0x804846d:      movl   0x4(%edx),%eax
0x8048470:      cmpl   0x8(%edx),%eax
0x8048473:      jb     0x8048480
0x8048480:      movzbl (%eax),%eax
0x8048483:      incl   0x4(%edx)
0x8048486:      cmpl   $0xffffffff,%eax
0x8048489:      jne    0x8048460

--------------------------------------------------------------------------------
SML code
--------------------------------------------------------------------------------

open TextIO
val ins = stdIn
fun loop(newlines: int, bytes: int) =
   case input1 ins of
      NONE => (newlines, bytes)
    | SOME c => loop(if c = #"\n" then newlines + 1 else newlines, bytes + 1)
val (newlines, bytes) = loop(0, 0)
val _ = print(concat["newlines: ", Int.toString newlines,
		     "\nbytes: ", Int.toString bytes, "\n"])

--------------------------------------------------------------------------------
MLton spy
--------------------------------------------------------------------------------
0x804c39c:      cmpb   $0xa,0x17(%esp,1)
0x804c3a1:      jne    0x804c4d8
0x804c4d8:      movl   0x34(%esi),%ecx
0x804c4db:      jmp    0x804c3ac
0x804c3ac:      movl   %ecx,0x10(%esp,1)
0x804c3b0:      incl   0x30(%esi)
0x804c3b3:      movl   0x10(%esp,1),%ecx
0x804c3b7:      movl   %ecx,0x34(%esi)
0x804c3ba:      cmpl   0x80537c8,%edi
0x804c3c0:      jbe    0x804c427
0x804c427:      movl   0x2c(%esi),%eax
0x804c42a:      movl   (%eax),%ebp
0x804c42c:      movl   0x10(%ebp),%edx
0x804c42f:      movl   0x805322c,%eax
0x804c434:      movl   (%eax),%ebx
0x804c436:      movl   0x8053230,%eax
0x804c43b:      cmpl   (%eax),%ebx
0x804c43d:      jnl    0x804c464
0x804c43f:      movl   0x805322c,%eax
0x804c444:      leal   0x1(%ebx),%ecx
0x804c447:      movl   %ecx,(%eax)
0x804c449:      cmpl   $0xfff,%ebx
0x804c44f:      ja     0x804c96c
0x804c455:      movb   (%ebx,%edx,1),%dl
0x804c458:      movb   %dl,0x17(%esp,1)
0x804c45c:      jmp    0x804c39c