
Hello, I have posted this already to the user list, maybe wrong forum... I have made now a small test and I don't know if I make something wrong. I have the following performance comparsion between a boost::function and a boost::signal. Okay, I know that boost::signal has a lot of more functionality and for that it is for sure slower than boost::function. But 100times slower? May be I do something wrong? On my pc I have for boost::function a runtime of 728ms and for boost::signals a runtime of 64128ms There is one slot used for signals. Can anyone give me some hint what I do wrong? my test program was: class TestBind { public: int counter; void OnEventReceived(char b) { counter++; } }; class TestSignal { public: int counter; void OnEventReceived(char b) { counter++; } }; int _tmain(int argc, _TCHAR* argv[]) { TestBind testBind; PerformanceCounter timer; boost::function<void (char)> f = boost::bind(&TestBind::OnEventReceived,&testBind,_1); for(int i = 0; i < 100000000; i++) { f('a'); } TestSignal testSignal; boost::signal<void (char)> sig; sig.connect(boost::bind(&TestSignal::OnEventReceived,&testSignal,_1));; for(int i = 0; i < 100000000; i++) { sig('a'); } } Best regards Hansjörg

I tested this and got the same result, about 100 times slower, strange.

I think it's not so much that boost::signal is slow, just that boost::function is really fast :) But you're comparison isn't very fair - at the least you should compare a vector<boost::function> to a boost::signal and see how the performance goes with 1, 2, 10 etc event handlers on each event. Then fix it up so you can disconnect an event handler during an event and see how the performance goes then (that's the mimimum you'd need for a usable construct). I remember reading some threads a while back about the slowness of boost::signal, and it's large array of features which are rarely used. Try and find them for some more info. Personally I'd be interested in a comparison between boost::signal and similar multi-event handler constructs in other languages, like C# events. Regards, Alex MDC

I have tested already also a vector<boost::function> against the boost::signal. The vector (able to disconnect during events) was about 2 times slower than boost::function. I have made now also tests with the new boost::signal library which should replace in the future this one. It is about 70times slower.... In the next days I want to make a comparsion with other eventhandlers.. I will post than the results. Best regards Hansjörg Alex MDC schrieb:
I think it's not so much that boost::signal is slow, just that boost::function is really fast :)
But you're comparison isn't very fair - at the least you should compare a vector<boost::function> to a boost::signal and see how the performance goes with 1, 2, 10 etc event handlers on each event. Then fix it up so you can disconnect an event handler during an event and see how the performance goes then (that's the mimimum you'd need for a usable construct).
I remember reading some threads a while back about the slowness of boost::signal, and it's large array of features which are rarely used. Try and find them for some more info.
Personally I'd be interested in a comparison between boost::signal and similar multi-event handler constructs in other languages, like C# events.
Regards, Alex MDC _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Wednesday 24 September 2008 01:30 am, Hansi wrote:
I have tested already also a vector<boost::function> against the boost::signal. The vector (able to disconnect during events) was about 2 times slower than boost::function. I have made now also tests with the new boost::signal library which should replace in the future this one. It is about 70times slower.... In the next days I want to make a comparsion with other eventhandlers.. I will post than the results.
When I compile your benchmark under linux with g++ 4.1.2 and -O3, I get: function 1.13 sec signals 16.28 sec thread_safe_signals 12.31 sec Maybe you need to try some different compiler switches? -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFI2jlN5vihyNWuA4URAoOBAJ9X8mWq5VZp8N8TG5xcmBaREemKSwCgkoXW bw5Ym0aCOpPudMoiXs8LARw= =F1dD -----END PGP SIGNATURE-----

I noticed that previous e-mails hadn't mentioned platform. It is really easy to get bitten by Microsoft's "secure STL" in later versions of VC even in optimized release builds.
You might try -D_SECURE_SCL=0 in your command line. See
http://einaros.blogspot.com/2007/02/iteration-techniques-put-on-benchmar k.html
Paul Rose

