std::vector, map сколько памяти занимают?
От: Баян 75 Россия  
Дата: 01.07.14 08:18
Оценка:
Коллеги, добрый день!

Мне надо приближённо оценить объём памяти, который занимает конкретный std:: контейнер.
Чтобы логировать распределение памяти, потом анализировать логи.
Как это правильно сделать?

Для простого типа TData (не содержащего в себе контейнеры и пр. динамически выделяемую память), я использую:

template<typename TData>
size_t CalculateMemory(const std::vector<TData>& s)
{
return s.capacity() * sizeof(TData);
}

Как вычислять для std::map, unordered_map?

Может, уже есть какие-то функции?

Спасибо.
Re: std::vector, map сколько памяти занимают?
От: jazzer Россия Skype: enerjazzer
Дата: 01.07.14 08:27
Оценка: 15 (2)
Здравствуйте, Баян 75, Вы писали:

Б7>Мне надо приближённо оценить объём памяти, который занимает конкретный std:: контейнер.

Б7>Чтобы логировать распределение памяти, потом анализировать логи.
Б7>Как это правильно сделать?

Б7>Может, уже есть какие-то функции?


Есть. Аллокатор, который ты передаешь в вектор и прочая, предоставляет функции allocate/deallocate — наиболее естественное место, чтобы вести статистику. Если хочешь профилировать вообще всё — можешь просто захачить std::allocator (может статься, что он уже не умеет логировать в твоей поставке STL под дебагом — проверь). Если не все, а что-то конкретное — передавай аллокатор в это конкретное.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: std::vector, map сколько памяти занимают?
От: smeeld  
Дата: 01.07.14 09:06
Оценка: -2 :)
Здравствуйте, Баян 75, Вы писали:


Б7>Мне надо приближённо оценить объём памяти, который занимает конкретный std:: контейнер.



В байтах:

typedef map<A, B> Mp;
 Mp mp;
.....................

 size_t sz=sizeof(Mp::value_type)*mp.size();
}
Re[2]: std::vector, map сколько памяти занимают?
От: Баян 75 Россия  
Дата: 01.07.14 09:19
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Есть. Аллокатор, который ты передаешь в вектор и прочая, предоставляет функции allocate/deallocate — наиболее естественное место, чтобы вести статистику. Если хочешь профилировать вообще всё — можешь просто захачить std::allocator (может статься, что он уже не умеет логировать в твоей поставке STL под дебагом — проверь). Если не все, а что-то конкретное — передавай аллокатор в это конкретное.


Спасибо!
Кажется, это — то что нужно. Буду смотреть.
Re[2]: std::vector, map сколько памяти занимают?
От: Баян 75 Россия  
Дата: 01.07.14 09:22
Оценка:
Здравствуйте, smeeld, Вы писали:

S> size_t sz=sizeof(Mp::value_type)*mp.size();


Это, кажется, слишком приближённо.
Но, всё равно, спасибо.
Re[3]: std::vector, map сколько памяти занимают?
От: Igore Россия  
Дата: 01.07.14 09:38
Оценка:
Здравствуйте, Баян 75, Вы писали:

Б7>Здравствуйте, smeeld, Вы писали:


S>> size_t sz=sizeof(Mp::value_type)*mp.size();


Б7>Это, кажется, слишком приближённо.

Б7>Но, всё равно, спасибо.

http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx
В конце размеры
Re[3]: std::vector, map сколько памяти занимают?
От: jazzer Россия Skype: enerjazzer
Дата: 01.07.14 09:40
Оценка:
Здравствуйте, Баян 75, Вы писали:

Б7>Здравствуйте, smeeld, Вы писали:


S>> size_t sz=sizeof(Mp::value_type)*mp.size();


Б7>Это, кажется, слишком приближённо.


Это мягко говоря

sizeof(Mp::value_type) — это не размер узла, а лишь размер того, что внутри узла лежит. А сам узел наружу не выставлен, это деталь реализации (а это, в частности, значит, что реализована работа с узлами может быть как угодно, единственное, что гарантируется — что в конечном итога она как-то пойдет через аллокатор).
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: std::vector, map сколько памяти занимают?
От: jazzer Россия Skype: enerjazzer
Дата: 01.07.14 09:44
Оценка:
Здравствуйте, Igore, Вы писали:

