[MLton-user] MLton performance

Matthew Fluet fluet@cs.cornell.edu
Sun, 20 Mar 2005 15:51:06 -0500 (EST)


>  Runs in about 10 seconds on my (Dual Athlon, 512MB, Linux2.4) system.

In general, a 10 second program isn't quite long enough to make meaningful 
comparisons between SML/NJ and MLton; though, in this particular instance, 
it is easily explained.

>  If I build it with the .mlb file:
> 
> $(SML_LIB)/basis/basis.mlb
> test.sml
> 
> it's also about 10 seconds.  If I build it with:
> 
> $(SML_LIB)/basis/basis.mlb
> $(SMLNJ_LIB)/Util/smlnj-lib.mlb
> test.sml
> 
> the runtime drops to 15 seconds

Indeed, because you have a very different program in the second case. 
Even though test.sml is not using any code from the SML/NJ Util Library, 
by including it in the .mlb, you are commiting yourself to all of the 
top-level effects of that Library, including allocation and 
initialization.  Worse, you are including the TimeLimit structure, which 
requires the MLton.Signals and MLton.Thread structures.  MLton is _very_ 
conservative in the presence of signal handling and multiple threads, even 
if the user program ends up not using them in any meaningful way.  One 
consequence of this is that every loop in the program is broken by a 
signal check, which in turn impacts the way in variables are register 
allocated.

This highlights one way in which MLton's MLBs and SML/NJ's CM are 
different.  CM will selectively include only those structures from a 
library that are used by the client code.  This means that CM drops 
top-level effects from modules that are not used by the client code; 
although this is generally considered bad programming practice when the 
effects are I/O, exceptions, etc., there are situations where it may be 
useful.  Hence, MLton does not drop any code included by the user, at the 
expense of including more code than is strictly needed by the "actual" 
user code.

There is one caveat: MLton actually drops unneeded portions of the Basis 
Library implementation, including unneeded portions of the MLton 
structure.  This is why a program which includes 
$(SML_LIB)/basis/mlton.mlb does not necessarily entail keeping the 
MLton.Signals and MLton.Thread structures.  Thus far, we have been 
reluctant to expose this mechanism to end users, because it relies on 
special properties of the Basis Library implementation and can easily give 
rise to non-intuitive behavior (of the kind exhibitted by CM) in the 
presence of top-level effects.  However, it may be time to revisit this 
decision in light of MLBs as the means of modularizing very large 
programs.

Returning to your original post, if the application you are comparing 
under SML/NJ and MLton uses the SML/NJ Library, but does not use the 
TimeLimit structure, then I would suggest editting 
$(SMLNJ_LIB)/Util/smlnj-lib.mlb to eliminate TimeLimit.  We have seen 
significant slowdowns in programs that accidently include MLton's signal 
and thread handling code.

I will consider editting the SML/NJ Library code available off the 
web-site to eliminate TimeLimit from smlnj-lib.mlb (exposing it as a 
separate time-limit.mlb).