SASGIS - SAS.Планета
View Issue Details
0001837SAS.Планета[All Projects] Багpublic27-02-2013 13:1302-07-2013 06:53
Garl 
zed 
normalmajoralways
resolvedfixed 
Windows7Professional
.Nightly 
131111131111 
0001837: Out of memory при поиске по большому .txt файлу
userdata\txt\allCountries.txt 982Мб
при поиске долго ищет, и вылетает в ошибку.
если подскажите как лечить - попробую вылечить самостоятельно
поиск
? SASPlanet.Debug.elf (68,205) 27-02-2013 13:13
http://www.sasgis.org/mantis/file_download.php?file_id=1275&type=bug
? u_MappedFile.pas (2,730) 27-02-2013 14:15
http://www.sasgis.org/mantis/file_download.php?file_id=1276&type=bug
Issue History
27-02-2013 13:13GarlNew Issue
27-02-2013 13:13GarlFile Added: SASPlanet.Debug.elf
27-02-2013 13:14GarlTag Attached: поиск
27-02-2013 13:49vdemidovNote Added: 0010653
27-02-2013 13:57zedNote Added: 0010654
27-02-2013 14:00GarlNote Added: 0010655
27-02-2013 14:09zedNote Added: 0010656
27-02-2013 14:12GarlNote Added: 0010657
27-02-2013 14:15zedFile Added: u_MappedFile.pas
27-02-2013 14:22zedNote Added: 0010658
27-02-2013 14:22zedNote Edited: 0010658bug_revision_view_page.php?bugnote_id=10658#r5157
28-02-2013 04:45GarlAssigned To => Garl
28-02-2013 04:45GarlStatusnew => resolved
28-02-2013 04:45GarlResolutionopen => fixed
28-02-2013 04:45GarlFixed in Version => 131111
28-02-2013 04:45GarlTarget Version => 131111
02-03-2013 08:33vdemidovStatusresolved => confirmed
02-03-2013 08:33vdemidovResolutionfixed => reopened
02-03-2013 08:33vdemidovFixed in Version131111 =>
02-03-2013 09:16vasketsovNote Added: 0010760
02-03-2013 09:17vasketsovNote Edited: 0010760bug_revision_view_page.php?bugnote_id=10760#r5205
02-03-2013 09:31vdemidovNote Added: 0010761
02-03-2013 10:37zedNote Added: 0010762
02-03-2013 10:49zedNote Edited: 0010762bug_revision_view_page.php?bugnote_id=10762#r5207
02-03-2013 11:04vasketsovNote Added: 0010764
02-03-2013 11:10zedNote Added: 0010765
02-03-2013 11:22vasketsovNote Added: 0010767
06-03-2013 06:20vdemidovStatusconfirmed => resolved
06-03-2013 06:20vdemidovFixed in Version => 131111
06-03-2013 06:20vdemidovResolutionreopened => fixed
06-03-2013 06:20vdemidovAssigned ToGarl => zed
02-07-2013 06:53vdemidovProduct Version131111 => .Nightly

Notes
(0010653)
vdemidov   
27-02-2013 13:49   
Не считывать файл полностью в память, а читать постепенно прямо из файла
(0010654)
zed   
27-02-2013 13:57   
Просто нужно читать файл построчно. Там такой формат, что одна строка - один населённый пункт. Очень удобно.

// Open existing text file and show first line
procedure ReadTxt;
var
  F: Textfile;
  str: string;
begin
  AssignFile(f, 'c:\ek.txt'); {Assigns the Filename}
  Reset(f); {Opens the file for reading}
  Readln(f, str);
  ShowMessage('1. line of textfile:' + str);
  Closefile(f); {Closes file F}
end;
(0010655)
Garl   
27-02-2013 14:00   
построчно не проиграем в производительности?
и в файле конец строки задан одним символом $0A
(0010656)
zed   
27-02-2013 14:09   
Сильно не проиграешь. А можешь и наоборот выиграть, если искомая комбинация будет найдена где-нибудь в начале файла.

