Boost logo

Boost :

From: Powell, Gary (powellg_at_[hidden])
Date: 2002-06-14 11:28:51


Ok Dave,
  Here's the new test run.

/// used a "::std::string"
powellg_at_powellg[260]>../gcc-3.1/bin/g++ -O3 -DSTRING post_increment.cpp
powellg_at_powellg[261]>time ./a.out
Done 16777215
./a.out 8.29s user 0.00s system 100% cpu 8.285 total
powellg_at_powellg[262]>../gcc-3.1/bin/g++ -O3 -DSTRING -DCONSTRUCTOR
post_increment.cpp
powellg_at_powellg[263]>time ./a.out
Done 16777215
./a.out 8.28s user 0.01s system 100% cpu 8.286 total
powellg_at_powellg[264]>../gcc-3.1/bin/g++ -O3 -DSTRING -DHELPER
post_increment.cpp
powellg_at_powellg[265]>time ./a.out
Done 16777215
./a.out 9.71s user 0.00s system 100% cpu 9.708 total

/// used a long
powellg_at_powellg[266]>../gcc-3.1/bin/g++ -O3 post_increment.cpp
powellg_at_powellg[267]>time ./a.out
Done 2147483647
./a.out 4.64s user 0.02s system 100% cpu 4.650 total
powellg_at_powellg[268]>../gcc-3.1/bin/g++ -O3 -DCONSTRUCTOR
post_increment.cpp
powellg_at_powellg[269]>time ./a.out
Done 2147483647
./a.out 4.66s user 0.00s system 100% cpu 4.651 total
powellg_at_powellg[270]>../gcc-3.1/bin/g++ -O3 -DHELPER post_increment.cpp
powellg_at_powellg[271]>time ./a.out
Done 2147483647
./a.out 4.65s user 0.00s system 100% cpu 4.648 total

As you can see it made no difference what I did for a "long". For the
string,
it was roughly 15% worse to use the template helper object. And it made
no
difference to use the special constructor.

One thing to note, to try and avoid having memory allocation take over
the
time, I did an assignment from the old to the new. To try and capture
whether
I was using named return type optimization, I did a construction with
the
result. (As opposed to having the compiler realize that the returned
result
wasn't used and removing it and the copy it made.)

Anyway this whole bit of test code makes me step back and ask just what
is it that
we are trying to do? Help the compilier know which local variable is
going to be the
returned value? Help the compilier know that it can ignore the local
copy if its not
used by the calling function? Is there a case to be made for yet another
keyword?

Again, this optimization has to be dependent on your compilier. So I'm
interested in
whether anyone else has any better/different results.

       -gary-

BTW
  in the "long" case, I get better results if I don't call operator++(),
and instead
do the ++rhs.value locally. So I expect if there was some way to get the
compilier to
do another pass at the generated code it would be faster.

--------------------------------------------------------
Test code

#include <iostream>
#include <string>
#include <limits>

class number {
private:

    template<class T>
    struct helper_class : public T
    {
        helper_class(T &rhs): T(rhs)
        {
            ++rhs;
            //rhs.increment();
        }
    };

    enum helper_enum { FOO };
    number(number &lhs, helper_enum)
    : value(lhs.value)
    { ++lhs; }

    void increment()
    {
        value += '1';
    }

#if defined (STRING)
::std::string value;
#else
long value;
#endif

public:
#if defined (STRING)
   explicit number( ::std::string const &rhs = "")
       : value(rhs) {}
#else
   explicit number(int rhs = 0)
       : value(rhs) {}
#endif

  number &operator++()
#if defined (STRING)
      { value += '1'; return *this; }
#else
      { ++value; return *this; }
#endif

  #if defined(HELPER)
  number const operator++(int)
      { return helper_class<number>(*this); }
  #elif defined (CONSTRUCTOR)
  number const operator++(int)
      { return number(*this, FOO); }
  #else
  number const operator++(int)
      { number old(*this);
        ++*this;
        return old; }
  #endif

  friend
  ::std::ostream & operator<<(::std::ostream &os, number const &rhs)
  {
    os << rhs.value;
    return os;
  }

};

int main()
{
    using ::std::cout;
    using ::std::endl;

    number x;
    int y(0);

#if defined (STRING)
   while (y < 0xFFFFFF ) { number z(x++); x = z; ++y;}
#else
   while (y < ::std::numeric_limits<long>::max() ) { number z(x++); x =
z; ++y;}
#endif

   cout << "Done " << y << endl;
   return 0;
}

-----Original Message-----
From: David Abrahams [mailto:david.abrahams_at_[hidden]]
Sent: Thursday, June 13, 2002 4:56 PM
To: boost_at_[hidden]
Subject: Re: [boost] Postfix Increment Operator

----- Original Message -----
From: "Powell, Gary" <powellg_at_[hidden]>

> 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.

I'd be very interested in knowing what happens when the value member is
a string. Have ++ add a character, for example. This would simulate
bignum.

-Dave


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