SASGIS - SAS.Планета |
View Issue Details |
|
ID | Project | Category | View Status | Date Submitted | Last Update |
0001837 | SAS.Планета | [All Projects] Баг | public | 27-02-2013 13:13 | 02-07-2013 06:53 |
|
Reporter | Garl | |
Assigned To | zed | |
Priority | normal | Severity | major | Reproducibility | always |
Status | resolved | Resolution | fixed | |
Platform | Windows | OS | 7 | OS Version | Professional |
Product Version | .Nightly | |
Target Version | 131111 | Fixed in Version | 131111 | |
|
Summary | 0001837: Out of memory при поиске по большому .txt файлу |
Description | userdata\txt\allCountries.txt 982Мб
при поиске долго ищет, и вылетает в ошибку. |
Steps To Reproduce | |
Additional Information | если подскажите как лечить - попробую вылечить самостоятельно |
Tags | поиск |
Relationships | |
Attached Files | 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 |
Date Modified | Username | Field | Change |
27-02-2013 13:13 | Garl | New Issue | |
27-02-2013 13:13 | Garl | File Added: SASPlanet.Debug.elf | |
27-02-2013 13:14 | Garl | Tag Attached: поиск | |
27-02-2013 13:49 | vdemidov | Note Added: 0010653 | |
27-02-2013 13:57 | zed | Note Added: 0010654 | |
27-02-2013 14:00 | Garl | Note Added: 0010655 | |
27-02-2013 14:09 | zed | Note Added: 0010656 | |
27-02-2013 14:12 | Garl | Note Added: 0010657 | |
27-02-2013 14:15 | zed | File Added: u_MappedFile.pas | |
27-02-2013 14:22 | zed | Note Added: 0010658 | |
27-02-2013 14:22 | zed | Note Edited: 0010658 | bug_revision_view_page.php?bugnote_id=10658#r5157 |
28-02-2013 04:45 | Garl | Assigned To | => Garl |
28-02-2013 04:45 | Garl | Status | new => resolved |
28-02-2013 04:45 | Garl | Resolution | open => fixed |
28-02-2013 04:45 | Garl | Fixed in Version | => 131111 |
28-02-2013 04:45 | Garl | Target Version | => 131111 |
02-03-2013 08:33 | vdemidov | Status | resolved => confirmed |
02-03-2013 08:33 | vdemidov | Resolution | fixed => reopened |
02-03-2013 08:33 | vdemidov | Fixed in Version | 131111 => |
02-03-2013 09:16 | vasketsov | Note Added: 0010760 | |
02-03-2013 09:17 | vasketsov | Note Edited: 0010760 | bug_revision_view_page.php?bugnote_id=10760#r5205 |
02-03-2013 09:31 | vdemidov | Note Added: 0010761 | |
02-03-2013 10:37 | zed | Note Added: 0010762 | |
02-03-2013 10:49 | zed | Note Edited: 0010762 | bug_revision_view_page.php?bugnote_id=10762#r5207 |
02-03-2013 11:04 | vasketsov | Note Added: 0010764 | |
02-03-2013 11:10 | zed | Note Added: 0010765 | |
02-03-2013 11:22 | vasketsov | Note Added: 0010767 | |
06-03-2013 06:20 | vdemidov | Status | confirmed => resolved |
06-03-2013 06:20 | vdemidov | Fixed in Version | => 131111 |
06-03-2013 06:20 | vdemidov | Resolution | reopened => fixed |
06-03-2013 06:20 | vdemidov | Assigned To | Garl => zed |
02-07-2013 06:53 | vdemidov | Product Version | 131111 => .Nightly |
Notes |
|
|
Не считывать файл полностью в память, а читать постепенно прямо из файла |
|
|
(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 то же самое примерно, поднимает с диска в кэш и ищет конец строки, выплёвывает их покуда есть чего, не зная ни о формате, ни о том, насколько можно упростить проверку, чего нашли.
В любом случае чиать весь гиговый файл враз конечно неправильно.
|
|
|
|
>В любом случае чиать весь гиговый файл враз конечно неправильно.
Как и мапить его целиком в адресное пространство.
Нужно сделать нормальное чтение, например с буферизацией при помощи 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
|
|
|
|
Не понимаю как VirtualUnlock может помочь в этом, это вообще "из другой оперы". Когда мапится файл, создаётся объект типа "секция" (ZwCreateSection+ZwMapViewOfSection), до Mm от него как до Луны в известной позе.
>с периодическим сбрасыванием ненужных страниц
А откуда известно, что страницы больше не нужны?
зы. Я б ограничился обычным файловым чтением в статический буфер, файл открывается для последовательного чтения, буфер дописывается в string, и далее поиск, ещё поиск, ещё поиск, не нашли - ещё читаем буферок, и т.п... зачем тут файл-то маппить в память? |
|
|
(0010765)
|
zed
|
02-03-2013 11:10
|
|
>А откуда известно, что страницы больше не нужны?
Никто в них в данный момент времени не пишет/не читает = не нужны.
>зачем тут файл-то маппить в память?
Предполагалось, что не будет жрать память и не нужно с буферками напрягаться. |
|
|
|
>Никто в них в данный момент времени не пишет/не читает
Ну они если и упадут, то только в своп (секция-то не меняется, и размер её не меняется, и атрибуты страниц тоже, так что вытеснены они могут быть на общих основаниях). Вот и осталось понять зачем это, тем более что всё равно это не панацея и не избавляет от возни с буферами.
>и не нужно с буферками напрягаться
А всё равно нужно будет напрягаться. Доступ-то последовательный. Соответственно если граница буфера попадает посередине искомого слова - "напряжение" и возникает, чтение следующего, стыковка, поиск и т.п.
К сожалению я не знаю простой нормальный системный способ открыть файл для последовательного доступа на чтение и тянуть его построчно, ограничив размер "окошка" и не долбясь с буферами, даже на Native NT API. |
|