Boost logo

Boost :

From: Reece Dunn (msclrhd_at_[hidden])
Date: 2004-12-01 17:36:37


Jody Hagins wrote:
> On Wed, 1 Dec 2004 18:17:37 +0000
> Stuart Dootson <stuart.dootson_at_[hidden]> wrote:
>
>>Jody - I ran your code on Windows 2000, compiled with VC++ 7.1 and got
>>similar results :
>
> Thanks for the info. Did you have to make any changes to the code?

I have also managed to get the tests working, but needed to make the
following changes (VC++ does not have <sys/time.h> by default):

===== [begin] =====

// workaround for mising <sys/time.h> on MS compilers...

#if defined(BOOST_MSVC)
#include <windows.h> // for timeval
#include <time.h>

#pragma comment( lib, "winmm.lib" )

int gettimeofday(struct timeval* tp, void* tzp)
{
    DWORD t;
    t = timeGetTime();
    tp->tv_sec = t / 1000;
    tp->tv_usec = t % 1000;
    return 0; // 0 indicates that the call succeeded.
}

inline void timersub( const timeval * tvp, const timeval * uvp, timeval
* vvp )
{
    vvp->tv_sec = tvp->tv_sec - uvp->tv_sec;
    vvp->tv_usec = tvp->tv_usec - uvp->tv_usec;
    if( vvp->tv_usec < 0 )
    {
       --vvp->tv_sec;
       vvp->tv_usec += 1000000;
    }
}
#else
#include <sys/time.h>
#endif

// ...end of missing <sys/time.h> workaround

===== [end] =====

Also included is a running comment on what the profiler is doing, so the
user can tell what is going on.

Have you thought about using boost::timer? I have also created a v2 jam
file to make it easier to build on different compilers.

It would be interesting to hook this into Boost.Test as this would make
it easier to capture the results and perform processing/analysis on the
data. Also, it would possibly be beneficial to have some sort of
Boost.Profiling library that sits on top of Boost.Test to make it easier
to do this.

Regards,
Reece

exe speed_test
  :
    speed_test.cpp /boost/signals//boost_signals/<link>static
  :
    <optimization>speed
  ;

stage bin : speed_test ;


#include "Connection.hpp"
#include "Signal.hpp"
#include "boost/signal.hpp"
#include "boost/bind.hpp"
#include <vector>
#include <cstdio>
#include <iostream>

// workaround for mising <sys/time.h> on MS compilers...

#if defined(BOOST_MSVC)
#include <windows.h> // for timeval
#include <time.h>

#pragma comment( lib, "winmm.lib" )

int gettimeofday(struct timeval* tp, void* tzp)
{
   DWORD t;
   t = timeGetTime();
   tp->tv_sec = t / 1000;
   tp->tv_usec = t % 1000;
   return 0; // 0 indicates that the call succeeded.
}

inline void timersub( const timeval * tvp, const timeval * uvp, timeval * vvp )
{
   vvp->tv_sec = tvp->tv_sec - uvp->tv_sec;
   vvp->tv_usec = tvp->tv_usec - uvp->tv_usec;
   if( vvp->tv_usec < 0 )
   {
      --vvp->tv_sec;
      vvp->tv_usec += 1000000;
   }
}
#else
#include <sys/time.h>
#endif

// ...end of missing <sys/time.h> workaround

struct X
{
  X(int x = 0) : x_(x) { }
  int x_;
};

void foo(X & x)
{
  x.x_ += 1234;
}

void blarg(X & x)
{
  x.x_ /= 71;
}

struct bar
{
  void operator()(X & x) { x.x_ *= 7; }
};

struct foobar
{
  void doit(X & x) { x.x_ += 7; }
};

struct timing
{
  size_t nslots_;
  size_t ncalls_;
  timeval start1_;
  timeval stop1_;
  timeval start2_;
  timeval stop2_;
};

timeval
operator-(
    timeval const & x,
    timeval const & y)
{
  timeval result;
  timersub(&x, &y, &result);
  return result;
}

double
as_double(
    timeval const & x)
{
  double result = x.tv_usec;
  result /= 1000000;
  result += x.tv_sec;
  return result;
}

int
main(
    int argc,
    char * argv[])
{
  try
  {
    std::vector<timing> timings;
    size_t num_slots[] =
    { 1, 10, 50, 100, 250, 500, 1000, 5000, 10000, 50000, 100000,
      500000, 0 };
    typedef lite::signals::Signal<void (X &)> Signal1;
    Signal1 signal1;
    typedef boost::signal<void (X &)> Signal2;
    Signal2 signal2;
    size_t totcalls[] = { 1000, 10000, 100000, 1000000, 0 };
    for (size_t * tc = totcalls; *tc > 0; ++tc)
    {
      size_t total_calls = *tc;
      std::cout << "profiling for " << total_calls << " total calls\n";
      for (size_t * ns = num_slots; *ns > 0 && *ns <= total_calls; ++ns)
      {
        std::cout << '.';
        size_t nslots = *ns;
        size_t niters = total_calls / nslots;

        signal1.disconnect_all_slots();
        signal1.connect(bar());
        foobar foobar1;
        signal1.connect(boost::bind(&foobar::doit, &foobar1, _1));

        signal2.disconnect_all_slots();
        signal2.connect(bar());
        foobar foobar2;
        signal2.connect(boost::bind(&foobar::doit, &foobar2, _1));

        std::vector<foobar> slots(nslots);
        for (size_t i = 0; i < slots.size(); ++i)
        {
          signal1.connect(boost::bind(&foobar::doit, &slots[i], _1));
          signal2.connect(boost::bind(&foobar::doit, &slots[i], _1));
        }

        X my_x(5);
        timing t;
        t.nslots_ = nslots;
        t.ncalls_ = niters;
        gettimeofday(&t.start1_, 0);
        for (size_t i = 0; i < niters; ++i)
        {
          signal1(my_x);
        }
        gettimeofday(&t.stop1_, 0);

        X bs_x(5);
        gettimeofday(&t.start2_, 0);
        for (size_t i = 0; i < niters; ++i)
        {
          signal2(bs_x);
        }
        gettimeofday(&t.stop2_, 0);

        timings.push_back(t);

        if (my_x.x_ != bs_x.x_)
        {
          std::cerr << "my_x(" << my_x.x_ << ") != bs_x("
              << bs_x.x_ << ")\n";
        }
      }
      std::cout << '\n';
    }
    size_t last_size = (size_t)-1;
    for (size_t i = 0; i < timings.size(); ++i)
    {
      if (last_size != timings[i].nslots_ * timings[i].ncalls_)
      {
        last_size = timings[i].nslots_ * timings[i].ncalls_;
        fprintf(stdout, "\n===== %u Total Calls =====\n", last_size);
        fprintf(stdout, "Num Slots Calls/Slot Boost Lite\n");
        fprintf(stdout, "--------- ---------- ------- -------\n");
      }
      fprintf(stdout, "%9u%14u%11.4f%10.4f\n",
          timings[i].nslots_,
          timings[i].ncalls_,
          as_double(timings[i].stop2_ - timings[i].start2_),
          as_double(timings[i].stop1_ - timings[i].start1_));
    }
    return 0;
  }
  catch (std::exception const & ex)
  {
    std::cerr << "exception: " << ex.what() << std::endl;
  }
  return 1;
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk