osstreams cause code bloat #168

Closed
opened 2020-08-18 20:12:07 +02:00 by muellerr · 1 comment
Owner

I recently added the framework to a cpp project which was relatively empty.
Code size was around 20-30kB . Then I compiled the framework and the code size grew by factor of 10 (even for the mission code with optimized code).

I dumped the sections with the linker flags -Wl,-Map=irgendeintollername.map
and found out something interesting

Here is an excerpt from .text (code)

 .text._ZNSt18__moneypunct_cacheIwLb0EE8_M_cacheERKSt6locale
                0x0000000020021464      0x1c8 c:/users/robin/appdata/roaming/xpacks/@xpack-dev-tools/arm-none-eabi-gcc/9.2.1-1.1.1/.content/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib\libstdc++_nano.a(wlocale-inst.o)
                0x0000000020021464                std::__moneypunct_cache<wchar_t, false>::_M_cache(std::locale const&)
 .text._ZNSt18__moneypunct_cacheIwLb1EE8_M_cacheERKSt6locale
                0x000000002002162c      0x1c8 c:/users/robin/appdata/roaming/xpacks/@xpack-dev-tools/arm-none-eabi-gcc/9.2.1-1.1.1/.content/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib\libstdc++_nano.a(wlocale-inst.o)
                0x000000002002162c                std::__moneypunct_cache<wchar_t, true>::_M_cache(std::locale const&)
 .text._ZNSt16__numpunct_cacheIwE8_M_cacheERKSt6locale
                0x00000000200217f4      0x180 c:/users/robin/appdata/roaming/xpacks/@xpack-dev-tools/arm-none-eabi-gcc/9.2.1-1.1.1/.content/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib\libstdc++_nano.a(wlocale-inst.o)
                0x00000000200217f4                std::__numpunct_cache<wchar_t>::_M_cache(std::locale const&)
 .text._ZNKSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb1EEES3_S3_RSt8ios_basewRKSbIwS2_SaIwEE
                0x0000000020021974      0x390 c:/users/robin/appdata/roaming/xpacks/@xpack-dev-tools/arm-none-eabi-gcc/9.2.1-1.1.1/.content/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib\libstdc++_nano.a(wlocale-inst.o)
                0x0000000020021974                std::ostreambuf_iterato

https://en.cppreference.com/w/cpp/locale/money_put hmm sounds nice but not too useful for a satellite :-)

There were countless of these sections related to osstream.
It also bloats .rodata (read-only data)

 .rodata._ZNSt10moneypunctIwLb1EE24_M_initialize_moneypunctEPiPKc.str4.4
                0x0000000020039918        0x0 c:/users/robin/appdata/roaming/xpacks/@xpack-dev-tools/arm-none-eabi-gcc/9.2.1-1.1.1/.content/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib\libstdc++_nano.a(monetary_members_cow.o)
                                          0x4 (size before relaxing)
 .rodata._ZTVSt18__moneypunct_cacheIcLb1EE
                0x0000000020039918       0x10 c:/users/robin/appdata/roaming/xpacks/@xpack-dev-tools/arm-none-eabi-gcc/9.2.1-1.1.1/.content/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib\libstdc++_nano.a(monetary_members_cow.o)
                0x0000000020039918                vtable for std::__moneypunct_cache<char, true>
 .rodata._ZTVSt18__moneypunct_cacheIcLb0EE
                0x0000000020039928       0x10 c:/users/robin/appdata/roaming/xpacks/@xpack-dev-tools/arm-none-eabi-gcc/9.2.1-1.1.1/.content/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib\libstdc++_nano.a(monetary_members_cow.o)
                0x0000000020039928                vtable for std::__moneypunct_cache<char, false>
 .rodata._ZTVSt18__moneypunct_cacheIwLb1EE

Now why is my code bloated even though I did not use the osstream?
The answer might be the following code

namespace sif {
extern ServiceInterfaceStream debug;
extern ServiceInterfaceStream info;
extern ServiceInterfaceStream warning;
extern ServiceInterfaceStream error;
}

which is necessary as a forward declaration for all ostream calls in the code.
The compiler propably compiles everything mandatory for osstreams to work in addition to the printf functions which are not so friendly to the code size (the reason many manufacturers supply smaller printf functions for example, of course there is not such a thing for ostreams)

I think if reducing the code size is a goal, the best way propably to offer an alternative to ostreams. This would propably mean a heavy use of preprocessor defines. I am actually curious what happens if we wrap all osstream usage in these defines and compile the framework without it..

Might try that out in the future. This can propably achieved with a python/sed script which looks for sif::info / sif::debug / sif::error / std::endl occurences and puts the preprocessor define above and below it

