Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Динамические массивы - вопрос выделения памяти. Out of memory  [new]
m52
Member

Откуда:
Сообщений: 702
Здравствуйте,

Delphi XE8
Вопрос про выделение памяти.

Мне необходимо экономно выделять RAM память для хранения списка файлов. Программа рекурсивно прочитывает с диска список файлов и кладет их в мои структуры TFileInfo (для хранения информации о каждом файле я заранее выделяю место new/dispose в куче), а указатели на каждый блок в памяти я храню в динамическом массиве.

Проблема: Вроде бы память под хранение указателей выделяется экономно, но если файлов слишком много (около 2-3 млн), то программа не может найти непрерывный кусок памяти в куче под динам.массив указателей и выдает "Out of memory".

"Вся соль", как я понял, в выделении непрерывного куска памяти. Но динам.массив мне нравится тем, что к элементам можно обращаться по индексу, в отличии от связанного списка. Чем можно заменить динамический массив? Может TStringList - в нем тоже можно обращаться по индексу, но я не знаю, как выделяется память для StringList - если тоже непрерывным куском, то такая же засада, как и с динамическими массивами.

Что посоветуете, где хранить указатели?

Заранее благодарен за советы.
2 окт 18, 08:27    [21692151]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
zinpub
Member

Откуда:
Сообщений: 296
m52,

А нельзя выделять память кусками поменьше?
2 окт 18, 08:35    [21692159]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
wadman
Member

Откуда: Санкт-Петербург
Сообщений: 24623
m52
но я не знаю, как выделяется память для StringList

Исходники же доступны.

Я-бы использовал одно из двух:
1. TList и производные (с хэшами, например).
2. Связанный список.
2 окт 18, 08:36    [21692160]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
zinpub
Member

Откуда:
Сообщений: 296
3 млн указателей - приблизительно 12Мб... система такой кусок памяти не может найти? Это сильно странно.
2 окт 18, 08:39    [21692165]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
MBo
Member

Откуда:
Сообщений: 64
m52,

От связанных списков толку очень мало, и их применение оправдано только в специфических случаях. К экономии памяти их использование не приведёт.

Списочные структуры (List, TStringlist) при расширении, когда места мало, выделяют новый массив длиной на четверть больше. Однако менеджер памяти должен освободить старый участок (с этим были проблемы во времена D6-7 - тогда менеджер был ленив и при постоянном расширении массива на единицу можно было забить всю память, сейчас это не так актуально).

Уменьшить количество перераспределений памяти можно, задав Capacity сразу разумное значение.

Однако память под указатели явно меньше, чем под данные - есть ли уверенность, что память под данные корректно обрабатывается, вовремя освобождается?

Думаю, стоит показать важные куски кода.
2 окт 18, 08:52    [21692176]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
Aleksandr Sharahov
Member

Откуда: Москва
Сообщений: 1682
m52,

что мешает использовать многомерные динамические массивы?
2 окт 18, 08:53    [21692177]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
Tactical Nuclear Penguin
Member

Откуда: холодно тут
Сообщений: 2596
можно сделать класс с этими TFileInfo и использовать TObjectList например...
2 окт 18, 08:57    [21692182]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
zinpub
Member

Откуда:
Сообщений: 296
MBo,

Ну не на четверть...

Первый столбец реальное кол-во элементов, второй Capacity - TstringList
000001 - 000004
000005 - 000008
000009 - 000012
000013 - 000028
000029 - 000044
000045 - 000060
000061 - 000076
000077 - 000095
000096 - 000118
000119 - 000147
000148 - 000183
000184 - 000228
000229 - 000285
000286 - 000356
000357 - 000445
000446 - 000556
000557 - 000695
000696 - 000868
000869 - 001085
001086 - 001356
001357 - 001695
001696 - 002118
002119 - 002647
002648 - 003308
003309 - 004135
004136 - 005168
005169 - 006460
006461 - 008075
008076 - 010093
2 окт 18, 09:00    [21692184]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
zinpub
Member

Откуда:
Сообщений: 296
Хотя да, пардон... с утра не углядел :-)
2 окт 18, 09:03    [21692186]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
Соколинский Борис
Member

Откуда: Москва
Сообщений: 8726
m52,
посоветую прежде всего разобраться, почему память так фрагментируется.
Даже если эту частную задачу решить, потом все равно что-то вылезет.
2 окт 18, 09:04    [21692188]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
m52
Member

Откуда:
Сообщений: 702
Вопрос в том, как выделяется память под TStringList, а не на сколько увеличивается. Если выделяется цельным куском, как для динамич. массива, то засада.

> 3 млн указателей - приблизительно 12Мб
Да, 12 МБ - мало, но даже такого цельного куска в куче может не найтись, даже если на ПК 15 ГБ RAM.

Про 3D динам.массив - тоже идея, если для каждой строки такого массива будет выделяться отдельный кусок в памяти, не пристыкованный к уже имеющемуся куску.
2 окт 18, 09:06    [21692190]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
zinpub
Member

Откуда:
Сообщений: 296
m52
Вопрос в том, как выделяется память под TStringList, а не на сколько увеличивается. Если выделяется цельным куском, как для динамич. массива, то засада.

> 3 млн указателей - приблизительно 12Мб
Да, 12 МБ - мало, но даже такого цельного куска в куче может не найтись, даже если на ПК 15 ГБ RAM.

Про 3D динам.массив - тоже идея, если для каждой строки такого массива будет выделяться отдельный кусок в памяти, не пристыкованный к уже имеющемуся куску.


Цельным - там массив такой же внутри

  TPointerList = array[0..MaxListSize - 1] of Pointer;
2 окт 18, 09:14    [21692201]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
Aleksandr Sharahov
Member

Откуда: Москва
Сообщений: 1682
zinpub,

не совсем
2 окт 18, 09:17    [21692205]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
zinpub
Member

Откуда:
Сообщений: 296
Aleksandr Sharahov,

Вроде он самый

function TList.Get(Index: Integer): Pointer;
begin
  if (Index < 0) or (Index >= FCount) then
    Error(@SListIndexError, Index);
  Result := FList^[Index];
end;
2 окт 18, 09:26    [21692210]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
goldmi45
Member

Откуда:
Сообщений: 1065
память фрагментируется, когда часто вызывается SetLength для динамического массива. Как часто вы изменяете размер этого динамического массива? Можно ли изменять (устанавливать) размер массива кусками не по одной структуре, а, скажем, сразу сотней или тысячей? Тогда массив не так часто будет пересоздаваться и память не будет так фрагментироваться....
2 окт 18, 09:28    [21692212]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
Aleksandr Sharahov
Member

Откуда: Москва
Сообщений: 1682
zinpub
m52
Вопрос в том, как выделяется память под TStringList, а не на сколько увеличивается. Если выделяется цельным куском, как для динамич. массива, то засада.

> 3 млн указателей - приблизительно 12Мб
Да, 12 МБ - мало, но даже такого цельного куска в куче может не найтись, даже если на ПК 15 ГБ RAM.

Про 3D динам.массив - тоже идея, если для каждой строки такого массива будет выделяться отдельный кусок в памяти, не пристыкованный к уже имеющемуся куску.


Цельным - там массив такой же внутри

  TPointerList = array[0..MaxListSize - 1] of Pointer;


zinpub,

в этой же цитате речь и о многомерных массивах,
для них память выделяется иначе
2 окт 18, 09:35    [21692221]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
zinpub
Member

Откуда:
Сообщений: 296
Aleksandr Sharahov,

Там да массив ссылок на массивы вроде
2 окт 18, 09:42    [21692226]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
MBo
Member

Откуда:
Сообщений: 64
Тест в Berlin отрабатывает за пару секунд, выделяя 15 миллионов раз память до гигабайта включительно. Переполнения нет (для полутора гиг - будет, система 32-разрядная)

var
  A: array of Byte;
  n : Integer;
begin
  n := 1;
  while n < 1024 * 1024 * 1024 do begin
    SetLength(A, n);
    A[n-1] := 31;
    n := n + 17;
  end;
  Caption := IntToStr(A[High(A)]);
2 окт 18, 09:43    [21692228]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 688
m52

