[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).