Никак не могу разобраться, что в приложении потребляет лишнюю память.
Из чего строю предположения о "лишней" памяти:
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;
Посчитанная память и выделенная почти полностью совпадают.
3) Загружаю приложение(игру) целиком. Таким же образом как и в прошлом пункте считаю потребляемую память везде, где возможно (поэлементно рекурсивно все контейнеры, раскрываю все смарт-поинтеры, память текстур, ...).
Посчитанная таким образом память — 243мб текстур + 7мб на все остальное. Реально выделенная — 350мб. Итого неизвестно куда уходят 100мб. Главная цель — понять что занимает эти злополучные 100мб.
Память мерял через:
— Windows: Private Bytes в Process Explorer от Русиновича
— Windows
Утечек нет или они минимальные, т.к. при многократной выгрузке и загрузке общая картина почти не меняется.
Ситуация под Windows и iOS аналогичная. Пробовал профилировать память в Xcode Instruments, но безрезультатно.
Помогите, а?
Заранее огромная благодарность за любые подсказки.
Здравствуйте, kFk, Вы писали:
kFk>1) Загружаю ряд текстур, в памяти они занимают 140мб. При этом потребление памяти увеличивается на 170мб. Итого 30мб overhead.
Здравствуйте, LuciferSaratov, Вы писали:
LS>Здравствуйте, kFk, Вы писали:
kFk>>1) Загружаю ряд текстур, в памяти они занимают 140мб. При этом потребление памяти увеличивается на 170мб. Итого 30мб overhead.
LS>возможно, это мипмапы.
Спасибо, но врядли, сейчас создание мипмапов отключено.
Здравствуйте, smeeld, Вы писали:
S>Здравствуйте, kFk, Вы писали:
S>Что там с компрессией текстур?
Специально для теста все в A8R8G8B8, чтоб объем памяти был четко w*h*32
Здравствуйте, kFk, Вы писали:
kFk>Специально для теста все в A8R8G8B8, чтоб объем памяти был четко w*h*32
В смысле, в файле данные текстуры хранятся точно не в сжатом виде. Как определили, что данная текстура
занимает именно X MB, размеры файла текстуры редко совпадают с его распакованным образом в памяти в виде
последовательности r8g8b8(alpha8) на точку.
Здравствуйте, smeeld, Вы писали:
S>Здравствуйте, kFk, Вы писали:
kFk>>Специально для теста все в A8R8G8B8, чтоб объем памяти был четко w*h*32
S>В смысле, в файле данные текстуры хранятся точно не в сжатом виде. Как определили, что данная текстура S>занимает именно X MB, размеры файла текстуры редко совпадают с его распакованным образом в памяти в виде S>последовательности r8g8b8(alpha8) на точку.
Формат D3DFMT_A8R8G8B8 предполагает использование 32байт на пиксель. Итого размер текстуры в памяти = ширина*высота*32
Здравствуйте, kFk, Вы писали:
kFk>Формат D3DFMT_A8R8G8B8 предполагает использование 32байт на пиксель. Итого размер текстуры в памяти = ширина*высота*32
Не имел дела с графическими библами от MS, предположу, что файл загружается в память специализированными для этого
функциями из 3D либы, попробуйте загрузить данные из файла стандартными системными функциями.
Здравствуйте, kFk, Вы писали:
kFk>Утечек нет или они минимальные, т.к. при многократной выгрузке и загрузке общая картина почти не меняется. kFk>Ситуация под Windows и iOS аналогичная. Пробовал профилировать память в Xcode Instruments, но безрезультатно.
kFk>Помогите, а? kFk>Заранее огромная благодарность за любые подсказки.
Xcode Instruments показывает где, сколько и кем выдленно. Если этого не достаточно, то я даже не знаю что ещё может помочь
Здравствуйте, kFk, Вы писали:
kFk>Никак не могу разобраться, что в приложении потребляет лишнюю память.
kFk>Из чего строю предположения о "лишней" памяти:
kFk>1) Загружаю ряд текстур, в памяти они занимают 140мб. При этом потребление памяти увеличивается на 170мб. Итого 30мб overhead.
kFk>2) Загружаю из xml множество строк, записываю их во что-то вроде std::vector<std::pair<std::string, std::string>>. kFk>Дальше вручную считаю сколько должно занять памяти. Для вектора считаю так: kFk>
capacity() — возвращает не количество элементов, а количество элементов которые можно запихнуть в сторадж без переаллокации. Попробуй вместо него использовать size.
Здравствуйте, Kernan, Вы писали:
K>capacity() — возвращает не количество элементов, а количество элементов которые можно запихнуть в сторадж без переаллокации. Попробуй вместо него использовать size.
Специально писал capacity, чтоб замерять реально выделенную память. Т.к. size дает лишь формальный размер вектора, а capacity — фактически выделенную/зарезервированную память.
Здравствуйте, kFk, Вы писали:
kFk>Заранее огромная благодарность за любые подсказки.
Фрагментация?
Позапоминай адреса/размеры всех аллокаций (можешь свой new забабахать, например) и в интересующий момент посмотри на раскладку всего добра в памяти.
Здравствуйте, jazzer, Вы писали:
J>Фрагментация? J>Позапоминай адреса/размеры всех аллокаций (можешь свой new забабахать, например) и в интересующий момент посмотри на раскладку всего добра в памяти.
Врядли настолько масштабно. 100мб фрагментации для 7мб данных малореально, т.к. реаллокаций не так и много.
Private Bytes — это не только выделенная таким образом память. Это еще и вся статика (глобальные и статические объекты, код и т.д.). А также все, что явно или неявно приватно выделено во всех DLL, загруженных в процесс.
Я бы посоветовал ко всему, что здесь сказано, запустить VMMap от Руссиновича и тщательно просмотреть все блоки памяти, особенно те, которые явно не имеют отношения к динамически выделенной памяти. Каков их суммарный размер ?
kFk>Никак не могу разобраться, что в приложении потребляет лишнюю память.
kFk>Из чего строю предположения о "лишней" памяти:
kFk>1) Загружаю ряд текстур, в памяти они занимают 140мб. При этом потребление памяти увеличивается на 170мб. Итого 30мб overhead.
kFk>2) Загружаю из xml множество строк, записываю их во что-то вроде std::vector<std::pair<std::string, std::string>>. kFk>Дальше вручную считаю сколько должно занять памяти. Для вектора считаю так: kFk>
kFk>Посчитанная память и выделенная почти полностью совпадают.
kFk>3) Загружаю приложение(игру) целиком. Таким же образом как и в прошлом пункте считаю потребляемую память везде, где возможно (поэлементно рекурсивно все контейнеры, раскрываю все смарт-поинтеры, память текстур, ...). kFk>Посчитанная таким образом память — 243мб текстур + 7мб на все остальное. Реально выделенная — 350мб. Итого неизвестно куда уходят 100мб. Главная цель — понять что занимает эти злополучные 100мб.
kFk>Память мерял через: kFk>- Windows: Private Bytes в Process Explorer от Русиновича kFk>- Windows kFk>
kFk>Утечек нет или они минимальные, т.к. при многократной выгрузке и загрузке общая картина почти не меняется. kFk>Ситуация под Windows и iOS аналогичная. Пробовал профилировать память в Xcode Instruments, но безрезультатно.
kFk>Помогите, а? kFk>Заранее огромная благодарность за любые подсказки.
А не пробовал смотреть в какой момент лишняя память сжирается? Вот есть подозрения на подгружаемые ресурсы — для теста попробуй их не подгружать
Единственный нормальный способ — это изолировать компоненты приложения — некое подобие юнит тестов.
Как написали выше — вполне может быть библиотека, которая пишет для себя кеш для быстрой загрузки ресурсов, ты вот загружаешь и выгружаешь многократно — а оно 1 раз записало в кеш и дергает его, вот память после первой загрузки практически не меняется.
Здравствуйте, kpcb, Вы писали:
K>Xcode Instruments показывает где, сколько и кем выдленно. Если этого не достаточно, то я даже не знаю что ещё может помочь
А как его надо использовать, чтоб он корректные данные показывал? Может нужны какие-то спец-шаги.
А то VM Tracker показывает корректно, но не особо полезно — лишь таблица с записями типа IOKit, MALLOC_LARGE, TEXT, ...
В Allocations (где есть call-stack и т.д.) при выбранном All Heap & Anonymous VM показывает в 4 раза меньше памяти, чем реально выделено, а при включенном All VM Regions в 2 раза больше.
Здравствуйте, kFk, Вы писали:
kFk>Заранее огромная благодарность за любые подсказки.
Ну и забыли упомянуть оверхед самого аллокатора памяти. Если аллоцировать много много мелких кусочков, оверхед легко может достигнуть 100%.
И да, Process Explorer скорее всего показывает объём памяти в выделенных страницах виртуальной памяти. Он не может знать как эти страницы были использованы аллокатором памяти, возможно почти никак или там дикая дефрагментация.