Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Непонятки с памятью, Динамический массив и SetLength 
:(
    Опции темы
LamerTM
Дата 23.11.2006, 11:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 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 (то есть когда меняется размер массива) загрузка происходит гораздо медленнее, и постоянно замедляется с каждым новым файлом, то есть очередное увеличение массива на единицу, с каждым разом происходит всё большее время.

Вот я чего не могу понять, - что это такое? И что делать? Я в ступоре. Хочу чтобы размер массива можно было увеличивать по ходу загрузки файлов, но это приводит к глюку.

PM MAIL   Вверх
ShadeSt
Дата 23.11.2006, 12:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 256
Регистрация: 9.8.2005
Где: Россия, г. Ставро поль

Репутация: нет
Всего: 7



а для чего используется тот массив?
для хранения имен файлов или для чего то другого?
сам по себе SetLength такого делать не может, и :
Код

If there is not enough memory available to reallocate the variable, SetLength raises an EOutOfMemory exception.

имхо, у тебя кто-то кушает память.
а вообще то хотелось бы глянуть на код.




--------------------
It's nice to be importand, but it's more importand to be nice © Scooter
PM MAIL ICQ Jabber   Вверх
Romkin
Дата 23.11.2006, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 189
Регистрация: 14.11.2006
Где: Москва

Репутация: 2
Всего: 5



Цитата(LamerTM @  23.11.2006,  11:59 Найти цитируемый пост)
Первый: массив изначально имеет длину 0, после чего перед загрузкой каждого файла увеличивается на 1 функцией SetLength. Это в конце концов приводит к глюку out of memory при большом числе файлов.

Естественно. Это называется "поиздеваемся над менеджером памяти" smile
Сам посмотри: SetLength выделяет память. Хорошо. Потом Требуется памяти на 1 больше. В результате в то, что выделено, уже не лезет - выделяется новый блок, а старый идет в пул свободных. А вернется он к системе еще не скоро, работа идет ;)
А сколько всего тебе надо - сам посчитай.

Цитата(LamerTM @  23.11.2006,  11:59 Найти цитируемый пост)
Второй способ: массив изначально устанавливается большого размера (массив динамический) функцией SetLength, после чего в него грузятся файлы. Ошибок при этом нет! Но это фиговый способ, т.к. жрет много памяти даже когда файлов мало.

А этот способ хороший. Только память надо выделять не "от балды", а точно по размеру файла. А его узнать очень просто.

И еще вопрос: нафига тебе это надо? Используй TFileStream...
И загружать файлы лучше когда надо посмотреть, а не заранее. Не верю я, что этот процесс долгий.
PM ICQ   Вверх
LamerTM
Дата 23.11.2006, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 11.3.2006

Репутация: нет
Всего: 0



Я и не программист.smile Программист в прошлом, в далеком детствеsmile

Покороче:

Есть динамический массив и 266 файлов. И два способа загрузки файлов в этот массив.

Первый способ: массив изначально имеет длину 0, после чего перед загрузкой каждого файла увеличивается на 1 функцией SetLength. Сначала все грузится нормально, но потом функция SetLength выдает out of memory (при попытке увеличить длину массива с 177 до 178 элементов).

Второй способ: массив изначально устанавливается большого размера (длина ставится 270, массив динамический) функцией SetLength, после чего в него грузятся файлы. Ошибок при этом нет! Но это фиговый способ, т.к. жрет много памяти даже когда файлов мало.

Вопрос: почему глючит способ №1.
PM MAIL   Вверх
Romkin
Дата 23.11.2006, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 189
Регистрация: 14.11.2006
Где: Москва

Репутация: 2
Всего: 5



Цитата(LamerTM @  23.11.2006,  12:41 Найти цитируемый пост)
Вопрос: почему глючит способ №1.

А я уже ответил smile Потому, что памяти тебе требуется на самом деле примерно N^2, где N - размер файлов
PM ICQ   Вверх
ShadeSt
Дата 23.11.2006, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 256
Регистрация: 9.8.2005
Где: Россия, г. Ставро поль

