Как профилировать потребление памяти набором классов C++?


Я пытаюсь вычислить потребление памяти моей программой (C++) с помощью gprof. Программа не имеет графического интерфейса, она полностью основана на cli.

Теперь я новичок в gprof, поэтому я прочитал несколько учебных пособий, которые научили меня, как запускать gprof и определятьВремя потребление.

Однако мне нужно выяснить потреблениепамяти определенным набором классов. Допустим, существует программа со многими типами, A, ..., Z. Теперь я хочу запустить свою программу и посмотреть, сколько накопилось памяти. используется объектами классов A, E, I, O, U (например).

Есть ли у вас, ребята, какие-нибудь идеи или указания, как я мог бы подойти к этой задаче?
Я не рассматриваю исключительно gprof, я открыт для любого программного обеспечения (fos), которое выполняет эту работу.

Я, конечно, искал как в google, так и в Google. stackoverflow.com для любого ответа на эту проблему, но либо я использую неправильные ключевые слова, либо никто не имеет этой проблемы.

Edit: предложения о том, чтобы сделать это вручную, очевидны. От конечно, я мог бы закодировать его в приложение, но его о большом количестве классов я бы предпочел не менять. Кроме того, я хочу иметь общее потребление памяти, поэтому я не могу считать только все созданные объекты, потому что мне придется отслеживать размер объекта по отдельности.

Edit2: я пошел с модификацией предложенияDeadMG , которое я только должен унаследовать. Это работает довольно хорошо, так что, если у кого - то есть подобная проблема, попробуйте это.

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++;
    }
};

Поиск Карты - это немного неприятно, я признаю это, но у меня не хватило смелости позаботиться о хранении итератора для каждого класса. Основная проблема заключалась в том, что вы должны были бы явно инициализировать его для каждого подсчитанного класса. Если вы знаете, как это сделать лучше, скажите мне, как.

3 2

3 ответа:

Тривиально.

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;
    }
};

Если использование A включает динамическую память,то это решение может быть улучшено. Можно также переопределить глобальный оператор new / delete.

Я не знаю, что gprof даже пытается решать вопросы использования памяти. Очевидной альтернативой было бы valgrind. Если вы заботитесь только об общем использовании памяти, вы также можете выполнить эту работу самостоятельно (перегрузка ::operator new и ::operator delete для отслеживания объема памяти, запрошенного программой). Конечно, Возможно , что у вас есть некоторый код, который получает память другими средствами (например, непосредственно вызывая что-то вроде sbrk), но это довольно необычно. Те не пытаются это сделать. однако отслеживать статически распределенное и / или использование стека.

GlibC предоставляет статистику по выделению памяти кучи. Взгляните на mallinfo. Вероятно, вы могли бы получить статистику в различных точках во время выполнения и получить некоторое представление о том, сколько памяти используется.