diff --git a/doc/api/examples/aggregation/README b/doc/api/examples/aggregation/README new file mode 100644 index 0000000000000000000000000000000000000000..8e67b605543640c2db33da5ba748edb924201909 --- /dev/null +++ b/doc/api/examples/aggregation/README @@ -0,0 +1,21 @@ + +Running test.sh tests several replacement patterns for a typical case +of polymorphism, and creates some statistics of the output. + +The 'critical' case is where the implementation is only instantiated +from a single location. + +'Symbols' refers to the number of additional symbols created by the +pattern (relevant for relocation on application startup and debugger +performance) + +'Size' refers to the size of the '.text' section, i.e. the 'generated +code'. + +'Debug' is the size of the .debug_info section in the binary. + + +Note that the numbers are not directly comparable. As the 'Slim' +versions push code from the implementation to the user side, the +ratio will be "better" when the the implementation is instantiated +from more than one place. diff --git a/doc/api/examples/aggregation/output.txt b/doc/api/examples/aggregation/output.txt new file mode 100644 index 0000000000000000000000000000000000000000..6b75ec188d5dcc67a382962a49b65014c66786d8 --- /dev/null +++ b/doc/api/examples/aggregation/output.txt @@ -0,0 +1,35 @@ +Interface/Implementation (out of line) + +Symbols: 13 +Size: 2388 +Debug: 4541 + + +Interface/Implementation (non-virtual) + +Symbols: 13 +Size: 2388 +Debug: 4431 + + +Interface/Implementation (inline) + +Symbols: 12 +Size: 2643 +Debug: 4402 + + +Merged + +Symbols: 7 +Size: 2447 +Debug: 4342 + + +Slimmest possible + +Symbols: 0 +Size: 1971 +Debug: 4246 + + diff --git a/doc/api/examples/aggregation/test.sh b/doc/api/examples/aggregation/test.sh new file mode 100755 index 0000000000000000000000000000000000000000..5232ce8629ac1489c833bdfb42599742d264c9fe --- /dev/null +++ b/doc/api/examples/aggregation/test.sh @@ -0,0 +1,196 @@ +#!/bin/bash + +export CXX="g++ -O3 -g " + +function stat() { + echo -e "" + echo -e "Symbols: $(nm $@ | grep ' [TVW] ' | grep _Z | grep -v "_ZNSs" | wc -l)" + echo -e "Size: $(size -d -B $@ | tail -1 | cut -c1-10)" + echo -e "Debug: $(echo "ibase=16;"$(readelf -S $@ | grep debug_info | cut -c50-56 | tr a-f A-F) | bc)" + echo -e "" + echo -e "" +# echo -e "Symbols: $(nm "$@" | grep ' [TUVW] '| grep _Z )" +} + + +function test_1() { + +echo "Interface/Implementation (out of line)" + +cat > interface_1.h <<EOF +#include <string> +struct Interface { virtual ~Interface() {} virtual std::string func() const = 0; }; +EOF + +cat > implementation_1.h <<EOF +#include "interface_1.h" +struct Implementation : Interface { std::string func() const; }; +EOF + +cat > implementation_1.cpp <<EOF +#include "implementation_1.h" +std::string Implementation::func() const { return "Test1"; } +EOF + +cat > main_1.cpp <<EOF +#include "implementation_1.h" +int main() { Interface *x = new Implementation(); return x->func().size(); } +EOF + +$CXX implementation_1.cpp main_1.cpp -o test_1 +stat test_1 + +} + + +function test_2() { + +echo "Interface/Implementation (non-virtual)" + +cat > interface_2.h <<EOF +#include <string> +struct Interface { virtual ~Interface() {} virtual std::string func() const = 0; }; +EOF + +cat > implementation_2.h <<EOF +#include "interface_2.h" +struct Implementation : Interface { + ~Implementation() {} std::string func() const { return "Test2"; } }; +EOF + +cat > main_2.cpp <<EOF +#include "implementation_2.h" +int main() { Interface *x = new Implementation(); return x->func().size(); } +EOF + +$CXX main_2.cpp -o test_2 +stat test_2 + +} + + +function test_3() { + +echo "Interface/Implementation (inline)" + +cat > interface_3.h <<EOF +#include <string> +struct Interface +{ + virtual ~Interface() {} + std::string func() const { return m_data; } + std::string m_data; +}; +EOF + +cat > implementation_3.h <<EOF +#include "interface_3.h" +struct Implementation : Interface { + Implementation() { m_data = "Test3"; } +}; +EOF + +cat > main_3.cpp <<EOF +#include "implementation_3.h" +int main() { Interface *x = new Implementation(); return x->func().size(); } +EOF + +$CXX main_3.cpp -o test_3 +stat test_3 + +} + + +function test_4() { + +echo "Merged" + +cat > interface_4.h <<EOF +#include <string> +struct Interface +{ + virtual ~Interface() {} + std::string func() const { return m_data; } + void setData(const std::string &data) { m_data = data; } +private: + std::string m_data; +}; +EOF + +cat > implementation_4.h <<EOF +#include "interface_4.h" +void setupImplementation(Interface *i) { i->setData("Test4"); } +EOF + +cat > main_4.cpp <<EOF +#include "implementation_4.h" +int main() { Interface *x = new Interface(); setupImplementation(x); return x->func().size(); } +EOF + +$CXX main_4.cpp -o test_4 +stat test_4 + +} + + +function test_5() { + +echo "Slimmest possible" + +cat > interface_5.h <<EOF +#include <string> +struct Interface +{ + std::string func() const { return m_data; } + void setData(const std::string &data) { m_data = data; } +private: + std::string m_data; +}; +EOF + +cat > main_5.cpp <<EOF +#include "interface_5.h" +int main() { Interface *x = new Interface(); x->setData("Test4"); return x->func().size(); } +EOF + +$CXX main_5.cpp -o test_5 +stat test_5 + +} + + +function test_6() { + +echo "Constructor" + +cat > interface_6.h <<EOF +#include <string> +struct Interface +{ + explicit Interface(const std::string &data) : m_data(data) {} + std::string func() const { return m_data; } +private: + const std::string m_data; +}; +EOF + +cat > main_6.cpp <<EOF +#include "interface_6.h" +int main() { Interface *x = new Interface("Test4"); return x->func().size(); } +EOF + +$CXX main_6.cpp -o test_6 +stat test_6 + +} + +function main() { + test_1 + test_2 + test_3 + test_4 + test_5 + #test_6 +} + +main