I>http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx

I>В конце размеры

Вот только это размеры самого объекта, они не включают динамическую память, взятую из аллокатора.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: std::vector, map сколько памяти занимают?
От: smeeld  
Дата: 01.07.14 09:55
Оценка:
Здравствуйте, Баян 75, Вы писали:


Б7>Это, кажется, слишком приближённо.

Б7>Но, всё равно, спасибо.

value_type-это тот объект(его typedef) который и есть сохраняемый в контейнере
объект, под который память и выделяется. Например для map из GNU-сных запилов;


template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
  typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
  class map
  {
  public:
  typedef _Key key_type;
  typedef _Tp mapped_type;
  typedef std::pair<const _Key, _Tp> value_type;
  typedef _Compare key_compare;
  typedef _Alloc allocator_type;


................................................................

 std::pair<iterator, bool>
629  insert(const value_type& __x)
630  { return _M_t._M_insert_unique(__x); }
631 

.................................................................


 pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
1487  _Compare, _Alloc>::iterator, bool>
1488  _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1489 #if __cplusplus >= 201103L
1490  _M_insert_unique(_Arg&& __v)
1491 #else
1492  _M_insert_unique(const _Val& __v)
1493 #endif
1494  {
1495  typedef pair<iterator, bool> _Res;
1496  pair<_Base_ptr, _Base_ptr> __res
1497  = _M_get_insert_unique_pos(_KeyOfValue()(__v));
1498 
1499  if (__res.second)
1500  return _Res(_M_insert_(__res.first, __res.second,
1501  _GLIBCXX_FORWARD(_Arg, __v)),
1502  true);
1503 
1504  return _Res(iterator(static_cast<_Link_type>(__res.first)), false);
1505  }
1506 
.............................................................................

 template<typename _Key, typename _Val, typename _KeyOfValue,
1126  typename _Compare, typename _Alloc>
1127 #if __cplusplus >= 201103L
1128  template<typename _Arg>
1129 #endif
1130  typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
1131  _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
1132 #if __cplusplus >= 201103L
1133  _M_insert_(_Base_ptr __x, _Base_ptr __p, _Arg&& __v)
1134 #else
1135  _M_insert_(_Base_ptr __x, _Base_ptr __p, const _Val& __v)
1136 #endif
1137  {
1138  bool __insert_left = (__x != 0 || __p == _M_end()
1139  || _M_impl._M_key_compare(_KeyOfValue()(__v),
1140  _S_key(__p)));
1141 
1142  _Link_type __z = _M_create_node(_GLIBCXX_FORWARD(_Arg, __v));
1143 
1144  _Rb_tree_insert_and_rebalance(__insert_left, __z, __p,
1145  this->_M_impl._M_header);
1146  ++_M_impl._M_node_count;
1147  return iterator(__z);
1148  }
1149 
...........................................................................................................

 _Link_type
393  _M_create_node(const value_type& __x)
394  {
395  _Link_type __tmp = _M_get_node();
396  __try
397  { get_allocator().construct(__tmp->_M_valptr(), __x); }
398  __catch(...)
399  {
400  _M_put_node(__tmp);
401  __throw_exception_again;
402  }
403  return __tmp;
404  }
405
Re[4]: std::vector, map сколько памяти занимают?
От: flаt  
Дата: 01.07.14 10:07
Оценка: +1
Здравствуйте, smeeld, Вы писали:

S>value_type-это тот объект(его typedef) который и есть сохраняемый в контейнере

S>объект, под который память и выделяется. Например для map из GNU-сных запилов;
Нет, там ещё структура под узел, в которой и лежит value_type: к примеру, https://github.com/llvm-mirror/libcxx/blob/master/include/__tree#L595
Re: std::vector, map сколько памяти занимают?
От: uzhas Ниоткуда  
Дата: 01.07.14 10:23
Оценка:
Здравствуйте, Баян 75, Вы писали:

Б7>Может, уже есть какие-то функции?


для более точной картины я рекомендую использовать инструменты, которые умеют анализировать выделенную память или утечки, например, GlowCode

берем код
void TestXYZ1()
{
  std::vector<int> v;
  v.reserve(1);
}

void TestXYZ2()
{
  std::vector<int> v;
  v.reserve(100000);
}
void TestXYZ3()
{
  std::unordered_map<int, int> v;
  for (int i = 0; i < 100000; ++i)
    v.emplace(i, i);
}

int main()
{
  TestXYZ1();
  TestXYZ2();
  TestXYZ3();
  return 0;
}


анализируем в дебаге:
  большая картинка

в релизе картина будет чуток другая, ибо в студии std::vector в дебаге делает аллокацию, даже если пустой
Re[5]: std::vector, map сколько памяти занимают?
От: smeeld  
Дата: 01.07.14 10:55
Оценка:
Здравствуйте, flаt, Вы писали:


F>Нет, там ещё структура под узел, в которой и лежит value_type:


Это про _Rb_tree_node<_Val> ?

Ну, мне думалось, что она в параллельном пространстве аллокатится.
Re[6]: std::vector, map сколько памяти занимают?
От: jazzer Россия Skype: enerjazzer
Дата: 01.07.14 11:01
Оценка:
Здравствуйте, smeeld, Вы писали:

S>Здравствуйте, flаt, Вы писали:



F>>Нет, там ещё структура под узел, в которой и лежит value_type:


S>Это про _Rb_tree_node<_Val> ?


S>Ну, мне думалось, что она в параллельном пространстве аллокатится.


Даже если так — ее не надо учитывать, выясняя расходы памяти?
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[7]: std::vector, map сколько памяти занимают?
От: smeeld  
Дата: 01.07.14 11:21
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Даже если так — ее не надо учитывать, выясняя расходы памяти?


А как с вопросом статистики памяти, не заменяя std::allocator?
Re[8]: std::vector, map сколько памяти занимают?
От: Evgeny.Panasyuk Россия  
Дата: 01.07.14 11:56
Оценка:
Здравствуйте, smeeld, Вы писали:

J>>Даже если так — ее не надо учитывать, выясняя расходы памяти?

S>А как с вопросом статистики памяти, не заменяя std::allocator?

Сделать свои ::operator new и т.п., измерить статистику памяти в ограниченном scope, причём при наличии других потоков — отфильтровать по tid/tls.
Re[4]: std::vector, map сколько памяти занимают?
От: Evgeny.Panasyuk Россия  
Дата: 01.07.14 12:13
Оценка:
Здравствуйте, jazzer, Вы писали:

J>а это, в частности, значит, что реализована работа с узлами может быть как угодно, единственное, что гарантируется — что в конечном итога она как-то пойдет через аллокатор


<зануда_mode /> Думаю что жёсткой гарантии нет: например эффекты стандартных контейнеров undefined для incomplete типов, и соответственно они могут сделать small size optimization в обход аллокатора.
Но на практике это ничего не меняет — я не встречал std::map с подобной оптимизацией.
Re[9]: std::vector, map сколько памяти занимают?
От: smeeld  
Дата: 01.07.14 12:51
Оценка: +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:


EP>Сделать свои ::operator new и т.п., измерить статистику памяти в ограниченном scope, причём при наличии других потоков — отфильтровать по tid/tls.


Оно!
Re[8]: std::vector, map сколько памяти занимают?
От: jazzer Россия Skype: enerjazzer
Дата: 01.07.14 14:36
Оценка:
Здравствуйте, smeeld, Вы писали:

S>Здравствуйте, jazzer, Вы писали:


J>>Даже если так — ее не надо учитывать, выясняя расходы памяти?


S>А как с вопросом статистики памяти, не заменяя std::allocator?


А что с ним? и в чем проблема заменить аллокатор или просто его захачить для твоих нужд? Благо STL вся в исходниках доступна Сделай спец.дефайн и под соответствующим ифдефом вставь запись статистики
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.