I recently added the framework to a cpp project which was relatively empty. Code size was around 20-30kB . Then I compiled the framework and the code size grew by factor of 10 (even for the mission code with optimized code). I dumped the sections with the linker flags `-Wl,-Map=irgendeintollername.map` and found out something interesting Here is an excerpt from `.text` (code) ```cpp .text._ZNSt18__moneypunct_cacheIwLb0EE8_M_cacheERKSt6locale 0x0000000020021464 0x1c8 c:/users/robin/appdata/roaming/xpacks/@xpack-dev-tools/arm-none-eabi-gcc/9.2.1-1.1.1/.content/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib\libstdc++_nano.a(wlocale-inst.o) 0x0000000020021464 std::__moneypunct_cache<wchar_t, false>::_M_cache(std::locale const&) .text._ZNSt18__moneypunct_cacheIwLb1EE8_M_cacheERKSt6locale 0x000000002002162c 0x1c8 c:/users/robin/appdata/roaming/xpacks/@xpack-dev-tools/arm-none-eabi-gcc/9.2.1-1.1.1/.content/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib\libstdc++_nano.a(wlocale-inst.o) 0x000000002002162c std::__moneypunct_cache<wchar_t, true>::_M_cache(std::locale const&) .text._ZNSt16__numpunct_cacheIwE8_M_cacheERKSt6locale 0x00000000200217f4 0x180 c:/users/robin/appdata/roaming/xpacks/@xpack-dev-tools/arm-none-eabi-gcc/9.2.1-1.1.1/.content/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib\libstdc++_nano.a(wlocale-inst.o) 0x00000000200217f4 std::__numpunct_cache<wchar_t>::_M_cache(std::locale const&) .text._ZNKSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb1EEES3_S3_RSt8ios_basewRKSbIwS2_SaIwEE 0x0000000020021974 0x390 c:/users/robin/appdata/roaming/xpacks/@xpack-dev-tools/arm-none-eabi-gcc/9.2.1-1.1.1/.content/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib\libstdc++_nano.a(wlocale-inst.o) 0x0000000020021974 std::ostreambuf_iterato ``` https://en.cppreference.com/w/cpp/locale/money_put hmm sounds nice but not too useful for a satellite :-) There were countless of these sections related to osstream. It also bloats .rodata (read-only data) ```cpp .rodata._ZNSt10moneypunctIwLb1EE24_M_initialize_moneypunctEPiPKc.str4.4 0x0000000020039918 0x0 c:/users/robin/appdata/roaming/xpacks/@xpack-dev-tools/arm-none-eabi-gcc/9.2.1-1.1.1/.content/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib\libstdc++_nano.a(monetary_members_cow.o) 0x4 (size before relaxing) .rodata._ZTVSt18__moneypunct_cacheIcLb1EE 0x0000000020039918 0x10 c:/users/robin/appdata/roaming/xpacks/@xpack-dev-tools/arm-none-eabi-gcc/9.2.1-1.1.1/.content/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib\libstdc++_nano.a(monetary_members_cow.o) 0x0000000020039918 vtable for std::__moneypunct_cache<char, true> .rodata._ZTVSt18__moneypunct_cacheIcLb0EE 0x0000000020039928 0x10 c:/users/robin/appdata/roaming/xpacks/@xpack-dev-tools/arm-none-eabi-gcc/9.2.1-1.1.1/.content/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib\libstdc++_nano.a(monetary_members_cow.o) 0x0000000020039928 vtable for std::__moneypunct_cache<char, false> .rodata._ZTVSt18__moneypunct_cacheIwLb1EE ``` Now why is my code bloated even though I did not use the osstream? The answer might be the following code ```cpp namespace sif { extern ServiceInterfaceStream debug; extern ServiceInterfaceStream info; extern ServiceInterfaceStream warning; extern ServiceInterfaceStream error; } ``` which is necessary as a forward declaration for all `ostream` calls in the code. The compiler propably compiles everything mandatory for osstreams to work in addition to the printf functions which are not so friendly to the code size (the reason many manufacturers supply smaller printf functions for example, of course there is not such a thing for ostreams) I think if reducing the code size is a goal, the best way propably to offer an alternative to ostreams. This would propably mean a heavy use of preprocessor defines. I am actually curious what happens if we wrap all osstream usage in these defines and compile the framework without it.. Might try that out in the future. This can propably achieved with a python/sed script which looks for sif::info / sif::debug / sif::error / std::endl occurences and puts the preprocessor define above and below it
muellerr added the
Documentation
question
labels 2020-08-18 20:13:31 +02:00
Author
Owner

I cab look into this after the state of the KSat fork and the main branch are (practically) equal because I already wrote a script to exclude ostream integration to test the difference. The first step is to write FSFW_INFO , FSFW_DEBUG, FSFW_WARNING and FSFW_ERROR print implementations.

I cab look into this after the state of the KSat fork and the main branch are (practically) equal because I already wrote a script to exclude ostream integration to test the difference. The first step is to write `FSFW_INFO` , `FSFW_DEBUG`, `FSFW_WARNING` and `FSFW_ERROR` print implementations.
Sign in to join this conversation.
No Milestone
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: fsfw/fsfw#168
No description provided.