| 1 | #include "performance.h" |
|---|
| 2 | |
|---|
| 3 | #include <osg/Timer> |
|---|
| 4 | #include <iostream> |
|---|
| 5 | |
|---|
| 6 | #include <osg/NodeVisitor> |
|---|
| 7 | #include <osg/ref_ptr> |
|---|
| 8 | #include <osg/MatrixTransform> |
|---|
| 9 | #include <osg/Group> |
|---|
| 10 | |
|---|
| 11 | struct Benchmark |
|---|
| 12 | { |
|---|
| 13 | |
|---|
| 14 | Benchmark() |
|---|
| 15 | { |
|---|
| 16 | calibrate(); |
|---|
| 17 | |
|---|
| 18 | _beginTick = _timer.tick(); |
|---|
| 19 | _endTick = _timer.tick(); |
|---|
| 20 | } |
|---|
| 21 | |
|---|
| 22 | void calibrate(unsigned int numLoops = 100000) |
|---|
| 23 | { |
|---|
| 24 | osg::Timer_t beginTick = _timer.tick(); |
|---|
| 25 | for(unsigned int i=0;i<numLoops;++i) |
|---|
| 26 | { |
|---|
| 27 | begin(); |
|---|
| 28 | end(); |
|---|
| 29 | } |
|---|
| 30 | osg::Timer_t endTick = _timer.tick(); |
|---|
| 31 | _averageDelay = _timer.delta_s(beginTick,endTick)/(double)numLoops; |
|---|
| 32 | } |
|---|
| 33 | |
|---|
| 34 | inline void begin() |
|---|
| 35 | { |
|---|
| 36 | _beginTick = _timer.tick(); |
|---|
| 37 | } |
|---|
| 38 | |
|---|
| 39 | inline void end() |
|---|
| 40 | { |
|---|
| 41 | _endTick = _timer.tick(); |
|---|
| 42 | } |
|---|
| 43 | |
|---|
| 44 | inline double time() |
|---|
| 45 | { |
|---|
| 46 | double t = _timer.delta_s(_beginTick,_endTick) - _averageDelay; |
|---|
| 47 | return t<0.0 ? 0.0 : t; |
|---|
| 48 | } |
|---|
| 49 | |
|---|
| 50 | inline void output(const char* str, double numIterations=1.0) |
|---|
| 51 | { |
|---|
| 52 | std::cout<<str<<"\t"; |
|---|
| 53 | double s = time()/numIterations; |
|---|
| 54 | if (s>=1.0) std::cout<<s<<" s"<<std::endl; |
|---|
| 55 | else if (s>=0.001) std::cout<<s*1000.0<<" ms (10 ^ -3)"<<std::endl; |
|---|
| 56 | else if (s>=0.000001) std::cout<<s*1000000.0<<" ns (10 ^ -6)"<<std::endl; |
|---|
| 57 | else std::cout<<s*1000000000.0<<" ps (10 ^ -9)"<<std::endl; |
|---|
| 58 | } |
|---|
| 59 | |
|---|
| 60 | osg::Timer _timer; |
|---|
| 61 | osg::Timer_t _beginTick; |
|---|
| 62 | osg::Timer_t _endTick; |
|---|
| 63 | double _averageDelay; |
|---|
| 64 | }; |
|---|
| 65 | |
|---|
| 66 | #define RUN(A,B,D) { A.begin(); for(unsigned int i=0;i<D;++i) B; A.end(); A.output(#B,D); } |
|---|
| 67 | |
|---|
| 68 | |
|---|
| 69 | static int v = 0; |
|---|
| 70 | #define OPERATION { v=v+1; } |
|---|
| 71 | |
|---|
| 72 | inline void inline_increment() { OPERATION } |
|---|
| 73 | void function_increment() { OPERATION } |
|---|
| 74 | |
|---|
| 75 | typedef void ( * IncrementProc) (); |
|---|
| 76 | IncrementProc s_functionIncrement = &function_increment; |
|---|
| 77 | inline void functionPointer_increment() { s_functionIncrement(); } |
|---|
| 78 | |
|---|
| 79 | |
|---|
| 80 | struct InlineMethod; |
|---|
| 81 | struct Method; |
|---|
| 82 | struct VirtualMethod; |
|---|
| 83 | struct VirtualMethod2; |
|---|
| 84 | |
|---|
| 85 | struct Visitor |
|---|
| 86 | { |
|---|
| 87 | virtual void apply(InlineMethod& m); |
|---|
| 88 | virtual void apply(Method& m); |
|---|
| 89 | virtual void apply(VirtualMethod& m); |
|---|
| 90 | virtual void apply(VirtualMethod2& m); |
|---|
| 91 | virtual ~Visitor() {} |
|---|
| 92 | }; |
|---|
| 93 | |
|---|
| 94 | |
|---|
| 95 | struct InlineMethod |
|---|
| 96 | { |
|---|
| 97 | void method() { OPERATION } |
|---|
| 98 | virtual void accept(Visitor& visitor) { visitor.apply(*this); } |
|---|
| 99 | virtual ~InlineMethod() {} |
|---|
| 100 | }; |
|---|
| 101 | |
|---|
| 102 | struct Method |
|---|
| 103 | { |
|---|
| 104 | virtual void accept(Visitor& visitor) { visitor.apply(*this); } |
|---|
| 105 | void method(); |
|---|
| 106 | virtual ~Method() {} |
|---|
| 107 | }; |
|---|
| 108 | |
|---|
| 109 | void Method::method() { OPERATION } |
|---|
| 110 | |
|---|
| 111 | struct VirtualMethod |
|---|
| 112 | { |
|---|
| 113 | virtual void accept(Visitor& visitor) { visitor.apply(*this); } |
|---|
| 114 | virtual void method(); |
|---|
| 115 | virtual ~VirtualMethod() {} |
|---|
| 116 | }; |
|---|
| 117 | |
|---|
| 118 | void VirtualMethod::method() { OPERATION } |
|---|
| 119 | |
|---|
| 120 | struct VirtualMethod2 : public VirtualMethod |
|---|
| 121 | { |
|---|
| 122 | VirtualMethod2() { } |
|---|
| 123 | |
|---|
| 124 | virtual void accept(Visitor& visitor) { visitor.apply(*this); } |
|---|
| 125 | virtual void method(); |
|---|
| 126 | virtual ~VirtualMethod2() { } |
|---|
| 127 | |
|---|
| 128 | char a[100]; |
|---|
| 129 | }; |
|---|
| 130 | |
|---|
| 131 | void VirtualMethod2::method() { OPERATION } |
|---|
| 132 | |
|---|
| 133 | void Visitor::apply(Method& m) { m.method(); } |
|---|
| 134 | void Visitor::apply(VirtualMethod& m) { m.method(); } |
|---|
| 135 | void Visitor::apply(InlineMethod& m) { m.method(); } |
|---|
| 136 | void Visitor::apply(VirtualMethod2& m) { m.method(); } |
|---|
| 137 | |
|---|
| 138 | struct CustomVisitor |
|---|
| 139 | { |
|---|
| 140 | virtual void apply(InlineMethod& m) { m.method(); } |
|---|
| 141 | virtual void apply(Method& m) { m.method(); } |
|---|
| 142 | virtual void apply(VirtualMethod& m) { m.method(); } |
|---|
| 143 | virtual void apply(VirtualMethod2& m) { m.method(); } |
|---|
| 144 | virtual ~CustomVisitor() {} |
|---|
| 145 | }; |
|---|
| 146 | |
|---|
| 147 | class CustomNodeVisitor : public osg::NodeVisitor |
|---|
| 148 | { |
|---|
| 149 | public: |
|---|
| 150 | void apply(osg::Node&) { } |
|---|
| 151 | void apply(osg::Group&) { } |
|---|
| 152 | void apply(osg::Transform&) { } |
|---|
| 153 | }; |
|---|
| 154 | |
|---|
| 155 | |
|---|
| 156 | void runPerformanceTests() |
|---|
| 157 | { |
|---|
| 158 | Benchmark benchmark; |
|---|
| 159 | |
|---|
| 160 | unsigned int iterations = 10000000; |
|---|
| 161 | |
|---|
| 162 | RUN(benchmark, {} , iterations) |
|---|
| 163 | |
|---|
| 164 | v = 0; |
|---|
| 165 | RUN(benchmark, OPERATION , iterations) |
|---|
| 166 | RUN(benchmark, functionPointer_increment() , iterations) |
|---|
| 167 | RUN(benchmark, inline_increment() , iterations) |
|---|
| 168 | RUN(benchmark, function_increment() , iterations) |
|---|
| 169 | |
|---|
| 170 | VirtualMethod2 m4; |
|---|
| 171 | RUN(benchmark, m4.method() , iterations) |
|---|
| 172 | |
|---|
| 173 | InlineMethod m1; |
|---|
| 174 | RUN(benchmark, m1.method() , iterations) |
|---|
| 175 | |
|---|
| 176 | Method m2; |
|---|
| 177 | RUN(benchmark, m2.method() , iterations) |
|---|
| 178 | |
|---|
| 179 | VirtualMethod m3; |
|---|
| 180 | RUN(benchmark, m3.method() , iterations) |
|---|
| 181 | RUN(benchmark, m3.method() , iterations) |
|---|
| 182 | |
|---|
| 183 | Visitor visitor; |
|---|
| 184 | RUN(benchmark, m4.accept(visitor), iterations) |
|---|
| 185 | RUN(benchmark, m1.accept(visitor), iterations) |
|---|
| 186 | RUN(benchmark, m2.accept(visitor), iterations) |
|---|
| 187 | RUN(benchmark, m3.accept(visitor), iterations) |
|---|
| 188 | RUN(benchmark, m4.accept(visitor), iterations) |
|---|
| 189 | |
|---|
| 190 | VirtualMethod* vm4 = &m4; |
|---|
| 191 | |
|---|
| 192 | RUN(benchmark, (dynamic_cast<VirtualMethod2*>(vm4))->method(), iterations) |
|---|
| 193 | RUN(benchmark, (static_cast<VirtualMethod2*>(vm4))->method(), iterations) |
|---|
| 194 | RUN(benchmark, { VirtualMethod mm; mm.method(); }, iterations) |
|---|
| 195 | RUN(benchmark, { VirtualMethod2 mm; mm.method(); }, iterations) |
|---|
| 196 | |
|---|
| 197 | |
|---|
| 198 | osg::ref_ptr<osg::Group> group = new osg::Group; |
|---|
| 199 | osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform; |
|---|
| 200 | osg::Node* m = mt.get(); |
|---|
| 201 | CustomNodeVisitor cnv; |
|---|
| 202 | RUN(benchmark, { osg::MatrixTransform* mtl = dynamic_cast<osg::MatrixTransform*>(m); if (mtl) cnv.apply(*mtl); }, 1000) |
|---|
| 203 | RUN(benchmark, { m->accept(cnv); }, 10000) |
|---|
| 204 | |
|---|
| 205 | } |
|---|