jamplus/jamplus — pull request #7 by ThomasSpurden (2012-11-20 11:35:21+00:00)
Title: Replace the LIST data structure

Here at Frontier Developments we are using JamPlus to build some very large projects. The memory usage of the Jam exectuable alone was peaking at around 900MB. This was starving the compilers and linkers on our 32bit Windows XP machines. I did some profiling and found that the main culprit for this was lists. Jam creates vast quantites of lists, and copies them around alot. I was able to significantly reduce memory usage by replacing the list implementation with a more encapsulated data structure, and then making them copy-on-write (since Jam makes a lot of read-only copies of lists).

This is a massive change to the Jam code base! Since it fundamentally changes the way lists operate I didn't attempt to make it opt-in via a compile-time define. I've also not tested every corner of the Jam functionality. I have compared the Jam execution debug traces (-d9) for our code build with and without this change (which picked up a few bugs) and am now satisfied that there is no behaviour change in our code build. We have been using a patched version of the Jam executable built from the master (not nextgen) branch with a highly customised version of the master Jam rules company-wide for several months now with no issues spotted.

Could you take a look at the changes and let me know:
* In principle is this would be something you would consider merging?
* What changes to the patch would be required for it to be suitable for merging?

(Apologies for the useless diffs on the generated jamgram.c, apparently my version of bison differs in some way from yours (possibly because I'm using the GNUWin32 version) despite having the same version number)

### Commit: New, more encapsulated, list implementation.
The actual data structures are now hidden from the users, and there is an
explicit difference between a list head and a list item. This reduces the
size of a list item to 2 pointers, but adds a 2 pointer overhead to the
list as a whole.

In addition the new list structures are optionally copy-on-write; the list
contains a reference count which is incremented whenever it is copied
(rather than actually creating a copy of the list). When a modification
is made to a list the reference count is checked. If the reference count
is greater than one then an actual copy of the list is created and the
modification is performed on the new copy, which is returned by the list
API call.

These two modifications significantly reduce jam memory usage for large
projects. In our code build the reduction was from approximately 900MB to
500MB.