Re: Узнать что потребляет "лишнюю" память
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 26.11.14 14:50
Оценка: -1
Здравствуйте, kFk, Вы писали:

kFk>Никак не могу разобраться, что в приложении потребляет лишнюю память.


kFk>Из чего строю предположения о "лишней" памяти:


kFk>1) Загружаю ряд текстур, в памяти они занимают 140мб. При этом потребление памяти увеличивается на 170мб. Итого 30мб overhead.


kFk>2) Загружаю из xml множество строк, записываю их во что-то вроде std::vector<std::pair<std::string, std::string>>.

kFk>Дальше вручную считаю сколько должно занять памяти. Для вектора считаю так:
kFk>
auto size = sizeof(v) + v.capacity() * sizeof(T);
kFk>for (const auto& element : v)
kFk>{
kFk>  size += TotalSizeOf(element) - sizeof(T);
kFk>}
kFk>return size;

kFk>Каждую строку считаю так:
kFk>
return sizeof(s) + s.capacity() * sizeof(std::string::value_type);

capacity() — возвращает не количество элементов, а количество элементов которые можно запихнуть в сторадж без переаллокации. Попробуй вместо него использовать size.
Sic luceat lux!
Узнать что потребляет "лишнюю" память
От: kFk  
Дата: 26.11.14 12:12
Оценка:
Никак не могу разобраться, что в приложении потребляет лишнюю память.

Из чего строю предположения о "лишней" памяти:

1) Загружаю ряд текстур, в памяти они занимают 140мб. При этом потребление памяти увеличивается на 170мб. Итого 30мб overhead.

2) Загружаю из xml множество строк, записываю их во что-то вроде std::vector<std::pair<std::string, std::string>>.
Дальше вручную считаю сколько должно занять памяти. Для вектора считаю так:
auto size = sizeof(v) + v.capacity() * sizeof(T);
for (const auto& element : v)
{
  size += TotalSizeOf(element) - sizeof(T);
}
return size;

Каждую строку считаю так:
return sizeof(s) + s.capacity() * sizeof(std::string::value_type);

Посчитанная память и выделенная почти полностью совпадают.

3) Загружаю приложение(игру) целиком. Таким же образом как и в прошлом пункте считаю потребляемую память везде, где возможно (поэлементно рекурсивно все контейнеры, раскрываю все смарт-поинтеры, память текстур, ...).
Посчитанная таким образом память — 243мб текстур + 7мб на все остальное. Реально выделенная — 350мб. Итого неизвестно куда уходят 100мб. Главная цель — понять что занимает эти злополучные 100мб.

Память мерял через:
— Windows: Private Bytes в Process Explorer от Русиновича
— Windows
PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
return pmc.PrivateUsage;

— iOS
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
return (kerr == KERN_SUCCESS) ? info.resident_size : 0; // size in bytes


Утечек нет или они минимальные, т.к. при многократной выгрузке и загрузке общая картина почти не меняется.
Ситуация под Windows и iOS аналогичная. Пробовал профилировать память в Xcode Instruments, но безрезультатно.

Помогите, а?
Заранее огромная благодарность за любые подсказки.
memory profiling visual studio xcode
Re: Узнать что потребляет "лишнюю" память
От: LuciferSaratov Россия  
Дата: 26.11.14 12:18
Оценка:
Здравствуйте, kFk, Вы писали:

kFk>1) Загружаю ряд текстур, в памяти они занимают 140мб. При этом потребление памяти увеличивается на 170мб. Итого 30мб overhead.


возможно, это мипмапы.
Re[2]: Узнать что потребляет "лишнюю" память
От: kFk  
Дата: 26.11.14 12:20
Оценка:
Здравствуйте, LuciferSaratov, Вы писали:

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


kFk>>1) Загружаю ряд текстур, в памяти они занимают 140мб. При этом потребление памяти увеличивается на 170мб. Итого 30мб overhead.


LS>возможно, это мипмапы.

Спасибо, но врядли, сейчас создание мипмапов отключено.
Re: Узнать что потребляет "лишнюю" память
От: smeeld  
Дата: 26.11.14 12:32
Оценка:
Здравствуйте, kFk, Вы писали:

Что там с компрессией текстур?
Re[2]: Узнать что потребляет "лишнюю" память
От: kFk  
Дата: 26.11.14 12:37
Оценка:
Здравствуйте, smeeld, Вы писали:

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


S>Что там с компрессией текстур?

Специально для теста все в A8R8G8B8, чтоб объем памяти был четко w*h*32
Отредактировано 26.11.2014 12:38 kFk . Предыдущая версия .
Re[3]: Узнать что потребляет "лишнюю" память
От: smeeld  
Дата: 26.11.14 12:50
Оценка:
Здравствуйте, kFk, Вы писали:

