![]() |
Модераторы: Poseidon, Snowy, bems, MetalFan |
![]() ![]() ![]() |
|
LamerTM |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 97 Регистрация: 11.3.2006 Репутация: нет Всего: 0 |
Здравствуйте.
Значится так. Есть прога, грузит она файлы. Каждый файл в отдельное дочернее окно (MDIChild то есть). После загрузки смотрю по диспетчеру задач сколько памяти занято, написано что 340Мб. (У меня физ. память 256МБ.) Общий объем файлов не более 25Мб, а результате их заргузки объем используемой памяти увеличивается более чем на 200Мб. К слову, файлов 266 штук. Соответственно, количество дочерних окон получается таким же. Тут я решил что надо что-то делать. Ну, думаю, наверное всю память занимают сами окна, а файлы там всего ничего, каких-то 25 метров. Решил переделать прогу так, чтобы все файлы загружались в одно дочернее окно (а в нём уже кнопочками можно выбирать какой файл просматривать, но это не важно). Ну вот, сделал я так. Врубил загрузку. Сижу, значит, любуюсь как файлы загружаются..... и тут бац! Out of memory! Я аж офигел. Думаю, ни фига себе! Ну смотрю в диспетчер задач, а там количество использованной памяти всего 140Мб! Раньше было 340 и всё в порядке, а тут на 140 метрах вдруг out of memory! Подумал я, что это какое-то ограничение у дочерних окон есть, что много в одно окно грузить нельзя. Прогнал в трассировщике, выяснилось что исключение возникает на команде SetLength - она выдает out of memory, когда пытается увеличить размер массива на 1 для загрузки следующего файла. Происходит это на 178 файле. То есть когда дается команда SetLength(arr, 178) то происходит это глючок. Да, ну так вот. Взял я и сразу поставил SetLength(arr, 1000) - чтобы сразу кучу места выделить, посмотреть что получится (это без загрузки файлов). Врубил прогу, и команда выделила память! Посмотрел по диспетчеру задач, объем используемой памяти стал 420Мб! И ничего! Всё пофиг! А там при каких-то 178 элементах массива, и 140 метрах памяти возникает ошибка! Потом я сделал так. Сразу стал выделять память на все файлы, на 270 штук (с запасом). И всё стало работать! Но это же фигня так делать. А что если мне не нужно столько места? В общем, фигня всё. Итак, коротко повторяю суть. Есть массив. И два способа загрузки файлов (оба способа - в одно окно). Первый: массив изначально имеет длину 0, после чего перед загрузкой каждого файла увеличивается на 1 функцией SetLength. Это в конце концов приводит к глюку out of memory при большом числе файлов. Второй способ: массив изначально устанавливается большого размера (массив динамический) функцией SetLength, после чего в него грузятся файлы. Ошибок при этом нет! Но это фиговый способ, т.к. жрет много памяти даже когда файлов мало. Да, и еще. При загрузке способом 1 (то есть когда меняется размер массива) загрузка происходит гораздо медленнее, и постоянно замедляется с каждым новым файлом, то есть очередное увеличение массива на единицу, с каждым разом происходит всё большее время. Вот я чего не могу понять, - что это такое? И что делать? Я в ступоре. Хочу чтобы размер массива можно было увеличивать по ходу загрузки файлов, но это приводит к глюку. |
|||
|
||||
ShadeSt |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 256 Регистрация: 9.8.2005 Где: Россия, г. Ставро поль Репутация: нет Всего: 7 |
а для чего используется тот массив?
для хранения имен файлов или для чего то другого? сам по себе SetLength такого делать не может, и :
имхо, у тебя кто-то кушает память. а вообще то хотелось бы глянуть на код. -------------------- It's nice to be importand, but it's more importand to be nice © Scooter |
|||
|
||||
Romkin |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 189 Регистрация: 14.11.2006 Где: Москва Репутация: 2 Всего: 5 |
Естественно. Это называется "поиздеваемся над менеджером памяти" ![]() Сам посмотри: SetLength выделяет память. Хорошо. Потом Требуется памяти на 1 больше. В результате в то, что выделено, уже не лезет - выделяется новый блок, а старый идет в пул свободных. А вернется он к системе еще не скоро, работа идет ;) А сколько всего тебе надо - сам посчитай. А этот способ хороший. Только память надо выделять не "от балды", а точно по размеру файла. А его узнать очень просто. И еще вопрос: нафига тебе это надо? Используй TFileStream... И загружать файлы лучше когда надо посмотреть, а не заранее. Не верю я, что этот процесс долгий. |
|||
|
||||
LamerTM |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 97 Регистрация: 11.3.2006 Репутация: нет Всего: 0 |
Я и не программист.
![]() ![]() Покороче: Есть динамический массив и 266 файлов. И два способа загрузки файлов в этот массив. Первый способ: массив изначально имеет длину 0, после чего перед загрузкой каждого файла увеличивается на 1 функцией SetLength. Сначала все грузится нормально, но потом функция SetLength выдает out of memory (при попытке увеличить длину массива с 177 до 178 элементов). Второй способ: массив изначально устанавливается большого размера (длина ставится 270, массив динамический) функцией SetLength, после чего в него грузятся файлы. Ошибок при этом нет! Но это фиговый способ, т.к. жрет много памяти даже когда файлов мало. Вопрос: почему глючит способ №1. |
|||
|
||||
Romkin |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 189 Регистрация: 14.11.2006 Где: Москва Репутация: 2 Всего: 5 |
||||
|
||||
ShadeSt |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 256 Регистрация: 9.8.2005 Где: Россия, г. Ставро поль Репутация: нет Всего: 7 |
Это почему?? то что увеличивать размер на 1цу это понятно, что это издевательство над менеджером памяти, но еще и вопрос в другом, что он хранит в том масссиве, потому как если это массив строк в которых просто хранятся имена файлов, то это уж никаким боком не должно приводить к переполнению памяти. -------------------- It's nice to be importand, but it's more importand to be nice © Scooter |
|||
|
||||
LamerTM |
|
||||||||||||
Шустрый ![]() Профиль Группа: Участник Сообщений: 97 Регистрация: 11.3.2006 Репутация: нет Всего: 0 |
О, мне тут уже написали еще.
![]()
Массив этот из записей типа record. Если коротко то так:
![]() |
||||||||||||
|
|||||||||||||
LamerTM |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 97 Регистрация: 11.3.2006 Репутация: нет Всего: 0 |
Пока решил так: при загрузке большого списка файлов массив сразу устанавливается на размер равный количеству файлов. Думаю неудобств (и глюков
![]() |
|||
|
||||
Romkin |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 189 Регистрация: 14.11.2006 Где: Москва Репутация: 2 Всего: 5 |
||||
|
||||
ShadeSt |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 256 Регистрация: 9.8.2005 Где: Россия, г. Ставро поль Репутация: нет Всего: 7 |
это что же получается, что для хранения файлика размером 10 байт, мне надо будет 100 байт???? с этим никто не спорит, но смысл переполнения памяти непонятен. это насколько я понимаю сложность алгоритма выраженная формулой. каким боком она относится к памяти ? киньте в меня ссылкой и я пойду учить матчасть. -------------------- It's nice to be importand, but it's more importand to be nice © Scooter |
|||
|
||||
Alexeis |
|
|||
![]() Амеба ![]() Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 109 Всего: 459 |
LamerTM, Возможно память фрагментируется сильно и уже не остается места на выделение одного непрерывного фрагмента. Потому с такими объемами лучше работать уже как с файлами отображаемыми в память, так не создается подкачка и скорость намного выше, а доступ так как будто это была бы обычная память.
-------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
Romkin |
|
||||
Бывалый ![]() Профиль Группа: Участник Сообщений: 189 Регистрация: 14.11.2006 Где: Москва Репутация: 2 Всего: 5 |
Если будешь считывать побайтно, и на каждый байт делать SetLength, как предложено - то да. У тебя, упрощенно, будет 10 участков памяти от 1 до 10 байт размером. При этом 9 из них использоваться не будут, нно память менеджер так просто не отдаст ![]()
А почему бы и нет? Асимптотика может относиться как ко времени, так и к размеру памяти. SetLength же что делает? Выделяет новый блок памяти нужного размера, и копирует туда содержимое. Старый помечается как неиспользуемый. Вот только проблема в том, что постоянно требуется блок памяти все большего размера, и из неиспользованных его подобрать нельзя, все время берется свежий блок. Менеджер памяти Delphi Динамические массивы в Delphi А вот что можно сделать: Динамическая таблица |
||||
|
|||||
ShadeSt |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 256 Регистрация: 9.8.2005 Где: Россия, г. Ставро поль Репутация: нет Всего: 7 |
Romkin, за ссылки спасибо, вечером почитаю..
-------------------- It's nice to be importand, but it's more importand to be nice © Scooter |
|||
|
||||
LamerTM |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 97 Регистрация: 11.3.2006 Репутация: нет Всего: 0 |
Romkin, Спасибо за ссылки! Еще не все прочитал, там много всего. А вот еще вопрос. Есть массив, а я хочу увеличить его размер. Это всегда будет новый фрагмент памяти выделяться, а старый будет бездействовать? Это ж может постоянно накапливаться и потом проявиться в виде глюка очередного. Может есть какая нибудь фунция типа дефрагментации памяти? А то я с массивами так много работаю, их много, и размеры большие могут быть. Тут выяснилось что я работать не умею. Ромкину бы плюса в репу дал, но не могу, постов мало! |
|||
|
||||
Romkin |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 189 Регистрация: 14.11.2006 Где: Москва Репутация: 2 Всего: 5 |
Блок будет помечен как свободный, при первой возможности будет использован. Менеджер памяти также делает и дефрагментацию, когда нужно и можно. Добавлено @ 16:58 А если массив большой - можно работать и через TMemoryStream или TList (TObjectList), они выделяют память вне кучи, и очень неплохо. |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Delphi: Общие вопросы" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |