Strange result

  • Thread starter Alf P. Steinbach
  • Start date
A

Alf P. Steinbach

1. The program below should theoretically not run on my old & clunky machine,
since theoretically it allocates 2 to 4 GB. In reality, according to Windows
Task Manager, it allocates only some 20 MB tops. And runs fine, though slow...

2. With MSVC, and/or with 10.000 or fewer iterations and Op vector elements, the
inefficient reference strings are faster than std::string string, as expected.
On my machine, with g++ and 100.000 iterations, the opposite happens, and the
machine trashes on allocation and deallocation for the ref strings. I guess on
a modern machine that limit must be higher (yet another factor of 10?), but I'm
interested whether (1) this can be reproduced, and (2) whether anyone has any
explanation (at a guess something causes a lot of memory to be allocated, but it
doesn't show up in Task Manager).

Disclaimer: this is late for me, so thinking box not entirely sharp...


#include <boost/progress.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <ostream>
#include <vector>
#include <string>

class RefString
{
private:
boost::shared_ptr<std::string> myString;
public:
RefString( size_t n, char c )
: myString( new std::string( n, c ) )
{}
};

template< class String >
struct Op_
{
String s;
std::vector<String> v;

Op_(): s( 200, ' ' ), v( 100, s ) {}
void operator()() { v.insert( v.begin(), s ); }
};

template< class String >
void doTest()
{
using namespace std;
typedef Op_<String> Op;
vector<Op> op( 100000 );

boost::progress_timer timer;
for( size_t i = 0; i < op.size(); ++i )
{
op();
}
}

template< class String >
void doNamedTest()
{
std::cout << typeid(String).name() << ": ";
doTest<String>();
}

int main()
{
for( int i = 1; i <= 5; ++i )
{
std::cout << "TEST #" << i << ":" << std::endl;
std::cout << std::endl;

doNamedTest<RefString>();
doNamedTest<std::string>();
}
}


Cheers, & TIA.,

- Alf
 
P

Paul Brettschneider

Hi,
1. The program below should theoretically not run on my old & clunky
machine,
since theoretically it allocates 2 to 4 GB. In reality, according to
Windows
Task Manager, it allocates only some 20 MB tops. And runs fine, though
slow...

2. With MSVC, and/or with 10.000 or fewer iterations and Op vector
elements, the inefficient reference strings are faster than std::string
string, as expected. On my machine, with g++ and 100.000 iterations, the
opposite happens, and the
machine trashes on allocation and deallocation for the ref strings. I
guess on a modern machine that limit must be higher (yet another factor of
10?), but I'm interested whether (1) this can be reproduced, and (2)
whether anyone has any explanation (at a guess something causes a lot of
memory to be allocated, but it doesn't show up in Task Manager).

I think you're missing copy constructors, see below:
Disclaimer: this is late for me, so thinking box not entirely sharp...


#include <boost/progress.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <ostream>
#include <vector>
#include <string>

class RefString
{
private:
boost::shared_ptr<std::string> myString;
public:
RefString( size_t n, char c )
: myString( new std::string( n, c ) )
{}

// Missing copy constructor for non-PODs:
RefString(const RefString &s)
: myString(s.myString)
{ };
RefString &operator=(const RefString &s)
{ myString = s.myString; return *this; };
};

template< class String >
struct Op_
{
String s;
std::vector<String> v;

Op_(): s( 200, ' ' ), v( 100, s ) {}

// Missing copy constructor for non-PODs:
Op_(const Op_ &o)
: s(o.s), v(o.v) { };
Op_ &operator=(const Op_ &o)
{ s = o.s; v = o.v; return *this; };

void operator()() { v.insert( v.begin(), s ); }
};

template< class String >
void doTest()
{
using namespace std;
typedef Op_<String> Op;
vector<Op> op( 100000 );

boost::progress_timer timer;
for( size_t i = 0; i < op.size(); ++i )
{
op();
}
}

template< class String >
void doNamedTest()
{
std::cout << typeid(String).name() << ": ";
doTest<String>();
}

int main()
{
for( int i = 1; i <= 5; ++i )
{
std::cout << "TEST #" << i << ":" << std::endl;
std::cout << std::endl;

doNamedTest<RefString>();
doNamedTest<std::string>();
}
}


HTH,
Paul
 
A

Alf P. Steinbach

* Paul Brettschneider:
Hi,


I think you're missing copy constructors, see below:


// Missing copy constructor for non-PODs:
RefString(const RefString &s)
: myString(s.myString)
{ };
RefString &operator=(const RefString &s)
{ myString = s.myString; return *this; };

Nope, these are effectively the same as those generated automatically.

// Missing copy constructor for non-PODs:
Op_(const Op_ &o)
: s(o.s), v(o.v) { };
Op_ &operator=(const Op_ &o)
{ s = o.s; v = o.v; return *this; };

Ditto, no need to reproduce what the language provides automatically.

Except if there's some bug in g++...


[snip]
HTH,
Paul

Well, it could have. :) So thanks.


Cheers,

- Alf
 
E

Erik Wikström

1. The program below should theoretically not run on my old & clunky machine,
since theoretically it allocates 2 to 4 GB. In reality, according to Windows
Task Manager, it allocates only some 20 MB tops. And runs fine, though slow...

Task Manager is not the best tool to use when trying to determine how
much memory an app uses since there are a few different memory-types it
can show information about. I do not have boost installed but running it
with the boost-specific parts commented out the app ate about 1.7 GB
(out of 2 GB available) of RAM, but the total amount allocated was much
higher (the page-file grew with about 2 GB).
 
P

Paul Brettschneider

Alf said:
* Paul Brettschneider:

Nope, these are effectively the same as those generated automatically.

Ooops, sorry. At least *I* learned something: I used to believe that the
default copy constructor does a dumb memcpy().

But the result MSVC vs. g++ is to be expected, isn't it? g++ does use
refcounting for std::string internally, so adding another refcounting layer
on top of it should make the program slower/use more memory.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top