kFk>Специально для теста все в A8R8G8B8, чтоб объем памяти был четко w*h*32


В смысле, в файле данные текстуры хранятся точно не в сжатом виде. Как определили, что данная текстура
занимает именно X MB, размеры файла текстуры редко совпадают с его распакованным образом в памяти в виде
последовательности r8g8b8(alpha8) на точку.
Re[4]: Узнать что потребляет "лишнюю" память
От: kFk  
Дата: 26.11.14 12:52
Оценка:
Здравствуйте, smeeld, Вы писали:

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


kFk>>Специально для теста все в A8R8G8B8, чтоб объем памяти был четко w*h*32


S>В смысле, в файле данные текстуры хранятся точно не в сжатом виде. Как определили, что данная текстура

S>занимает именно X MB, размеры файла текстуры редко совпадают с его распакованным образом в памяти в виде
S>последовательности r8g8b8(alpha8) на точку.

Формат D3DFMT_A8R8G8B8 предполагает использование 32байт на пиксель. Итого размер текстуры в памяти = ширина*высота*32
Re[5]: Узнать что потребляет "лишнюю" память
От: smeeld  
Дата: 26.11.14 13:06
Оценка:
Здравствуйте, kFk, Вы писали:

kFk>Формат D3DFMT_A8R8G8B8 предполагает использование 32байт на пиксель. Итого размер текстуры в памяти = ширина*высота*32


Не имел дела с графическими библами от MS, предположу, что файл загружается в память специализированными для этого
функциями из 3D либы, попробуйте загрузить данные из файла стандартными системными функциями.
Re: Узнать что потребляет "лишнюю" память
От: kpcb Россия  
Дата: 26.11.14 13:37
Оценка:
Здравствуйте, kFk, Вы писали:

kFk>Утечек нет или они минимальные, т.к. при многократной выгрузке и загрузке общая картина почти не меняется.

kFk>Ситуация под Windows и iOS аналогичная. Пробовал профилировать память в Xcode Instruments, но безрезультатно.

kFk>Помогите, а?

kFk>Заранее огромная благодарность за любые подсказки.

Xcode Instruments показывает где, сколько и кем выдленно. Если этого не достаточно, то я даже не знаю что ещё может помочь
Re[2]: Узнать что потребляет "лишнюю" память
От: kFk  
Дата: 26.11.14 16:14
Оценка:
Здравствуйте, Kernan, Вы писали:

K>capacity() — возвращает не количество элементов, а количество элементов которые можно запихнуть в сторадж без переаллокации. Попробуй вместо него использовать size.


Специально писал capacity, чтоб замерять реально выделенную память. Т.к. size дает лишь формальный размер вектора, а capacity — фактически выделенную/зарезервированную память.
Re: Узнать что потребляет "лишнюю" память
От: jazzer Россия Skype: enerjazzer
Дата: 26.11.14 16:49
Оценка:
Здравствуйте, kFk, Вы писали:

kFk>Заранее огромная благодарность за любые подсказки.


Фрагментация?
Позапоминай адреса/размеры всех аллокаций (можешь свой new забабахать, например) и в интересующий момент посмотри на раскладку всего добра в памяти.
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[2]: Узнать что потребляет "лишнюю" память
От: kFk  
Дата: 26.11.14 19:06
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Фрагментация?

J>Позапоминай адреса/размеры всех аллокаций (можешь свой new забабахать, например) и в интересующий момент посмотри на раскладку всего добра в памяти.

Врядли настолько масштабно. 100мб фрагментации для 7мб данных малореально, т.к. реаллокаций не так и много.
Re: Узнать что потребляет "лишнюю" память
От: Pavel Dvorkin Россия  
Дата: 27.11.14 02:59
Оценка:
Здравствуйте, kFk, Вы писали:

kFk>Память мерял через:

kFk>- Windows: Private Bytes в Process Explorer от Русиновича
kFk>- Windows
kFk>
PROCESS_MEMORY_COUNTERS_EX pmc;
kFk>GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
kFk>return pmc.PrivateUsage;
kFk>


Private Bytes — это не только выделенная таким образом память. Это еще и вся статика (глобальные и статические объекты, код и т.д.). А также все, что явно или неявно приватно выделено во всех DLL, загруженных в процесс.

Я бы посоветовал ко всему, что здесь сказано, запустить VMMap от Руссиновича и тщательно просмотреть все блоки памяти, особенно те, которые явно не имеют отношения к динамически выделенной памяти. Каков их суммарный размер ?
With best regards
Pavel Dvorkin
Re: Узнать что потребляет "лишнюю" память
От: omgOnoz  
Дата: 27.11.14 03:00
Оценка:
Здравствуйте, kFk, Вы писали:

  Скрытый текст
