thanks for the suggestions.
Here's my results:
sharing common data made a good difference: I had a 141 MB binary, and it gets down to 44 MB.
I tried forgetting signatures, structures, and types, and even values; this made another 24MB of difference - so now I know I had 20MB of structure/signature defs. :)
It turns out that forgetting types and values make almost no difference.
So now I seem to have 20MB of code left - still much more than I would expect, but perhaps avoiding inlining functors will improve on this...
Now I have a couple of questions...
I was thinking about calling PolyML.shareCommonData on every defined value - would this do more than on PolyML.rootFunction ? or does polyml already ignore unused functions?
What happens to exceptions which are raise after PolyML.Compiler.forgetXXX where the exception would normally contain type-names ? are they also forgotten?
thanks, lucas
David Matthews wrote:
Lucas Dixon wrote:
is the code for the substructure n1 literally getting copied each time?
Even with this I find it hard to imagine how I'd generate 120 MB of machine code from 7500 lines of ML...
I noticed some forget functions in the PolyML compiler; is there some clever way to say all I care about is stuff reachable from calling some specified function?
There are several things you can do. To be honest I don't know why there is such an enormous blow-up.
If you are producing a single function as the result of your compilation then if you are exporting this all you need, as Phil says, is to run PolyML.shareCommonData on the function before you export it.
If you are building the function but still want to retain it within Poly/ML it's a little more complicated.
If you're using saveState to save the state it is always a good idea to run PolyML.shareCommonData PolyML.rootFunction; before PolyML.SaveState.saveState
What this does is go over the whole reachable memory and merge immutable values that are identical. In particular if the compiler has had to copy some signatures it will be able to merge those parts that can be merged and if they are in an existing parent state it will set the pointers to use the already saved data.
You can use PolyML.objSize to see the number of words used by everything reachable from a particular value. This could be useful to see if the blow-up is due to code in your function or information Poly/ML is keeping about structures and signatures. For example,
val x = ([1,2,3], [1,2,3]);
val x = ([1, 2, 3], [1, 2, 3]) : int list * int list
PolyML.objSize x;
val it = 21 : int
PolyML.shareCommonData x;
val it = () : unit
PolyML.objSize x;
val it = 12 : int
PolyML.objSize PolyML.rootFunction; can be used to see the total size of everything reachable from the root.
You can use PolyML.Compiler.structureNames() and similar to get a list of the structures and remove those you don't want with PolyML.Compiler.forgetStructure. You need to do this before saving state.
Let us know if this works.
David.