![]() |
|
Модераторы: Snowy, MetalFan, bems, Poseidon |
![]()
|
|
| Freimaks |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 31 Регистрация: 23.4.2011 Репутация: нет Всего: нет |
Ну вроде прочитал, не могу сказать что понял 100% все, но кое что прояснилось в моей голове.
Завел один класс TBinPoints, в качестве полей класса описал все возможные поля записи в bin-файле, определил их свойства и сделал три конструктора (по одному для каждого из типов файлов). Далее как понял мне все-равно надо использовать записи, чтобы считывать файл. Завел соответственно 3 записи, которые использую для BaseStream.Read(Запись, SizeOf(запись)). Вроде все правильно, да и все работает. Я не могу понять теперь, что мне использовать в качестве Key в TDictionary. Ради интереса я делал так:
И далее в качестве Key использовал BinPoints.PointCode (типа класс) и в итоге у меня в TDictionary оставалось количество записей=количеству разных классов. Потом в качестве Key попробовал указывать MD5 от строки из координат... работает конечно - но долго до невозможности. В общем пока остались вопросы по Key в TDictionary. |
|||
|
||||
| Qu1nt |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 602 Регистрация: 13.1.2007 Репутация: 22 Всего: 50 |
Читай про устройство хеш-таблиц. Вот, один из простеньких вариантов:
|
|||
|
||||
| Freimaks |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 31 Регистрация: 23.4.2011 Репутация: нет Всего: нет |
Решил проблему с ключом несколько иначе: создал запись из пяти полей (X,Y,Z,Time,Code) и в качестве ключа использую эту запись в соответствии с требованиями подхода - либо только 4 поля, либо все 5. Вроде работает, дубли ищет.
В примере как я понял ключ генерится с помощью function TPointComparer.GetHashCode(const Value: TPoint): Integer;. Как работают хеш-таблицы я почитал - я хотел примерно такое же сделать ручками на базе двух массивов, но так как потом получилось завести Dictionary, то решил на это забить. В принципе то, что я сваял на данный момент работает, но не идеально. |
|||
|
||||
| Qu1nt |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 602 Регистрация: 13.1.2007 Репутация: 22 Всего: 50 |
К сожалению, стандартного шаблонного множества в Delphi нет, как и аналога С++ std::multimap. Поэтому для экономии памяти я бы использовал в TDictionary только поле ключа. И в зависимости от задачи менял только компаратор.
|
|||
|
||||
| Freimaks |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 31 Регистрация: 23.4.2011 Репутация: нет Всего: нет |
Да, это актуально, т.к. памяти все это жрет не мало. Но больше всего меня беспокоит скорость чтения\записи. Я думал, что торможение идет в следствии различных операций переброса значений в класс, в запись в Dictionary. Но это влияет в меньшей степени. Сделал отдельную процедуру просто для чтения одного файла.
Чтение этого файла размеров в 53.3 мегабайта занимает около 30 секунд... если не больше. Можно как-то ускорить. Хотя бы куда копать не подскажете? |
||||
|
|||||
| Qu1nt |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 602 Регистрация: 13.1.2007 Репутация: 22 Всего: 50 |
Как ситуация меняется, если убрать взаимодействие с пользовательским интерфейсом? Убери Application.ProcessMessages и ProgressBar из цикла.
|
|||
|
||||
| Freimaks |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 31 Регистрация: 23.4.2011 Репутация: нет Всего: нет |
Сократил до минимума... толку никакого. Я просто понять не могу в чем проблема - т.е. я что-то делаю не так, инструмент медленный или что вообще не так. В родной проге этот файл открывается за 1-2 секунды...
RPointsTime - это packed record. |
|||
|
||||
| Qu1nt |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 602 Регистрация: 13.1.2007 Репутация: 22 Всего: 50 |
Хорошо, в таком случае нужно читать блочно. Попробуй за раз читать несколько тысяч точек.
|
|||
|
||||
| Freimaks |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 31 Регистрация: 23.4.2011 Репутация: нет Всего: нет |
||||
|
||||
| Freimaks |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 31 Регистрация: 23.4.2011 Репутация: нет Всего: нет |
Я понял как делать!!! Ща усе сделаю
|
|||
|
||||
| Qu1nt |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 602 Регистрация: 13.1.2007 Репутация: 22 Всего: 50 |
Только добрался до компилятора. Ага, оказывается свойства Position и Size не кэшируются, отсюда такое проседание. Добавив буфер и исправив этот момент получил значительный прирост в производительности. Загрузка 200 МБ файла в список у меня занимает меньше секунды.
Это сообщение отредактировал(а) Qu1nt - 20.4.2012, 22:22 |
|||
|
||||
| Freimaks |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 31 Регистрация: 23.4.2011 Репутация: нет Всего: нет |
Да, я сначала пытался просто Position и Size определять до входа в цикл чтения файла - прирост был.
Но больше всего помогло чтение файла за один раз, а потом циклом раскидывание его в Dictionary. Выглядит вот так (кусок кода):
Чтение происходит очень быстро - гораздо меньше секунды. Обработка тоже быстро проходит, запись... ну тут еще не сравнивал, пока не до нее - главное пишет правильно. Пока не могу избавиться от двух проблем: 1. Жрет много памяти - это и логично, сначала файл в оперативку, потом дублируем его в Dictionary так еще и с ключем, состоящим из львиной доли файла. Обойти большой ключ проблематично. Но Вы говорили, что можно в качестве значений давать не сами значений класса, а лишь указатель на него. Как это сделать и как происходит удаление самих данных класса, я вообще понять не могу... 2. После отработки каждого файла в оперативке остается большое количество данных. И это не смотря на то, что я делаю обнуление массива RPointsTimeArray:=nil;, так еще и в конце обработки каждого файла делаю Dictionary.Free. Статистика такая: подаем файл 120Мб, в оперативке максимальное потребление за время обработки примерно 550Мб, после завершения обработки остается 212Мб. Обработка (без записи) занимает время в в среднем 4200 мсек. |
|||
|
||||
| Qu1nt |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 602 Регистрация: 13.1.2007 Репутация: 22 Всего: 50 |
В общем я не знаю, что тебе сказать. Я говорю как нужно делать, привожу примеры, а ты пишешь по своему.
Подведем итог. Не нужно весь файл в память грузить. Если бы ты запустил мой пример, увидел бы, что ~10 000 оптимальный размер буфера и его увеличение прироста не дает. Не нужно использовать поле значения в TDictionary. Это отнимает лишнюю память. Нужно понять разницу между TList/TObjectList, TDictionary/TObjectDictionary. Нужно научиться форматировать код. Нужно избавиться от глобальных переменных в пользу ООП. |
|||
|
||||
| Freimaks |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 31 Регистрация: 23.4.2011 Репутация: нет Всего: нет |
Попробую переделать. Буду учить матчасть...
|
|||
|
||||
| Freimaks |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 31 Регистрация: 23.4.2011 Репутация: нет Всего: нет |
Все сделал как советовали - действительно так лучше. Пробовал с разным размером буфера при считывании - да, после 10000 прироста нет (если и есть то он незначительный).
Переделал таким же макаром и запись, единственное при записи я использую буфер большего размера - 1 000 000 записей, дальше прироста нет, меньше - скорость записи падает. Вроде бы щас написал все алгоритмы (сделал даже переброс точек в другой класс при нахождении дубликатов). Все работает, но есть одно но, исправить которое наверно и невозможно. Это скорость самой обработки. Сейчас у меня такой расклад: файл 240 Мб., 10506680 точек (все сдвоенные). Обработка от начала и до конца занимает 27815 мсек, из которых на саму обработку (удаление дубликатов) уходит 11482 мсек. Остальное сжирается записью и чтением. Примерное сравнение с аналогичной программой - мое творение работает раз в 10 медленнее. |
|||
|
||||
![]()
|
| Правила форума "Delphi: Для новичков" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Delphi: Для новичков | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |