Какой самый быстрый способ чтения огромных файлов в Delphi?

Моя программа должна читать куски из огромного двоичного файла с произвольным доступом. У меня есть список смещений и длин, которые могут иметь несколько тысяч записей. Пользователь выбирает запись, и программа ищет смещение и считывает длину байтов.

Программа внутренне использует TMemoryStream для хранения и обработки фрагментов, прочитанных из файла. Чтение данных осуществляется через TFileStream, например:

FileStream.Position := Offset;
MemoryStream.CopyFrom(FileStream, Size);

Это работает нормально, но, к сожалению, становится все медленнее, когда файлы становятся больше. Размер файла начинается с нескольких мегабайт, но часто достигает нескольких десятков гигабайт. Размер фрагментов составляет около 100 Кбайт.

Содержимое файла читается только моей программой. Это единственная программа, обращающаяся к файлу в то время. Также файлы хранятся локально, так что это не проблема сети.

Я использую Delphi 2007 на Windows XP.

Что я могу сделать, чтобы ускорить доступ к этому файлу?

редактировать:

  • Доступ к файлам медленный для больших файлов, независимо от того, какая часть файла читается.
  • Программа обычно не читает файл последовательно. Порядок чанков определяется пользователем и не может быть предсказан.
  • Чтение фрагмента из большого файла всегда медленнее, чем чтение такого же большого фрагмента из небольшого файла.
  • Я имею в виду производительность чтения фрагмента из файла, а не общее время, необходимое для обработки всего файла. Последнее, очевидно, займет больше времени для больших файлов, но это не проблема здесь.

Я должен извиниться перед всеми: после того, как я реализовал доступ к файлу, используя отображенный в памяти файл, как предполагалось, оказалось, что это не имело большого значения. Но после того, как я добавил еще какой-то временной код, оказалось, что не доступ к файлам замедляет работу программы. Доступ к файлу на самом деле занимает почти постоянное время независимо от размера файла. У некоторой части пользовательского интерфейса (которую я еще не определил), похоже, есть проблема производительности с большими объемами данных, и почему-то я не смог увидеть разницу, когда впервые запустил процессы.

Я прошу прощения за то, что был неаккуратным в определении узкого места.

3 ответа

Решение

Если вы откроете раздел справки для функции WinAPI CreateFile (), вы найдете там интересные флаги, такие как FILE_FLAG_NO_BUFFERING и FILE_FLAG_RANDOM_ACCESS . Вы можете играть с ними, чтобы получить некоторую производительность.

Затем копирование данных файла, даже размером 100 КБ, является дополнительным шагом, который замедляет операции. Рекомендуется использовать функции CreateFileMapping и MapViewOfFile, чтобы получить готовый указатель на данные. Таким образом, вы избегаете копирования и, возможно, получаете определенные преимущества в производительности (но вам нужно тщательно измерять скорость).

TMemoryStream в Delphi работает медленно из-за того, как он выделяет память. У компании NexusDB есть TnxMemoryStream, который намного эффективнее. Там могут быть некоторые бесплатные, которые работают лучше.

Стандартный Delphi TFileStream также не самый эффективный компонент. Путь в историю Джулиан Бакнолл опубликовал компонент с именем BufferedFileStream в журнале или где-то еще, который очень эффективно работал с файловыми потоками.

Удачи.

Может быть, вы можете принять этот подход:

Сортируйте записи по максимальному расположению файлов, а затем по следующему:

  1. Возьмите записи, которые нуждаются только в первых X МБ файла (до определенной позиции файла)
  2. Чтение X МБ из файла в буфер (TMemorystream
  3. Теперь прочитайте записи из буфера (возможно, многопоточные)
  4. Повторите это для всех записей.

Вкратце: кэшируйте часть файла и считывайте все записи, которые в него вписываются (многопоточные), затем кэшируйте следующую часть и т. Д.

Может быть, вы можете набрать скорость, если вы просто исходите из своего подхода, но сортируете записи по позиции.

Другие вопросы по тегам