|Priority:||4 - Normal|
|Created by:||Jonathan Perkin|
|Reported by:||Jonathan Perkin|
|Assigned to:||Jonathan Perkin|
During the work to CTF convert pkgsrc,
libicudata.so exposed memory scaling issues with ctfconvert. It is a 29MB shared library containing 3,449 DIEs.
The current conversion process allocates memory as follows:
ctf_die_tis created for each DIE during the initialisation process.
ctf_die_tholds a DWARF handle open on the input file.
ctf_die_tincludes a new
ctf_file_tallocation, each of which
mmap()'s its own private copy of the CTF data, symtab, and strtab from the object.
ctf_file_tis allocated, again with its own
mmap'ed private copies, as the destination for the merge output.
With all these allocations, a 32-bit
ctfconvert process runs out of available memory while processing
While investigating solutions for this issue, we should bear in mind much larger objects than even
libicudata.so such as
libLLVM.so, which as of version 3.7 is 681MB and contains 43,149 DIEs. A fix should be able to handle files as large as that, even though we can't currently process it due to it being C++.
With the proposed patch the conversion process is changed to be as follows:
ctf_die_tfor every DIE up-front, we instead defer full initialisation to the main conversion process in
-bon the command line if necessary).
ctf_file_tis returned as the result.
ctf_file_tis added as an input to the next batch.
ctf_file_t, or a failure.
The default batchsize of 256 is based on a few constraints:
ctf_id_t's will be different compared to those generated by a previous
ctfconvert. If we're able to choose a batchsize which is larger than the number of DIEs in most objects then we will avoid changing
ctf_id_t's. Whilst mostly cosmetic, it's still nice to avoid differences if possible.
Timing a patched
libicudata.so resulted in the following build times:
|Time (seconds)||45||30||23||19||17||16||14||13||Failed |
Further analysis across pkgsrc may be helpful to determine whether we should consider changing the default.
For the record, due to the fact both tickets change similar code and are somewhat interdependent, this ticket must be rebased and checked after OS-6428 has been pushed. In particular, as this change pre-initialises
cdp->cd_elf the new check in OS-6428's
ctf_dwarf_free_dies becomes useless, and we might want a cleaner way to avoid trying to free dies that have already been freed.
Looking at this more, I think the way we're processing the symbol table is fine, but what we're doing with it isn't. We should probably try to convert it and ignore failures in those dies maybe.