L.S.
I was happy to notice that the memory leak in the file-io is fixed, after I succesfully compiled and installed gpc version 20020910, based on gcc-2.95.2 19991024 (release).
However, currently I am compiling a FE program using the automake option, and it turns out that the build is recursively. Creating a log file (using gpc -v and editing a bit) yields the following result:
1 /tmp/ccAHxoUT.i 2 ch_const.p 3 general.p 4 NODES/nodes.p 5 MATERIAL/constitution.p 6 NODES/nodes.p 7 MATERIAL/constitution.p 8 ELEMENTS/elements.p 9 NODES/nodes.p 10 MATERIAL/constitution.p 11 NODES/nodes.p 12 MATERIAL/constitution.p 13 ELEMENTS/elements.p 14 global.p 15 NODES/nodes.p 16 NODES/SCAL/scalnode.p ...
The main program uses the units ch_const, general, initnode, ... where initnode uses nodes, constitution, elements, ... whele elements uses nodes, constitution, ... Looking at the log file, NODES/nodes.p is compiled multiple times due to the recursive nature of automake.
That this really is a problem can be seen from the fact that, according to top, the size of gpc1 is 611M, and running for 2920min, whereas a previous version of gpc only took minutes. However, that previous version creates a memory leak. More figures on the size of the problem: gpcpp has been invoked more than 250000 times, resulting in 213 units that are compiled.
The source of the problem is the recursion. Take the following worst case scenario: unit 1. unit 2 uses unit 1 unit 3 uses unit 1,2 unit 4 uses unit 1,2,3 unit 5 uses unit 1,2,3,4 .... the program uses unit 1....n
Compilation takes 1 step for unit 1, 2 for unit 2 (namely 1 for unit 1 and 1 for unit 2), 4 for unit 3 ( namely 1 for unit 1, 2 for unit 2,1 for unit 3), 8 for unit 4 (namly 1 for unit 1, 2 for unit 2, 4 for unit 3 and 1 for unit 4)
By induction, the program requires 2^n steps. Now 250000 is negligible compared to 2^(more than 213), so my whining on the compilation effort should be taken with a bit of salt. The situation could be far worse ;-)
This recursion scenario makes sure that the object files of the units are always based on the latest versions of the source.
Anyway, I would like to suggest the following method (which I hope is easy to implement, and I hope I did not overlook some problem scenario) Basically, it boiles down to pruning the recursive branches that are done earlier.
Create an empty list of up-to-date object files for each unit that is required do: procedure create_object_file * verify that the units it requires are on the list, if not, call create_object_file for that unit * compile the unit.
In this case, compilation of unit 5 takes considerable less steps: 1 for unit 1, 2 for unit 2 (1 to see unit 1 is up to date, 1 for unit 2), 3 for unit 3 (2 to see unit 1 and 2 are up to date, 1 for unit 3), 4 for unit 4 (3 to see unit 1,2 and 3 are up to date, 1 for unit 4), and 1 for unit 5. This requires 5 unit compilations, and 6 `up to date'-checks in the list. Thus n(n+1)/2 + 1 steps are required to compile the program, of which n+1 compilations and n(n-1)/2 `up to date' checks. The savings are in the fact that an `up to date' check of, e.g., unit 4 does not require the `up to date' checks of its dependencies, since it is already in the `up to date' list after its compilation.
Based on these considerations, only 22792 steps would be required, whereas now more than 250000 gpcpp invocations occurred.
Regretfully, I do not have the time to start hacking around in gpc myself, so I hope you have some use for these comments. For the time being, I just compile the units in exactly the sequence as they occur in the logfile, and build without automake ;-)
Regards,
Marten Jan de Ruiter Structural Optmimzation and Computational Mechanics group, Delft University of Technology