size — c ++: найти самый большой контейнер в программе

Я пытаюсь проанализировать большую программу на C ++. Программа активно использует структуры данных контейнера STL, такие как набор, карта, неупорядоченный набор, неупорядоченная карта, вектор и т. Д. Иногда они являются вложенными, например, карта множеств.

Я хочу выяснить, в конкретном запуске программы, какие контейнеры содержат наибольшее количество элементов (то есть наибольшее значение size ()). Я могу внести небольшие изменения в программу.

Если бы был способ перебрать все контейнеры, или если был способ перехватить API-интерфейсы (изменения размера) контейнеров, это могло бы быть полезным. Но это невозможно.

Как бы вы подошли к этому?

Дополнение: Платформа в Linux, компилятор либо g ++, либо clang ++.

5

Решение

Если вы можете вносить незначительные изменения, можете ли вы добавить каждый контейнер в большой список?

Как это:

std::set<......> my_set;  // existing code
all_containers.add( &my_set ); // minor edit IMHO

Тогда вы можете позвонить all_containers.analyse() что бы позвонить size() на каждом из них и распечатать результаты.

Вы можете использовать что-то вроде этого:

struct ContainerStatsI {
virtual int getSize() = 0;
};
template<class T> struct ContainerStats : ContainerStatsI {
T* p_;
ContainerStats( T* p ) : p_(p) {}
int getSize() { return p->size(); }
};
struct ContainerStatsList {
std::list<ContainerStatsI*> list_; // or some other container....
template<class T> void add( T* p ) {
list_.push_back( new ContainerStats<T>(p) );
}
// you should probably add a remove(T* p) as well
void analyse() {
for( ContainerStatsI* p : list_ ) {
p->getSize(); // do something with what's returned here
}
}
};
2

Другие решения

Этот метод полезен, когда ваш проект действительно большой и имеет много экземпляров разных контейнеров. Преимущество метода в том, что вам не нужно изменять большой объем кода. Это позволяет сузить тип контейнера для поиска. Этот метод помогает диагностировать ситуацию по каждому контактору и типу.

Можно переопределить template< class T > struct allocator, Возможно переименовать оригинальный распределитель в заголовках std или изменить его. Сделать возможным сделать статистику для распределения и освобождения. Вы будете знать количество и размер для каждого типа элементов. Но Вы не можете знать, какой экземпляр контейнера имеет элементы.

шаблон template< class T > struct allocator размещены в заголовочных файлах библиотеки. Он всегда существует и не нуждается в перестройке библиотеки среды разработки, поскольку вы знаете, что шаблон невозможно скомпилировать в статическую библиотеку (исключая специализацию). Шаблоны компилируются всегда с вашими источниками. Но могут быть проблемы с предварительно скомпилированными заголовками. Для проекта его можно регенерировать или не использовать, но для библиотеки необходимо проверить. Возможно, это узкое место метода, но просто проверить, существует проблема или нет.

Существует один эмпирический метод, который не гарантирует точности. Когда приложение закрывается, контейнеры освобождаются после освобождения его элементов. Таким образом, вы можете написать статистику по контейнеру родительского типа, сколько внутренних элементов было в каком типе контейнера.

Например, пусть у нас есть:

vector<A>({1,2,3}) and map<string,B>({1,2}) and map<string,B>({1,2})

Это создаст список событий освобождения, как это:

B, B, map<string,B>,
A, A, map<string,A>,
A, A, A, vector<A>,

Таким образом, вы можете знать, что 3 элемента A в vector<A>, 2 элемента A в map<string,A>и 2 элемента A в map<string,A>

2

Добавьте статистический код к деструкторам контейнеров в заголовочных файлах std. Это не требует изменения большого количества кода большого проекта. Но это также показывает только тип контейнера (см. Мой другой ответ здесь). Метод не требует C ++ 0x или C ++ 11 или более.

Первый а также обязательный шаг — добавить вашу библиотеку std под контроль исходного кода, например, git, для быстрого просмотра того, что действительно изменилось, и для быстрого переключения между измененной и исходной версией.

Поместите эту декларацию Stat Класс в папку исходных файлов библиотеки std:

class Stat {
std::map<std::string,int> total;
std::map<std::string,int> maximum;
public:
template<class T>
int log( std::string cont, size_t size ) {
std::string key = cont + ": " + typeid(T).name();
if( maximum[key] < size ) maximum[key] = size;
total[key] += size;
}
void show_result() {
std::cout << "container type total maximum" << std::endl;
std::map<std::string,int>::const_iterator it;
for( it = total.begin(); it != total.end(); ++it ) {
std::cout << it->first << " " << it->second
<< " " << maximum[it->first] << std::endl;
}
}
static Stat& instance();
~Stat(){ show_result(); }
};

Инстанцирующий экземпляр синглтона Stat класс в вашем проекте cpp файла:

Stat& Stat::instance() {
static Stat stat;
return stat;
}

Отредактируйте шаблоны контейнеров библиотеки std. Добавить статистику по деструкторам.

// modify this standart template library sources:

template< T, Allocator = std::allocator<T> > vector {
...
virtual ~vector() {
Stat::instance().log<value_type>( "std::vector", this->size() );
}
};

template< Key, T, Compare = std::less<Key>,
Allocator = std::allocator<std::pair<const Key, T> > map {
...
virtual ~map(){
Stat::instance().log<value_type>( "std::map", this->size() );
}
};

Рассмотрим программу, например, сейчас:

int main() {
{
// reject to use C++0x, project does not need such dependency
std_vector<int> v1; for(int i=0;i<10;++i) v1.push_back( i );
std_vector<int> v2; for(int i=0;i<10;++i) v2.push_back( i );
std_map<int,std::string> m1; for(int i=0;i<10;++i) m1[i]="";
std_map<int,std::string> m2; for(int i=0;i<20;++i) m2[i]="";
}
Stat::instance().show_result();
return 0;
}

Результат для gcc:

container type total maximum
std::map: St4pairIiSsE 30 20
std::vector: i 20 10

Если вам нужно более подробное описание типов, чем найти информацию о вашей среде разработки. Такое преобразование описано здесь для gcc: https://lists.gnu.org/archive/html/help-gplusplus/2009-02/msg00006.html

Вывод может быть таким:

container type total maximum
std::map: std::pair<int, std::string> 30 20
std::vector: int 20 10
1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector