Очень приятно ощущать себя не полным идиотом.
Вчера вечером я упомянул о сортировке этого огромного объема данных. Но начинать, как выяснилось, надо было не с этого, а с несколько более сложной (в плане обдумывания, а не в алгоритмическом плане) задачи.
Итак, пишем программу на Дельфи для работы с таблицами в 200 тысяч строк и 40 столбцов. Конечно, в большинстве случаев файлы будут меньше, но такие тоже встречаются.
Помещаем на форму стандартный компонент TStringGrid и пишем функцию заполнения этой таблицы. Разумеется, делаем всё аккуратно, пытаясь в разумных пределах максимизировать скорость. Сначала читаем данные из файла в буферный массив TStringList, затем определяем требуемое количество строк и столбцов таблицы. Устанавливаем эти значения, после чего определяем, что в какую ячейку положить, и заполняем ячейки таблицы.
Результат совершенно обескураживающий, ибо программа не работает, заставляя Винды всё время вспоминать о наличии винчестера. Ставим проверку после каждого этапа. Чтение файла в TStringList - довольно быстро и без проблем. Определение и установка размеров таблицы - аналогично. Заполнение таблицы - висим...
Берём маленький файлик (вместо 200 тысяч - 30 тысяч строк). Всё проходит довольно быстро, этап заполнения таблицы (там ещё парсинг простенький есть - деление на поля, не надо забывать) длится порядка 10 секунд, остальные - порядка секунды. Меняем программу таким образом, чтобы она заполняла одну и ту же "маленькую" таблицу подряд одними и теми же значениями десять раз - с каждым разом заполнение происходит всё дольше, на седьмом проходе висим окончательно...
Значит, дело не в размере таблицы (ну или не только в этом), но и в какой-то утечке памяти. Ближе к вечеру напишу решение, а пока подумайте сами, где происходит эта утечка и как её избежать.
Подсказка номер 1.
У компонента TStringGrid есть парочка private методов. Если бы они были доступны, "утечек памяти" можно было бы легко избежать.
Решение.
В общем, дело оказалось в том, что при каждом занесении очередной строки в ячейку компонент TStringGrid посылает Windows запрос на перерисовку этой ячейки. Пока функция работает, Windows с её окном ничего не делает, а запросы на перерисовку всё копятся и копятся в памяти. Сначала физической, затем начинается свопинг. В конце концов система виснет окончательно, хотя Ctrl+Alt+Del и убиение программы лечат ситуацию. По крайней мере, такова ситуация в Win98, в NT-линейке я не проверял.
К счастью, можно вызывать методы, которые заполняют сразу всю строку или весь столбец. Эти методы и сами по себе работают дольше, так как вызывают те же функции заполнения ячейки, да и для их работы приходится подготавливать StringList, что кушает и память, и время. Зато преимущество этих методов состоит в том, что на время своей работы они запрещают перерисовку ячеек, используя методы BeginUpdate и EndUpdate, упомянутые в подсказке. Таким образом, каждый такой метод вызывает один запрос на перерисовку.
Отсюда легко сообразить, что если выполнять заполнение таблицы по столбцам, указанной проблемы удаётся избежать, поскольку столбцов всего около 40. Заполнение таблицы по строкам, конечно, менее эффективно. При заполнении каждого столбца нам, к сожалению, приходится заполнять довольно большой StringGrid на N(=200000) элементов, но этот расход памяти гораздо менее критичен, чем N*M сообщений Windows.
Я жив
[Print]
kv75