Paul Rose wrote:
I noticed that previous e-mails hadn't mentioned platform.
It is really easy to get bitten by Microsoft's "secure STL" in later versions of VC even in optimized release builds.
You might try -D_SECURE_SCL=0 in your command line. See
http://einaros.blogspot.com/2007/02/iteration-techniques-put-on-benchmar k.html
Thanks for the link, unfortunately he doesn't release the actual benchmark he used so I can't inspect it for validity. I assume its an oversight in his post that he is assigning each value to sum instead of accumulating each value in sum. I took a little shot at recreating part of his benchmark and testing a few more options. Here are the results of a run on VC8 SP1 with /O2 /Ob2 and _SECURE_SCL=0 using Boost trunk at revision 48954. Iterator accumulate took 0.39 seconds. Pointer accumulate took 0.407 seconds. Iterator for loop took 0.484 seconds. Pointer for loop took 0.391 seconds. Index for loop took 0.437 seconds. Index for_each took 0.531 seconds. Pointer for_each took 0.516 seconds. BOOST_FOREACH took 1.469 seconds. MSVC for each took 0.547 seconds. I don't necessarily claim my benchmark to be more less valid than his but I attached it here if anyone wants to try it themselves. Thanks, -- Michael Marcin #include <algorithm> #include <numeric> #include <cstdlib> #include <vector> #include <iostream> #include <boost/timer.hpp> #include <boost/foreach.hpp> void force_calculation( long long sum ) { static int count = 0; static volatile long long value; if( count && value != sum ) { std::cerr << "error in run " << count << std::endl; } value = sum; ++count; } struct sum_func { sum_func() : sum(0) {} long long sum; void operator()( unsigned i ) { sum += i; } }; int main() { std::vector<unsigned> data; std::srand(10); std::generate_n(std::back_inserter(data), 100000000, &std::rand); { boost::timer timer; long long sum = std::accumulate( data.begin(), data.end(), 0ll ); double elapsedtime = timer.elapsed(); std::cout << "Iterator accumulate took " << elapsedtime << " seconds." << std::endl; force_calculation(sum); } { boost::timer timer; unsigned* begin = &data.front(); long long sum = std::accumulate( begin, begin+data.size(), 0ll ); double elapsedtime = timer.elapsed(); std::cout << "Pointer accumulate took " << elapsedtime << " seconds." << std::endl; force_calculation(sum); } { boost::timer timer; long long sum = 0; for( std::vector<unsigned>::iterator it = data.begin(), iend = data.end(); it != iend; ++it ) { sum += *it; } double elapsedtime = timer.elapsed(); std::cout << "Iterator for loop took " << elapsedtime << " seconds." << std::endl; force_calculation(sum); } { boost::timer timer; long long sum = 0; unsigned* it = &data.front(); for( unsigned* iend = it+data.size(); it != iend; ++it ) { sum += *it; } double elapsedtime = timer.elapsed(); std::cout << "Pointer for loop took " << elapsedtime << " seconds." << std::endl; force_calculation(sum); } { boost::timer timer; long long sum = 0; for( std::size_t i = 0, size = data.size(); i != size; ++i ) { sum += data[i]; } double elapsedtime = timer.elapsed(); std::cout << "Index for loop took " << elapsedtime << " seconds." << std::endl; force_calculation(sum); } { boost::timer timer; long long sum = std::for_each( data.begin(), data.end(), sum_func() ).sum; double elapsedtime = timer.elapsed(); std::cout << "Index for_each took " << elapsedtime << " seconds." << std::endl; force_calculation(sum); } { boost::timer timer; unsigned* begin = &data.front(); long long sum = std::for_each( begin, begin+data.size(), sum_func() ).sum; double elapsedtime = timer.elapsed(); std::cout << "Pointer for_each took " << elapsedtime << " seconds." << std::endl; force_calculation(sum); } { boost::timer timer; long long sum = 0; BOOST_FOREACH( unsigned i, data ) { sum += i; } double elapsedtime = timer.elapsed(); std::cout << "BOOST_FOREACH took " << elapsedtime << " seconds." << std::endl; force_calculation(sum); } #ifdef _MSC_VER { boost::timer timer; long long sum = 0; for each( long long i in data ) { sum += i; } double elapsedtime = timer.elapsed(); std::cout << "MSVC for each took " << elapsedtime << " seconds." << std::endl; force_calculation(sum); } #endif } /* Sample results Iterator accumulate took 0.39 seconds. Pointer accumulate took 0.407 seconds. Iterator for loop took 0.484 seconds. Pointer for loop took 0.391 seconds. Index for loop took 0.437 seconds. Index for_each took 0.531 seconds. Pointer for_each took 0.516 seconds. BOOST_FOREACH took 1.469 seconds. MSVC for each took 0.547 seconds. */

Hi, I met a crash when define _SECURE_SCL=0 in release mode but in debug mode, it's ok, I'm using VC2005. in e:\libraries\boost_1_36_0\boost\signals\detail\named_slot_map.hpp void init_next_group() { while (group != last_group && group->second.empty()) ++group; if (group != last_group) { slot_ = group->second.begin(); // crash and debugger stops at here slot_assigned = true; } } //////// code below class TestSignal { public: int counter; void OnEventReceived(char b) { counter++; } }; int _tmain(int argc, _TCHAR* argv[]) { int const times = 100000; TestSignal testSignal; boost::signal<void (char)> sig; sig.connect(boost::bind(&TestSignal::OnEventReceived,&testSignal,_1)); for(int i = 0; i < times; i++) { sig('a'); } }

I think it is because you have build the library with SECURE_SCL=1 defined. It has not a compatible ABI! I think boost should also make by default this libraries and autolink against the right one... Best regards Hansjörg Wang Yun schrieb:
Hi, I met a crash when define _SECURE_SCL=0 in release mode but in debug mode, it's ok, I'm using VC2005.
in e:\libraries\boost_1_36_0\boost\signals\detail\named_slot_map.hpp
void init_next_group() { while (group != last_group && group->second.empty()) ++group; if (group != last_group) { slot_ = group->second.begin(); // crash and debugger stops at here slot_assigned = true; } }
//////// code below
class TestSignal { public:
int counter;
void OnEventReceived(char b) { counter++; } };
int _tmain(int argc, _TCHAR* argv[]) { int const times = 100000;
TestSignal testSignal; boost::signal<void (char)> sig;
sig.connect(boost::bind(&TestSignal::OnEventReceived,&testSignal,_1));
for(int i = 0; i < times; i++) { sig('a'); } }
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (6)
-
Alex MDC
-
Frank Mori Hess
-
Hansi
-
Michael Marcin
-
Paul Rose
-
Wang Yun