-
Pcrepair © (13.12.17 23:14) [0]Добрый день. Есть следующая ситуация
РС(i7 8Gb Win7 x64 + RAD XE3), приложения можно компилировать только в 32 разр. режиме
- список грузит файл с диска
Procedure RestorData;
begin
try
CS.Enter;
try
gStore.LoadFromFile(ExtractFilePath(Application.ExeName)+'Store.txt');
finally
CS.Leave;
end;
except
on E:Exception do
begin
ShowMessage('RestorDataParams = '+'('+E.Message+')');
end;
end;
end;
- при определенных условиях(не всегда) выскакивает ошибка:
First chance exception at $7561C54F. Exception class EOutOfMemory with message 'Out of memory'. Process loader.exe (3736)
в основном ошибка выскакивает при попытке загрузить в список файл размером в 300 мб с числом строк около 3 млн. при запуске программы,
или выгрузить список обратно при выходе из программы.
- список со строками совершенно необходим(стек со списком УРЛ для загрузки), хотя...
Вопросы :
1. вообще эта проблема решаема для TStringList
2. если список не тянет, что еще можно использовать для загрузки-выгрузки милионов строк(до 500 символов в строке) из какого либо хранилища на ЖД -
kilkennycat © (14.12.17 10:44) [1]1. да.
2. TStringList
TStringList служит для отображения. отобразить он может лишь столько, сколько мониторов у компа. Остальное храните там, где оно уже хранится. -
Pcrepair © (14.12.17 10:52) [2]с листбокс не перепутал? для отображения ахаха
-
KilkennyCat © (14.12.17 11:08) [3]нет, перепутал с вариантом ответить или нет. надо было не отвечать.
-
Sha © (14.12.17 12:37) [4]> список со строками совершенно необходим(стек со списком УРЛ для загрузки)
Предполагается ли затем все эти УРЛ также одновременно загрузить?
Просто вопрос. -
> (стек со списком УРЛ для загрузки)
- при условии последовательного доступа к элементам списка - проще хранить единым блоком с строке и парсить на лету...
Либо отдельно построить список смещений. Либо честный связный список...
Проблема древняя как мир
LoadFromFile():
1. Файл целиком загружается в строку.
2. SetTextStr()
- где на каждом элементе происходит выделение памяти под очередную подстроку и перевыделение памяти под очередной размер списка.
То есть на определённом этапе у нас
- выделена память под все содержимое файла
- выделена память под N-подстрок
- выделена память под array[N] of TStringItem
а нам надо выделить память под array[N+N div 4] of TStringItem, т. к. N-подстрок с большой долей вероятности фрагментируют память - и расширение блока памяти на месте невозможно.
(...|array[n]|...substr[N-1]|)
Сценарий сильно зависит от соотношения количства и длинны элементов, чаще всего(для коротких элемнтов) - они все размещаются на пространстве освобожденном от массива предыдущего размера.
Если заранее знать количество строк - проблему можно временно решитьgStore.Capacity:= MaxN;
- если (<размер фала> * 2 + O(N) + MaxN * sizeof(TStringItem)) - не вылезает за размер доступной памяти.
O(N) - оверхэд на хранение N строк(TStrRec + списки менеджера памяти).
> для загрузки-выгрузки
TMemoryStream.LoadFromFile();
parse_and_do_something(PChar(TMemoryStream.Memory), TMemoryStream.Size); -
Pcrepair © (14.12.17 16:15) [6]
> Предполагается ли затем все эти УРЛ также одновременно загрузить?
предполагается, но не одновременно а поочередно, причем выборка текущего УРЛ через РандомРеиндж
пока что использование АссасинФайл вполне помогло в деле загрузки 3млн. строк из текстового файла в переменную(список). правда грузится подольше, но это не принципиально -
Sha © (14.12.17 21:19) [7]В таком случае непонятно, зачем грузить строки.
Можно держать их в любой БД или сортированном файле. -
> или сортированном файле
- проблема не в сортировке, а в равномерном распределении РандомРеиндж по элементам. Если делать случайную выборку по полному размеру файла - вероятность попадания будет зависеть от длины URL(в сравненнии с количеством элементов - перекос мизерный, но лучше избегать математических ловушек, т.к. если отсортировать элементы по длине - получим явно выраженную линейную функцию распределения)... То есть, нужно либо нормализовать длину строки, либо строить индекс смещений. Если нужна выборка с отсечением дублей - однозначно индекс, который можно рэндомизировать при построении, а потом делать прямой обход.
З.Ы. Главное не удивляться, что случайный список всегда получется одинаковый, при одинаковом начальном RandSeed. :)
> держать их в любой БД
- я так полагаю - список URL быстро устаревает, и скорее всего периодически генерируется какой-то третьей стороной в самом элементарном виде, и БД превратится в run-time прослойку(тот самый микроскоп)...
Хотя уже замечал тенденцию использовать LiteSQL в роли универсального контейнера... -
Sha © (15.12.17 09:40) [9]> проблема не в сортировке, а в равномерном распределении РандомРеиндж
я даже не догадываюсь, что такое этот ваш РандомРеиндж,
но если это то, что я думаю, то можно отсортировать по нему
и просто читать файл последовательно-закольцовано ))