views:

94

answers:

3

I am trying to figure out the memory consumption by my (C++) program using gprof. The program does not have a gui, it is entirely cli based.

Now, I am new to gprof, so I read a few tutorials, that taught me how to run gprof and spot time consumption.

However, I need to find out the memory consumption by a specific set of classes. Say there is a program with many types, A, ..., Z. Now I want to run my program and see how many accumulated memory was used by objects of the classes A, E, I, O, U (for example).

Have you guys any ideas or pointers how I could approach this task?
I am not exclusively considering gprof, I am open for any (fos) software that gets the job done.

I have, of course, searched both google and stackoverflow.com for any answer to this problem, but either I use the wrong keywords or there is nobody having this problem out there.

Edit: Suggestions about doing this manually are obvious. Of course I could code it into the application, but its about a great deal of classes I would rather not change. Also, I want to have the total memory consumption, so I cannot only count all created objects, because I would have to track the size of the object individually.

Edit2: I went with a modification of DeadMG's suggestion, which I only have to inherit from. It works pretty well, so, if anybody has as similar problem, try this.

class GlobalObjectCounter {
  public: 
    struct ClassInfo {
      unsigned long created;
      unsigned long destroyed;
      unsigned short size;
      ClassInfo() : created(0), destroyed(0), size(0) {}
      ClassInfo(unsigned short _size) : created(0), destroyed(0), size(_size) {}
      void fmt(std::ostream& os) {
        os << "total: " << (this->created) << " obj = " << (this->created*this->size) << "B; ";
        os << "current: " << (this->created-this->destroyed) << " obj = " << ((this->created-this->destroyed) * this->size) << "B; ";
      }
    };
  protected:
    static std::map<std::string,ClassInfo> classes;
    GlobalObjectCounter() {}
  public:
    static void dump(std::ostream& os) {
      for (std::map<std::string,ClassInfo>::iterator i = classes.begin(); i != classes.end(); ++i) {
        os << i->first << ": ";
        i->second.fmt(os);
        os << "\n";
      }
    }
};

template <class T> class ObjectCounter : public GlobalObjectCounter {
  private:
    static ClassInfo& classInfo() {
      static ClassInfo& classInfo = classes[std::string("") + typeid(T).name()];
      classInfo.size = sizeof(T);
      return classInfo;
    }
  public:
    ObjectCounter() {
      classInfo().created++;
    }
    ObjectCounter(ObjectCounter const& oc) {
      classInfo().created++;
    }
    ObjectCounter& operator=(const ObjectCounter&) {}
    ~ObjectCounter() {
      classInfo().destroyed++;
    }
};

The map lookup is a bit nasty, I admit it, but I didn't have the nerve to take care of storing the iterator for each class. The main issue was that you would have to explicitly initialise it for each counted class. If you know how to do that better, tell me how.

+3  A: 

I'm not aware of gprof even attempting to deal with questions of memory usage. The obvious alternative would be valgrind. If you only care about total memory usage, you could also do the job on your own (overload ::operator new and ::operator delete to track how much memory the program has requested). Of course, it's possible that you have some code that obtains memory by other means (e.g., directly calling something like sbrk), but that's fairly unusual. Those don't attempt to track statically allocated and/or stack usage though.

Jerry Coffin
Thanks for the hint to check out valgrind. It seems more concerned with memory than gprof.
bitmask
+2  A: 

Trivial.

template<typename T> class Counter {
    static int count = 0;
    Counter() { count++; }
    Counter(const Counter&) { count++; }
    Counter& operator=(const Counter&) {}
    ~Counter() { count--; }
};
class A : Counter<A> {
    static int GetConsumedBytes() {
        return sizeof(A) * count;
    }
};

If the use of A involves dynamic memory, then this solution can be improved on. You can also override the global operator new/delete.

DeadMG
That is an approach I would only employ if there is no other alternative, as I had to modify the source code. Also I'd like to avoid multiple inheritance, because we could have `class A: public E`.But thanks for the suggestion, I may build on it, if there is nothing else.
bitmask
Static inheritance won't be treated the same as regular inheritance, apart from anything else, because there's no actual virtual methods.
DeadMG
I believe I will have to go along with something like this, unless anybody has another idea.However, I wonder why you put `GetConsumedBytes` in `A` instead of `Counter`. This kind of redundancy is what bugs me most at the moment.
bitmask
A::GetConsumedBytes() is shorter than Counter<A>::GetConsumedBytes(). Because the inheritance is static, then it doesn't matter whatsoever.
DeadMG
+1  A: 

GlibC provides statistics on heap memory allocation. Take a look at mallinfo. You could probably obtain statistics at various points during execution and get some kind of idea of how much memory is being used.

doron
That tells me the total memory, but cannot give me more detailed information, about the respective classes.
bitmask