ctf: optimize type_id() and fix array dimension lookup
type_id() is the single hottest hot spot in dwarf2ctf, and had a number of
more or less severe performance problems:
- we were calling str_append() where str_appendn() would do, incurring more
realloc()s and strlen()s than necessary.
- when calling type_id() for types such as structure members that have the same
type-id representation as their reffed type, we were calling the hook
function even though it's already been called with that ID by our recursive
call on the reffed type. Some hook functions are quite expensive, so this
is probably a bad idea.
- we were calling realpath() once per call, although a very limited number of
input arguments are expected (one per translation unit) and the mapping from
input to output never changes. This is a perfect candidate for caching.
The latter in particular has a vast impact on dwarf2ctf performance, reducing it
by around 80% in my tests.
str_append() and str_appendn() themselves were suboptimal, taking the length of
their arguments more times than necessary and calling realloc() more often than
required (once per argument after the first in the case of str_appendn().)
Now that we are using str_appendn() more heavily, this becomes a significant
contributor to runtime, so this is fixed too.
Further, array dimension lookup (both in type_id() and in
assemble_ctf_array_dimension()) was broken due to looping past the first array
dimension without looking at it. This tended to cause false sharing of
actually-distinct types (all one-dimensional arrays were treated as the same
type regardless of dimension, and since C only has one-dimensional arrays...)
We also add some comments noting that the format of type_id() and the
by-hand-constructed type IDs in the alias fixup code must be kept aligned, since
the breakage when this is not so is quite obscure and hard to figure out.
Signed-off-by: Nick Alcock <nick.alcock@oracle.com>