Ещё, как вариант, можно открывать файл как MemoryMapped - тогда винда прозрачно оптимизирует считывание данных из файла. Но придётся работать с PChar и вручную искать конец строки.
(0010657)
Garl   
27-02-2013 14:12   
ну мы и так вручную ищем КонецСтроки
есть пример работы с MemoryMapped?
(0010658)
zed   
27-02-2013 14:22   
Прикрепил юнит.

Использовать можно как-то так:

VFile := TMappedFile.Create('c:\test.txt');
VData := PByte(VFile.Content);
for I := 0 to VFile.Size - 1 do begin
  if VData^ = $0A then begin
  // найден конец строки
  end;
  Inc(VData);
end;
VFile.Free;

(0010760)
vasketsov   
02-03-2013 09:16   
(edited on: 02-03-2013 09:17)
Есть подозрение, что можно читать блоками скажем по 4k. Всё равно системный кэш будет поднимать с диска такими (или аналогичными в соответствии с настройками оси и железа) блоками. Ну и в этом случае ищется либо начало искомого текста либо конец строки (если нашлось начало текста - ищем после него конец строки, при необходимости подгружая следующий блок, потом проверяем что нашли искомое, нет - перепрыгиваем на длину искомой строки и продолжаем), и вся эта котовасия покуда или не найдётся или файл не кончится. Хотя может там сложнее формат, и так не получится.
А посрочно конечно медленно, да и делает RTL то же самое примерно, поднимает с диска в кэш и ищет конец строки, выплёвывает их покуда есть чего, не зная ни о формате, ни о том, насколько можно упростить проверку, чего нашли.
В любом случае чиать весь гиговый файл враз конечно неправильно.

(0010761)
vdemidov   
02-03-2013 09:31   
>В любом случае чиать весь гиговый файл враз конечно неправильно.
Как и мапить его целиком в адресное пространство.
Нужно сделать нормальное чтение, например с буферизацией при помощи MapViewOfFile по кускам.
(0010762)
zed   
02-03-2013 10:37   
(edited on: 02-03-2013 10:49)
Мне почему-то казалось, что винда должна была сама мапить файл по-странично (теми же кусками по 4k), с периодическим сбрасыванием ненужных страниц. Но почему-то всё не так (:

Похоже, что периодический вызов VirtualUnlock мог бы решить проблему:
http://stackoverflow.com/questions/1880714/createfilemapping-mapviewoffile-how-to-avoid-holding-up-the-system-memory/1882478

(0010764)
vasketsov   
02-03-2013 11:04   
Не понимаю как VirtualUnlock может помочь в этом, это вообще "из другой оперы". Когда мапится файл, создаётся объект типа "секция" (ZwCreateSection+ZwMapViewOfSection), до Mm от него как до Луны в известной позе.

>с периодическим сбрасыванием ненужных страниц
А откуда известно, что страницы больше не нужны?

зы. Я б ограничился обычным файловым чтением в статический буфер, файл открывается для последовательного чтения, буфер дописывается в string, и далее поиск, ещё поиск, ещё поиск, не нашли - ещё читаем буферок, и т.п... зачем тут файл-то маппить в память?
(0010765)
zed   
02-03-2013 11:10   
>А откуда известно, что страницы больше не нужны?
Никто в них в данный момент времени не пишет/не читает = не нужны.

>зачем тут файл-то маппить в память?
Предполагалось, что не будет жрать память и не нужно с буферками напрягаться.
(0010767)
vasketsov   
02-03-2013 11:22   
>Никто в них в данный момент времени не пишет/не читает
Ну они если и упадут, то только в своп (секция-то не меняется, и размер её не меняется, и атрибуты страниц тоже, так что вытеснены они могут быть на общих основаниях). Вот и осталось понять зачем это, тем более что всё равно это не панацея и не избавляет от возни с буферами.

>и не нужно с буферками напрягаться
А всё равно нужно будет напрягаться. Доступ-то последовательный. Соответственно если граница буфера попадает посередине искомого слова - "напряжение" и возникает, чтение следующего, стыковка, поиск и т.п.

К сожалению я не знаю простой нормальный системный способ открыть файл для последовательного доступа на чтение и тянуть его построчно, ограничив размер "окошка" и не долбясь с буферами, даже на Native NT API.