1

I have an application that creates thousands of small objects (upwards of 500,000). There is an object factory that allocates these objects on the heap.

The problem that I'm running into is that when the object that holds these smaller object goes out of scope (Driver), 65% of the processing time is spent destroying these small objects.

map, entries, and fields hold pointers to an abstract base class, and each base class has many child classes.

The application architecture follows this format:

class Driver {

    boost::ptr_map<std::string, Class1-Base> map;
}

class Class1-Base {

    boost::ptr_vector<Class2-Base> entries;
}

class Class2-Base {
    boost::ptr_vector<Class3-Base> fields;
}

class Class3-Base {
    unsigned long value;
}

I have tried several different methods to increase the application's performance.

I first used a data structures with normal pointers and then explicitly deleted the objects in the class's destructor.

I then tried using data structures with boost::shared_ptr<> but I determined that reference counting caused a significant overhead and didn't provide any great benefit.

The solution I've come to now is to use boost::ptr_container so it takes ownership of the heap objects and will automatically destroy them when the container goes out of scope. With this solution, significant time is still spent destroying objects.

Is there anything I can do to prevent all this time destroying objects?

burtmacklin16
  • 715
  • 2
  • 13
  • 31
  • Do these objects own anything _other_ than other objects with the same lifetime, which all die at the same time? Do any of their destructors have deliberate side-effects you need to preserve? – Useless Sep 23 '14 at 14:20
  • @Useless No, all of the objects have the same life-time and there are no side-effects that need to be perseved. – burtmacklin16 Sep 23 '14 at 14:22
  • Did you measure those times with optimizations enabled? Also, 65% of _what_ time is spent in the destructors? – sehe Sep 23 '14 at 14:22
  • @sehe Sorry, I should have been more clear. I ran the profiler Very Sleepy, and 65% of the samples were taken during the Driver destructor. I don't believe I have any optimizations enabled. – burtmacklin16 Sep 23 '14 at 14:24
  • 2
    If you´re running debug mode of VS, that could be a problem. – deviantfan Sep 23 '14 at 14:27
  • In that case some kind of pool/arena allocator is what you need. Just switch everything back to raw pointers, make the destructors no-ops, and release the entire pool when the parent is destroyed. The Boost.Pool allocator suggested by @sehe is a good choice. – Useless Sep 23 '14 at 14:33

1 Answers1

2

I'd suggest using a memory pool to allocate the elements from, e.g. using Boost Pool library.

If you don't actually require destruction per element (i.e. the elements themselves have trivial destructors, although they, obviously cannot be POD since they have virtual members) you can avoid destructing the elements altogether, and release the entire pool in one fell swoop. This removes the dynamic allocation bottleneck from the equation.

Related:


As a simple measure (the low-hanging fruit) consider using a drop-in fast heap library, such as libtcmalloc from google-perftools.

Related:

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633