A benchmark of three C++ open source callback/signal/slot libraries -- CppCallback, libsigc++, and boost signal
This is a benchmark comparison of the speed performance of three C++ signal/slot/callback libraries,
CppCallback, libsigc++, and boost::signal2.
The source code of the benchmark is included in the CppCallback package.
| Test environment | |||||
| Hardware |
|
||||
| Software |
|
||||
| Functions | Compiler | Native call(C) | CppCallback (gcallback) |
LibSigC++ 2.2.8 |
Boost(D) Signal2 1.46.0 |
| Single slot (callback) benchmark, 100M (100,000,000) iterations. Time unit: milliseconds. | |||||
| Inline member function(E) | VC 9 | 46 | 781 | 766 | 3547 |
| GCC 4.5.2 | 47 | 1047 | 1000 | 1875 | |
| Non-inline member function | VC 9 | 391 | 766 | 781 | 3515 |
| GCC 4.5.2 | 453 | 1047 | 1000 | 1813 | |
| Virtual member function | VC 9 | 359 | 719 | 672 | 3579 |
| GCC 4.5.2 | 406 | 1031 | 969 | 1750 | |
| global function | VC 9 | 47 | 719 | 734 | 3578 |
| GCC 4.5.2 | 47 | 766 | 781 | 1562 | |
| functor object | VC 9 | 47 | 468 | 438 | 3156 |
| GCC 4.5.2 | 47 | 515 | 516 | 1547 | |
| Signal(F) (callback list) benchmark, 10M (10,000,000) iterations. Time unit: milliseconds. | |||||
| Invoke empty signal | VC 9 | N/A | 63 | 93 | 2000 |
| GCC 4.5.2 | N/A | 31 | 31 | 1703 | |
| Invoke signal with 5 slots | VC 9 | N/A | 641 | 2734 | 8797 |
| GCC 4.5.2 | N/A | 578 | 2547 | 7515 | |
| Invoke signal with 10 slots | VC 9 | N/A | 1109 | 3328 | 15203 |
| GCC 4.5.2 | N/A | 1094 | 3032 | 13063 | |
| Invoke signal with 50 slots | VC 9 | N/A | 6735 | 7875 | 64813 |
| GCC 4.5.2 | N/A | 5109 | 6703 | 54969 | |
Notes:
|
|||||
Some conclusions based on the data of CppCallback and libsigc++ that compiled with VC:
- For non-inline function, a slot, or a callback, has the same performance level as the native function call. Indeed a slot is only only 50% slower than a native call.
- The slot invoking performance is almost the same between CppCallback and libsigc++.
- A single slot invoking is about equivalent to invoking a normal function via two function pointers, or call a virtual function two times.
- Functor object has the best performance. So always prefer it when possible.
- The slot invoking performance is enough for most purpose usage. 100M iterations only need up to 1000ms, which is average 10ns for a single call. That means if there are 10K slot invoking, only 0.1ms is spent on the invoking itself. 0.1ms is nothing for most high performance games. And don't forget this is the performance on quite old hardware.
- The callback list (signal) performance of CppCallback, for a single slot (note it's 5 slots in a signal in the benchmark) is 50% slower than one single slot call without callback list. That means if there are 10K slot invoking, only 0.2ms is spent on the invoking itself. That also means we can heavily use callbacks (signals) in a 60 FPS game without worrying the impact of the callbacks.
- When there are few slots (callbacks) in a signal (callback list), CppCallback has better performance than libsigc++ because CppCallback has less setup overhead before dispatching. When there are a lot of slots, the performance difference between CppCallback and libsigc++ is trivial.
Posts: 3
Reply #3 on : Sun March 03, 2013, 20:24:52