Нужна помощь в управлении большими файлами - PullRequest
2 голосов
/ 01 января 2012

Я хочу прочитать файл 4 ГБ и создать его копию, внеся изменения в некоторые поля.Мой приоритет - экономия времени, т. Е. Обработка должна быть быстрой.
Я хочу загрузить ее в память, чтобы операции чтения / записи стали быстрыми.Я должен использовать кучу?Или я должен попробовать что-то еще, как файлы, отображенные в памяти?или любой другой выход?

Прежде всего, спасибо всем за помощь ... Позвольте мне перефразировать мой вопрос ... Вот, пожалуйста.
Мне нужно получить файл от пользователя, этот файл имеет размер около 3-4 ГБ.,Он содержит записи, у каждой записи есть несколько полей, в которых есть некоторые конфиденциальные данные, которые мне нужно искать и шифровать до EOF ..
Если я выполню поиск и шифрование с помощью FILE I / O, это будет длиться вечно ... как пакетобработка ... Таким образом, я могу создать массив из 4 ГБ в куче, так как я работаю на 64-битной ОС, загрузить весь файл и выполнить операцию.эта локальная копия даст лучшую производительность, чем у FILE IO ...
Я рассматриваю файлы с отображением в памяти, поскольку она устраняет необходимость в массиве (локальное копирование) и скорость работы также хороша, однако я не знаком с этим, такспрашиваю, целесообразно ли это для вышеупомянутого сценария ... !!
Я также думал о MATLAB ... вы также можете предложить, если у вас есть лучший выход .. thnx ...

Ответы [ 3 ]

3 голосов
/ 01 января 2012

Я полагаю, что следует использовать подход с отображением памяти, но вы должны действительно попробовать его и измерить то, что дает наилучшую производительность для вас.Начните с наивной прямой реализации, и если этого недостаточно, попробуйте оптимизировать ее.

1 голос
/ 04 января 2012

Из описания вашей проблемы я не уверен, что вы можете избежать плохой производительности ввода-вывода.Если вам нужно отсканировать 4 ГБ данных, чтобы добраться до нужной записи, а затем снова записать весь файл, я сомневаюсь, что это будет иметь большое значение, если вы будете использовать обычный файловый ввод-вывод или mmap, поскольку горлышко бутылки будет считывать данныес диска.В обоих случаях ядро ​​будет пытаться кэшировать часто используемые части файла, поэтому повторное чтение выполняется быстро.

Звучит так, будто вам нужна какая-то поддержка копирования при записи из файловой системы, но это будетсильно зависит от функций файловой системы (если они вообще существуют).

Вы можете попробовать использовать mmap с MAP_PRIVATE.Сначала вы должны отобразить исходный файл в памяти.Любые сделанные изменения будут храниться только в памяти (MAP_PRIVATE), но любые не затронутые части файла будут сохранены из исходного файла (уменьшая нагрузку на память, если вы ее не трогаете).Затем вам нужно будет записать новый файл с обычным файловым вводом / выводом, проходящим через сопоставленную память.Однако я сомневаюсь, что ядро ​​будет достаточно умным, чтобы обнаружить любое ненужное копирование.

Как уже отмечали другие для файлов такого размера, потребуется 64-битная архитектура для сопоставления всего файла сразу.

1 голос
/ 01 января 2012

Решение простое, но требует от вас дополнительной информации о деталях данного формата файла.

Однако, некоторый псевдокод для универсального решения (простой C, запросите реализацию C ++, когда хотите):

#define BUFSIZE 4096 // 4k, try larger or smaller values to improve performance...

int process_file( const char* filename ) {
  char buffer[BUFSIZE];
  size_t nread;
  FILE* fp;
  if( (fp=fopen(filename,"rb"))==NULL ) return 1;
  while( (nread=fread(buffer,1,BUFSIZE,fp))>=0 ) {
    if( nread==0 ) break; // EOF
    process_file_buffer( buffer, nread );
  }
  fclose(fp);
  return nread>=0 ? 0 : 2; // 0==success, 2==read error, check "errno"!
}

void process_file_buffer( const char* buffer, size_t size ) {
  // process, and write result to target file
}

EDIT

Относительно ваших сомнений в вопросах управления памятью: это во многом зависит от вашего фактического кода и ваших реальных требований. В моем примере кода есть только один единственный буфер, автоматически распределяемый по стеку, которого вполне достаточно для этого варианта использования.

Однако, если у вас есть особые требования, то уточняйте их!

ДРУГОЕ РЕДАКТИРОВАНИЕ:

Этот код является надежным и обеспечивает идеальную основу для большего. Однако: если у вас когда-нибудь возникнут проблемы с производительностью, вам действительно нужно запустить профилировщик (или написать & свой собственный код профилирования).

Почему?

Вы можете подозревать, что ЭТОТ КОД является узким местом, но я держу пари, что этого не будет;) Не забывайте, что вы также должны написать что-то для DISK, и не забывайте, что вы должны пройти любой один байт файла через память - и оттуда через регистры ЦП - для его обработки (это было одним из ваших реальных требований ...).

SO: Не обращайте внимания на ввод-вывод в память. Сначала вы должны думать о чем-то еще;)

Вам, наверное, не нравится это слышать. Но это просто ваша первоначальная ситуация.

И, прежде чем вы начнете думать об управлении памятью, вы должны начать думать о ваших реальных требованиях к I..O ...

ЕЩЕ ДРУГОЕ РЕДАКТИРОВАНИЕ:

KISS - будь проще, глупый; -)

...