kFk>Никак не могу разобраться, что в приложении потребляет лишнюю память.

kFk>Из чего строю предположения о "лишней" памяти:


kFk>1) Загружаю ряд текстур, в памяти они занимают 140мб. При этом потребление памяти увеличивается на 170мб. Итого 30мб overhead.


kFk>2) Загружаю из xml множество строк, записываю их во что-то вроде std::vector<std::pair<std::string, std::string>>.

kFk>Дальше вручную считаю сколько должно занять памяти. Для вектора считаю так:
kFk>
auto size = sizeof(v) + v.capacity() * sizeof(T);
kFk>for (const auto& element : v)
kFk>{
kFk>  size += TotalSizeOf(element) - sizeof(T);
kFk>}
kFk>return size;

kFk>Каждую строку считаю так:
kFk>
return sizeof(s) + s.capacity() * sizeof(std::string::value_type);

kFk>Посчитанная память и выделенная почти полностью совпадают.

kFk>3) Загружаю приложение(игру) целиком. Таким же образом как и в прошлом пункте считаю потребляемую память везде, где возможно (поэлементно рекурсивно все контейнеры, раскрываю все смарт-поинтеры, память текстур, ...).

kFk>Посчитанная таким образом память — 243мб текстур + 7мб на все остальное. Реально выделенная — 350мб. Итого неизвестно куда уходят 100мб. Главная цель — понять что занимает эти злополучные 100мб.

kFk>Память мерял через:

kFk>- Windows: Private Bytes в Process Explorer от Русиновича
kFk>- Windows
kFk>
PROCESS_MEMORY_COUNTERS_EX pmc;
kFk>GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
kFk>return pmc.PrivateUsage;
kFk>

kFk>- iOS
kFk>
struct task_basic_info info;
kFk>mach_msg_type_number_t size = sizeof(info);
kFk>kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
kFk>return (kerr == KERN_SUCCESS) ? info.resident_size : 0; // size in bytes


kFk>Утечек нет или они минимальные, т.к. при многократной выгрузке и загрузке общая картина почти не меняется.

kFk>Ситуация под Windows и iOS аналогичная. Пробовал профилировать память в Xcode Instruments, но безрезультатно.

kFk>Помогите, а?

kFk>Заранее огромная благодарность за любые подсказки.


А не пробовал смотреть в какой момент лишняя память сжирается? Вот есть подозрения на подгружаемые ресурсы — для теста попробуй их не подгружать
Единственный нормальный способ — это изолировать компоненты приложения — некое подобие юнит тестов.

Как написали выше — вполне может быть библиотека, которая пишет для себя кеш для быстрой загрузки ресурсов, ты вот загружаешь и выгружаешь многократно — а оно 1 раз записало в кеш и дергает его, вот память после первой загрузки практически не меняется.
Отредактировано 27.11.2014 3:06 omgOnoz . Предыдущая версия . Еще …
Отредактировано 27.11.2014 3:05 omgOnoz . Предыдущая версия .
Отредактировано 27.11.2014 3:01 omgOnoz . Предыдущая версия .
Re[2]: Узнать что потребляет "лишнюю" память
От: kFk  
Дата: 27.11.14 17:09
Оценка:
Здравствуйте, kpcb, Вы писали:

K>Xcode Instruments показывает где, сколько и кем выдленно. Если этого не достаточно, то я даже не знаю что ещё может помочь


А как его надо использовать, чтоб он корректные данные показывал? Может нужны какие-то спец-шаги.
А то VM Tracker показывает корректно, но не особо полезно — лишь таблица с записями типа IOKit, MALLOC_LARGE, TEXT, ...
В Allocations (где есть call-stack и т.д.) при выбранном All Heap & Anonymous VM показывает в 4 раза меньше памяти, чем реально выделено, а при включенном All VM Regions в 2 раза больше.
Re: Узнать что потребляет "лишнюю" память
От: johny5 Новая Зеландия
Дата: 27.11.14 21:55
Оценка:
Здравствуйте, kFk, Вы писали:

kFk>Заранее огромная благодарность за любые подсказки.


Ну и забыли упомянуть оверхед самого аллокатора памяти. Если аллоцировать много много мелких кусочков, оверхед легко может достигнуть 100%.
И да, Process Explorer скорее всего показывает объём памяти в выделенных страницах виртуальной памяти. Он не может знать как эти страницы были использованы аллокатором памяти, возможно почти никак или там дикая дефрагментация.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.