I'm currently building an application for a lowish-spec ARM Cortex M4 in C++, using arm-none-eabi-g++
with stdlibc++ statically linked.
Some parts of the code are currently using std::stringstream
to construct a string for various purposes, and would be quite difficult to remove/refactor out of the codebase.
A fairly basic subset of the code with all stringstreams shimmed
(via a fakestream.h
header something like:
namespace blah {
class stringstream {
stringstream() {}
~stringstream() {}
std::string str() {
return "dummy";
}
template<typename T>
stringstream& operator<<(T val) {
return *this;
}
};
}
Along with invocations changed to:
#include "fakestream.h"
using blah::stringstream;
...
stringstream ss;
ss << ...
trims about 350kB of code from the application, vs using std::stringstream.
I realise that some amount of that code is indeed necessary, but when using bloaty to inspect the .elf generated, a lot of the space seems to be taken with functions such as:
6.5% 20.0Ki std::num_get<>::_M_extract_int<>()
3.7% 11.3Ki std::__cxx11::money_get<>::_M_extract<>()
2.9% 8.97Ki std::money_get<>::_M_extract<>()
2.7% 8.24Ki d_print_comp_inner
2.3% 6.97Ki _svfprintf_r
2.1% 6.42Ki _svfwprintf_r
2.0% 6.11Ki __strftime.isra.0
2.0% 6.09Ki __ssvfscanf_r
1.8% 5.61Ki __ssvfiscanf_r
1.8% 5.54Ki std::__cxx11::time_get<>::_M_extract_via_format()
1.5% 4.65Ki std::num_get<>::_M_extract_float()
1.4% 4.29Ki std::__cxx11::money_put<>::_M_insert<>()
1.4% 4.24Ki std::num_get<>::do_get()
1.4% 4.17Ki std::__moneypunct_cache<>::_M_cache()
1.3% 3.96Ki _strtod_l
1.3% 3.89Ki _vfiprintf_r
1.3% 3.87Ki std::time_get<>::_M_extract_via_format()
1.2% 3.81Ki _dtoa_r
1.2% 3.64Ki std::money_put<>::_M_insert<>()
1.1% 3.53Ki std::locale::_Impl::_Impl()
1.1% 3.28Ki std::__facet_shims::__moneypunct_fill_cache<>()
1.1% 3.27Ki _svfiprintf_r
1.0% 3.21Ki std::num_put<>::_M_insert_int<>()
0.8% 2.54Ki std::num_put<>::_M_insert_float<>()
0.7% 2.11Ki d_type
0.6% 1.94Ki std::__cxx11::time_get<>::_M_extract_name()
and I know for certain that I'm not using any money
or time
related classes/values for stringstream or anywhere else.
From what (little) I understand, there's potentially some locale-related indirection happening in ios
or ios_base
to allow these types to be formatted according to the active locale, but I have no need for any of that in this application.
Is it possible to somehow indicate that these features are unnecessary, and should be omitted from the final output?
Ideally it would be possible to just continue using std::stringstream
directly, but replacing it with a proxy or similar as above (but that actually delegates the necessary functionality for formatting basic integer types, strings, and a few custom object overloads).