Boost logo

Boost :

From: Powell, Gary (powellg_at_[hidden])
Date: 2002-06-13 18:43:34


So I did some testing. (finally)

  at worst case my timing was

.866 slow times
.741 fast times

and it turns out that using this template has the same time as the
traditional method and the special constructor method.

class number {
private:
    template<class T>
    class post_increment_class : public T {
          
          post_increment_class(T &rhs) : T (rhs)
          {
              // ++rhs; // slow
              // rhs.increment(); // slow (no return value)
              ++rhs.value; // fast! it's an int, we know what to do
now.
          }
   };

   void increment() { ++value; } // see whether not having a
return value as operator++() does helps.

public:
.....

};

So for gcc-3.1 -O3, it looks like it's not just the name return value
that messes up the optimization. And at least with the template
post_increment_class, you get the default copy constructor. But you have
to pre increment the value, and not call the operator++()!

I figure this sort of optimization is going to be of limited value as
the compilers seem to be getting better and better at it. Until then
your mileage may vary.

     -Gary-

BTW
  Anyone with access to KCC tried these?

-----Original Message-----
From: Brad King [mailto:brad.king_at_[hidden]]
Sent: Wednesday, June 12, 2002 12:58 PM
To: boost_at_[hidden]
Subject: Re: [boost] Postfix Increment Operator

| Why not just:
| number operator++(int)
| {
| return postfix_incrementer<number>(*this);
| }
| ?
> When testing this and the prev. version with gcc, I get a 2:3
> perfomance difference in favour of the traditional solution. Gcc 3.1
> -O3 ./postincr
> Number1: 6650000
> Number2: 9900000

I did some checking, and it looks like gcc 2.95 refuses to inline the
constructor-based implementation. However, gcc 3.0 will happily do so
when any optimization is used.

I just ran some tests using the original implementation I previously
posted. The test program is shown below. This is nothing formal, but
shows that even with the integer case, the new technique can beat the
traditional implementation (on this particular
platform/compiler/version/etc, at least).

It is interesting to note that the two implementations produce identical
performance when the trivial copy constructor is generated by the
compiler. The new implementation wins only when the copy constructor is
hand-implemented. I suppose this is because there are two copy
constructions with the traditional implementation, but the return value
optimization allows the new implementation to have only one copy
construction (actually 0 copy constructors and 1 special constructor).

-Brad

Several trials of each build produced equal results to two decimal
places.

 Build line used: : Time from "time ./a.out"
g++304 -O3 -DNEW_IMPL -DWITH_COPY : 1.10 seconds
g++304 -O3 -DWITH_COPY : 1.16 seconds
g++304 -O3 -DNEW_IMPL : 0.39 seconds
g++304 -O3 : 0.39 seconds

Test program:

class number {
  
#ifdef NEW_IMPL
  // Use "enum" instead of "class" to make it an integer type
  // that is easier to optimize away.
  enum postfix_increment {};
  number(number& r, postfix_increment): value(r.value) { ++r; } #endif
  
  int value;
public:
  number(): value(0) {}
  
#ifdef WITH_COPY
  number(const number& r): value(r.value) {}
#endif
  
  bool operator < (int v) const { return value < v; }
  number& operator++() { ++value; return *this; }
  
#ifdef NEW_IMPL
  const number operator++(int)
    { return number(*this, postfix_increment()); }
#else
  const number operator++(int)
    { number t(*this); ++(*this); return t; }
#endif
};

int main()
{
  number n;
  while(n++ < 0x0FFFFFFF);
  return 0;
}

_______________________________________________
Unsubscribe & other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost


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