This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC] Reduce code bloat caused by demangler (was: Don't access fpos_t.__state on uClibc w/o wchar support)


On Mon, Sep 29, 2003 at 09:03:37AM -0000, Pétur Runólfsson wrote:
> Bernardo Innocenti wrote:
> > Actually, there are bigger outstanding problems in 3.4: the new
> > demangler gets linked in as soon as the program uses exceptions,
> > bringing 200KB worth of code with it.

I don't understand this remark entirely.
Please note the following:

1) The bits/demangle.h is only included in libstdc++-v3/src/demangle.cc,
   and therefore only the size of demangle.o matters.

2) The size of demangle.o is 231332 bytes, but that is including
   debugging symbols.  After stripping it is 42684 bytes.

3) The symbols that are actually in that object file are mostly
   code that is really needed to demangle.  Code that is
   "dragged" in somehow from templated standard functions like
   std::string is:

std::vector<__gnu_cxx::demangler::qualifier<std::allocator<char> >, std::allocator<char> >::_M_insert_aux(__gnu_cxx::__normal_iterator<__gnu_cxx::demangler::qualifier<std::allocator<char> >*, std::vector<__gnu_cxx::demangler::qualifier<std::allocator<char> >, std::allocator<char> > >, __gnu_cxx::demangler::qualifier<std::allocator<char> > const&)

with size 1058 bytes

std::vector<__gnu_cxx::demangler::substitution_st, std::allocator<char> >::_M_insert_aux(__gnu_cxx::__normal_iterator<__gnu_cxx::demangler::substitution_st*, std::vector<__gnu_cxx::demangler::substitution_st, std::allocator<char> > >, __gnu_cxx::demangler::substitution_st const&)

with size 471 bytes

std::vector<int, std::allocator<char> >::_M_insert_aux(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<char> > >, int const&)

with size 342 bytes

__gnu_cxx::__normal_iterator<__gnu_cxx::demangler::qualifier<std::allocator<char> >*, std::vector<__gnu_cxx::demangler::qualifier<std::allocator<char> >, std::allocator<char> > > std::__uninitialized_copy_aux<__gnu_cxx::__normal_iterator<__gnu_cxx::demangler::qualifier<std::allocator<char> >*, std::vector<__gnu_cxx::demangler::qualifier<std::allocator<char> >, std::allocator<char> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::demangler::qualifier<std::allocator<char> >*, std::vector<__gnu_cxx::demangler::qualifier<std::allocator<char> >, std::allocator<char> > > >(__gnu_cxx::__normal_iterator<__gnu_cxx::demangler::qualifier<std::allocator<char> >*, std::vector<__gnu_cxx::demangler::qualifier<std::allocator<char> >, std::allocator<char> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::demangler::qualifier<std::allocator<char> >*, std::vector<__gnu_cxx::demangler::qualifier<std::allocator<char> >, std::allocator<char> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::demangler::qualifier<std::allocator<char> >*, std::vector<__gnu_cxx::demangler::qualifier<std::allocator<char> >, std::allocator<char> > >, __false_type)

with size 273 bytes

std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)

with size 198 bytes

std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)

with size 134 bytes
and

__gnu_cxx::__normal_iterator<__gnu_cxx::demangler::substitution_st*, std::vector<__gnu_cxx::demangler::substitution_st, std::allocator<char> > > std::__uninitialized_copy_aux<__gnu_cxx::__normal_iterator<__gnu_cxx::demangler::substitution_st*, std::vector<__gnu_cxx::demangler::substitution_st, std::allocator<char> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::demangler::substitution_st*, std::vector<__gnu_cxx::demangler::substitution_st, std::allocator<char> > > >(__gnu_cxx::__normal_iterator<__gnu_cxx::demangler::substitution_st*, std::vector<__gnu_cxx::demangler::substitution_st, std::allocator<char> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::demangler::substitution_st*, std::vector<__gnu_cxx::demangler::substitution_st, std::allocator<char> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::demangler::substitution_st*, std::vector<__gnu_cxx::demangler::substitution_st, std::allocator<char> > >, __false_type)

with size 94 bytes.

This list was obtained with:

objdump -t ./i686-pc-linux-gnu/libstdc++-v3/src/.libs/demangle.o | grep -v '\*UND\*' | sed -e 's/.* .*[[:space:]]\(000[^ ]*\) \(.*\)/\1 \2/' | sort | egrep -v '^(00000000|.*decode_|$)'

where the 'demangle_' symbols have been removed because they are the bulk
of true demangler functions:

objdump -t troep.o | grep -v '\*UND\*' | sed -e 's/.* .*[[:space:]]\(000[^ ]*\) \(.*\)/\1 \2/' | sort | grep decode_ | cut -d \  -f 2 | xargs c++filt
__gnu_cxx::demangler::session<std::allocator<char> >::decode_number(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_builtin_type(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_unscoped_name(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_decimal_integer(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_class_enum_type(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_name(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_call_offset(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_source_name(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_template_param(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, __gnu_cxx::demangler::qualifier_list<std::allocator<char> >*)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_unqualified_name(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_literal(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_local_name(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_operator_name(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_template_args(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_bare_function_type(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_nested_name(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_expression(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_substitution(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, __gnu_cxx::demangler::qualifier_list<std::allocator<char> >*)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_special_name(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
__gnu_cxx::demangler::qualifier_list<std::allocator<char> >::decode_qualifiers(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, bool)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_encoding(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char const*, int)
__gnu_cxx::demangler::session<std::allocator<char> >::decode_type_with_postfix(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, __gnu_cxx::demangler::qualifier_list<std::allocator<char> >*)

with a total size of 26307 bytes.


Now I suppose that you don't mean *shared* code, linked in from
libstdc++ (the Undefined symbols in demangle.o).  I surely also
hope that the size of the decode_* routines aren't that "huge"
because of dragged in code bloat because of *inlined* code from
<string> or <vector>.  But that is easy to test by recompiling
demangle.o with -O0; that gives me a total size of 15884 bytes
for the decode_* functions.

So, it seems to me that the 'code bloat' caused by the use of
<string> and <vector> (not <iostream> which is unrelated) is
about 12 kb, at most.  By rewriting the demangle to not use
<vector> and <string>, you need to add a little code, so lets
say you can reduce this with 2/3, with 8 kb; on a total of
42 kb that is a 20% possible reduction.

-- 
Carlo Wood <carlo@alinoe.com>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]