
2009/7/23 Sajjan Kalle
Profiling the project in question where the performance of boost::signals is one of the problems it seems two of the bottlenecks is slot_call_iterator::increment and slot_call_iterator::equal, and in those in particular find_if, which seems to be used for incrementing the iterator. I'll try to create a sample with timing on a bit more fragmented world like use case.
I'll throw signals2 in to the mix once I've built 1.39, in the meantime, here's a new variant which depends on only stl and boost. #include <iostream> #include "boost/signals.hpp" #include <vector> #include "boost/function.hpp" #include "boost/timer.hpp" #include <cstdlib> #include <algorithm> void foo( ) { } int main() { std::vector< boost::function< void ( void ) > > manualSignal; boost::signal< void ( void ) > boostSignalFragmented, boostSignalUnfragmented; typedef std::vector< boost::signals::connection > ConnectionVector; ConnectionVector connections; for( unsigned int i = 0; i < 10000; ++i ) { manualSignal.push_back( &foo ); boostSignalUnfragmented.connect( &foo ); } for( unsigned int i = 0; i < 100000; ++i ) { connections.push_back( boostSignalFragmented.connect( &foo ) ); } for( unsigned int i = 0; i < 90000; ++i ) { ConnectionVector::iterator index = connections.begin() + rand() % connections.size(); (*index).disconnect(); *index = *connections.rbegin(); connections.erase( connections.begin() + connections.size() - 1 ); } { boost::timer tm; for( unsigned int i = 0; i < 1000; ++i ) { for( unsigned int j = 0; j < 10000; ++j ) manualSignal[ i ]( ); } double elapsed = tm.elapsed(); std::cout << "vector variant: " << elapsed << std::endl; } { boost::timer tm; for( unsigned int i = 0; i < 1000; ++i ) { boostSignalUnfragmented( ); } double elapsed = tm.elapsed(); std::cout << "boost::signal Unfragmented variant: " << elapsed << std::endl; } { boost::timer tm; for( unsigned int i = 0; i < 1000; ++i ) { boostSignalFragmented( ); } double elapsed = tm.elapsed(); std::cout << "boost::signal Fragmented variant: " << elapsed << std::endl; } } This gives me ~0.032 on vector, ~1.80 on unfragmented boost::signal and lastly ~3.04 on fragmented boost::signal.