Репутация: нет
Всего: 7



Цитата(Romkin @  23.11.2006,  12:50 Найти цитируемый пост)
Потому, что памяти тебе требуется на самом деле примерно N^2, где N - размер файлов

Это почему??

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


--------------------
It's nice to be importand, but it's more importand to be nice © Scooter
PM MAIL ICQ Jabber   Вверх
LamerTM
Дата 23.11.2006, 13:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 11.3.2006

Репутация: нет
Всего: 0



О, мне тут уже написали еще.smile Сейчас отвечу, сорри, я занят тут.

Цитата
а для чего используется тот массив?
для хранения имен файлов или для чего то другого?

Массив этот из записей типа record. Если коротко то так:

Код

type 
 TElem=record // элементы файла (файлы из TElem)
   f1: Double;
   f2: Double; // ну и так далее, тут только простые Double
 end;

TElemArray=array of TElem; // массив хранящий данные из файла

TFileData=record
 Data: TElemArray; // - сюда грузятся данные из файла.
 // еще дополнительные параметры тут есть, но это не важно
end;

var
FilesArray=array of TFileData; // тот самый массив.



Цитата
Естественно. Это называется "поиздеваемся над менеджером памяти" 
Сам посмотри: SetLength выделяет память. Хорошо. Потом Требуется памяти на 1 больше. В результате в то, что выделено, уже не лезет - выделяется новый блок, а старый идет в пул свободных. А вернется он к системе еще не скоро, работа идет ;)
А сколько всего тебе надо - сам посчитай.
Спасибо. Всегда удивлялся как удается так быстро увеличить длину массива на 1 не выделяя новый блок, а оказывается выделяется. Но в диспетчере задач не отображается переполнение памяти - вот в чем прикол, или там и не должно отображаться это?
Цитата
И еще вопрос: нафига тебе это надо? Используй TFileStream...
Не знаю что такое TFileStream. Сорри. Посмотрю.
Цитата
И загружать файлы лучше когда надо посмотреть, а не заранее. 
Нет, мне лучше сразу, потому что потом по ним много вычислений идет и каждый раз грузить больше времени займёт.
Цитата
А я уже ответил  Потому, что памяти тебе требуется на самом деле примерно N^2, где N - размер файлов
Когда я тот пост написал я еще твоего ответа не видел.smile
PM MAIL   Вверх
LamerTM
Дата 23.11.2006, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 11.3.2006

Репутация: нет
Всего: 0



Пока решил так: при загрузке большого списка файлов массив сразу устанавливается на размер равный количеству файлов. Думаю неудобств (и глюковsmile)не будет, а там посмотрим.
PM MAIL   Вверх
Romkin
Дата 23.11.2006, 14:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 189
Регистрация: 14.11.2006
Где: Москва

Репутация: 2
Всего: 5



Цитата(ShadeSt @  23.11.2006,  12:58 Найти цитируемый пост)
 потому как если это массив строк в которых просто хранятся имена файлов, то это уж никаким боком не должно приводить к переполнению памяти.

Да хоть массив байт smile Асимптотика не зависит от этого.
PM ICQ   Вверх
ShadeSt
Дата 23.11.2006, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 256
Регистрация: 9.8.2005
Где: Россия, г. Ставро поль

Репутация: нет
Всего: 7



Цитата(Romkin @  23.11.2006,  12:50 Найти цитируемый пост)
Потому, что памяти тебе требуется на самом деле примерно N^2, где N - размер файлов


это что же получается, что для хранения файлика размером 10 байт, мне надо будет 100 байт????


Цитата(Romkin @  23.11.2006,  14:18 Найти цитируемый пост)
Да хоть массив байт 

с этим никто не спорит, но смысл переполнения памяти непонятен.


Цитата(Romkin @  23.11.2006,  14:18 Найти цитируемый пост)
Асимптотика

это насколько я понимаю сложность алгоритма выраженная формулой.
каким боком она относится к памяти ?
киньте в меня ссылкой и я пойду учить матчасть.


--------------------
It's nice to be importand, but it's more importand to be nice © Scooter
PM MAIL ICQ Jabber   Вверх
Alexeis
Дата 23.11.2006, 14:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



LamerTM, Возможно память фрагментируется сильно и уже не остается места на выделение одного непрерывного фрагмента. Потому с такими объемами лучше работать уже как с файлами отображаемыми в память, так не создается подкачка и скорость намного выше, а доступ так как будто это была бы обычная память.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Romkin
Дата 23.11.2006, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 189
Регистрация: 14.11.2006
Где: Москва

Репутация: 2
Всего: 5



Цитата(ShadeSt @  23.11.2006,  14:34 Найти цитируемый пост)
это что же получается, что для хранения файлика размером 10 байт, мне надо будет 100 байт????


Если будешь считывать побайтно, и на каждый байт делать SetLength, как предложено - то да. У тебя, упрощенно, будет 10 участков памяти от 1 до 10 байт размером. При этом 9 из них использоваться не будут, нно память менеджер так просто не отдаст smile


Цитата(ShadeSt @  23.11.2006,  14:34 Найти цитируемый пост)
это насколько я понимаю сложность алгоритма выраженная формулой.
каким боком она относится к памяти ?
киньте в меня ссылкой и я пойду учить матчасть.

А почему бы и нет? Асимптотика может относиться как ко времени, так и к размеру памяти. 
SetLength же что делает? Выделяет новый блок памяти нужного размера, и копирует туда содержимое. Старый помечается как неиспользуемый. Вот только проблема в том, что постоянно требуется блок памяти все большего размера, и из неиспользованных его подобрать нельзя, все время берется свежий блок.
Менеджер памяти Delphi
Динамические массивы в Delphi
А вот что можно сделать:
Динамическая таблица
PM ICQ   Вверх
ShadeSt
Дата 23.11.2006, 15:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 256
Регистрация: 9.8.2005
Где: Россия, г. Ставро поль

Репутация: нет
Всего: 7



Romkin, за ссылки спасибо, вечером почитаю..




--------------------
It's nice to be importand, but it's more importand to be nice © Scooter
PM MAIL ICQ Jabber   Вверх
LamerTM
Дата 23.11.2006, 16:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 11.3.2006

Репутация: нет
Всего: 0



Цитата

LamerTM, Возможно память фрагментируется сильно и уже не остается места на выделение одного непрерывного фрагмента. Потому с такими объемами лучше работать уже как с файлами отображаемыми в память, так не создается подкачка и скорость намного выше, а доступ так как будто это была бы обычная память.
Понятно. Скорее всего так и есть. Объем небольшой, всего 25 метров. А что такое файлы отображаемые в память я не знаю. Потом посмотрю. Я подумаю об этом завтра(с).

Romkin, Спасибо за ссылки! Еще не все прочитал, там много всего.

А вот еще вопрос. Есть массив, а я хочу увеличить его размер. Это всегда будет новый фрагмент памяти выделяться, а старый будет бездействовать? Это ж может постоянно накапливаться и потом проявиться в виде глюка очередного. Может есть какая нибудь фунция типа дефрагментации памяти? А то я с массивами так много работаю, их много, и размеры большие могут быть. Тут выяснилось что я работать не умею.

Ромкину бы плюса в репу дал, но не могу, постов мало!
PM MAIL   Вверх
Romkin
Дата 23.11.2006, 16:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 189
Регистрация: 14.11.2006
Где: Москва

Репутация: 2
Всего: 5



Цитата(LamerTM @  23.11.2006,  16:40 Найти цитируемый пост)
 Есть массив, а я хочу увеличить его размер. Это всегда будет новый фрагмент памяти выделяться, а старый будет бездействовать?

Блок будет помечен как свободный, при первой возможности будет использован. Менеджер памяти также делает и дефрагментацию, когда нужно и можно.

Добавлено @ 16:58 
А если массив большой - можно работать и через TMemoryStream или TList (TObjectList), они выделяют память вне кучи, и очень неплохо.
PM ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1049 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.