> 3 млн указателей - приблизительно 12Мб
Да, 12 МБ - мало, но даже такого цельного куска в куче может не найтись, даже если на ПК 15 ГБ RAM.


Для 32-битного Win-приложения доступна виртуальная память 2 ГБ в независимости от того, сколько на ПК установлено ОЗУ. Эти 2 ГБ не являются непрерывной областью, скорее всего и 1ГБ непрерывной области Вы не обнаружите. Однако этож как можно засрать память, чтобы в ней не нашлось цельного куска 12 МБ? Начиная в Delphi 2007 (или даже 2006) используется "новый" менеджер памяти (FastMM), с которым стало очень сложно добиться сильной фрагментации памяти.
2 окт 18, 12:51    [21692506]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
m52
Member

Откуда:
Сообщений: 702
Вы не забывайте, что в куче еще выделяется место для 3 млн структур типа TFileInfo - именно они занимают большую часть памяти в куче, хотя каждый элемент - это отдельный маленький блок, под который выделена память с помощью new(), поэтому эти структурки не требуют непрерывного массива памяти, в отличии от динамического массива указателей.
2 окт 18, 13:11    [21692535]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
Котовасия
Member

Откуда:
Сообщений: 1187
m52> место для 3 млн структур типа TFileInfo


Может, ты и все 3 млн файлов открытыми держишья? Рассказывай уж все сразу.
2 окт 18, 13:15    [21692543]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3631
DmSer
m52
> 3 млн указателей - приблизительно 12Мб
Да, 12 МБ - мало, но даже такого цельного куска в куче может не найтись, даже если на ПК 15 ГБ RAM.


Для 32-битного Win-приложения доступна виртуальная память 2 ГБ в независимости от того, сколько на ПК установлено ОЗУ. Эти 2 ГБ не являются непрерывной областью, скорее всего и 1ГБ непрерывной области Вы не обнаружите. Однако этож как можно засрать память, чтобы в ней не нашлось цельного куска 12 МБ? Начиная в Delphi 2007 (или даже 2006) используется "новый" менеджер памяти (FastMM), с которым стало очень сложно добиться сильной фрагментации памяти.

Я в это всё не верю.
Если нет у менеджера - он попросит у системы эти 12мб. А система их найдет всегда, хоть на свопе.
Тут проблема в том, вангую, что уже 2Гб растрачены.
2 окт 18, 13:27    [21692561]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3631
MBo
Однако менеджер памяти должен освободить старый участок (с этим были проблемы во времена D6-7 - тогда менеджер был ленив и при постоянном расширении массива на единицу можно было забить всю память

Не замечал такого поведения за всю жизнь.
Когда TList'у не хватает массива указателей - он пытается сделать реаллок, и если не получается - то создает новый массив бОльшего размера, копирует туда и освобождает старый.
Как в таком подходе можно "забить всю память" - я не знаю. Нормальный менеджер памяти в D6-D7 - FastMM, кстати, тоже вроде.
2 окт 18, 13:30    [21692569]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
delphinotes
Member

Откуда: Санкт-Петербург
Сообщений: 308
Тут уже несколько раз написали про фрагментацию памяти, и смена менеджера памяти вряд ли поможет.

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

Это легко представить, если нарисовать на листочке в клеточку: вот массив из одного элемента, потом делаем реаллок - из двух (но старт массива уже в другой части доступной области), затем из трёх и так далее. Каждый раз - всё больше и больше (и каждый раз старт массива смещается).

Решается просто: или сразу выделяем большое кол-во памяти под массив + переменная, показывающая реальное кол-во элементов, либо переходим на TList и задаём ему Capacity ~ кол-во файлов (который как раз и нужен, чтобы не делать постоянные реаллоки).
2 окт 18, 14:05    [21692630]     Ответить | Цитировать Сообщить модератору
 Re: Динамические массивы - вопрос выделения памяти. Out of memory  [new]
wadman
Member

Откуда: Санкт-Петербург
Сообщений: 24623
delphinotes
и задаём ему Capacity ~ кол-во файлов

Знать-бы еще заранее количество файлов.
2 окт 18, 14:14    [21692649]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Delphi Ответить