Сортировка гигантских двоичных файлов с помощью C#

#c# #binary #binaryfiles #large-data

#c# #двоичный #двоичные файлы #большие данные

Вопрос:

У меня есть большой файл размером примерно 400 ГБ. Генерируется ежедневно внешней закрытой системой. Это двоичный файл следующего формата:

 byte[8]byte[4]byte[n]
  

Где n равно значению int32 байта[4].

В этом файле нет разделителей, и для чтения всего файла вы просто повторяете до EOF. С каждым «элементом», представленным как байт [8] байт [4] байт [n].

Файл выглядит следующим образом

 byte[8]byte[4]byte[n]byte[8]byte[4]byte[n]...EOF
  

байт [8] — это 64-разрядное число, представляющее период времени, представленный тиками .NET. Мне нужно отсортировать этот файл, но, похоже, я не могу найти самый быстрый способ сделать это.

В настоящее время я загружаю галочки в структуру и начальную и конечную позиции byte [n] и читаю до конца файла. После этого я сортирую список в памяти по свойству Ticks, а затем открываю BinaryReader и ищу каждую позицию в порядке тиков, считываю значение byte [n] и записываю во внешний файл.

В конце процесса я получаю отсортированный двоичный файл, но это занимает ЦЕЛУЮ ВЕЧНОСТЬ. Я использую C # .NET и довольно мощный сервер, но, похоже, проблема с дисковым вводом-выводом.

Характеристики сервера:

  • 2x 2,6 ГГц Intel Xeon (шестиядерный процессор с HT) (24 потока)
  • 32 ГБ оперативной памяти
  • 500 ГБ RAID 1 0
  • 2 ТБ RAID 5

Я просмотрел весь Интернет и могу найти только примеры, когда огромный файл составляет 1 ГБ (заставляет меня хихикать).

У кого-нибудь есть какие-либо советы?

Комментарии:

1. Я не уверен, что понимаю, как вам удается читать один файл объемом 400 ГБ и записывать другой, отсортированный файл объемом 400 ГБ в системе с RAID-диском объемом всего 500 ГБ, но предложение Грега звучит неплохо, хотя я лично не делал этого с файлами такого размера.

2. Эй, у меня также есть RAID 5 объемом 2 ТБ.

Ответ №1:

Отличный способ ускорить такого рода доступ к файлам — это отобразить весь файл в адресное пространство и позволить ОС самостоятельно считывать любые биты из файла, которые ей нужны. Так что делайте то же самое, что и сейчас, за исключением чтения из памяти вместо использования BinaryReader /seek/read .

У вас много оперативной памяти, так что это должно обеспечить довольно хорошую производительность (при условии, что вы используете 64-разрядную ОС).

Комментарии:

1. Спасибо за быстрый ответ! Сможет ли MemoryMappedFile обрабатывать файл объемом 400 ГБ? Нужно ли мне создавать разные типы средств доступа к представлению (произвольный доступ или последовательный)? Еще раз спасибо! 🙂

2. MemoryMappedFile должен иметь возможность обрабатывать весь файл за один раз. Я делал это с помощью Python на FreeBSD с файлом объемом 30 ГБ, но я полностью ожидаю, что это будет нормально работать в Windows с вашим размером файла. Я не уверен в разнице между средствами доступа, но любой из них, вероятно, будет работать. Вы будете читать файл один раз последовательно, затем после сортировки вы будете читать его в случайном порядке.

Ответ №2:

Используйте сортировку слиянием. Это онлайн и хорошо распараллеливается.

http://en.wikipedia.org/wiki/Merge_sort

Ответ №3:

Если вы можете изучить Erlang или Go, они могут быть очень мощными и очень хорошо масштабируемыми, поскольку у вас есть 24 потока. Используйте асинхронный ввод-вывод. Сортировка слиянием. И поскольку у вас 32 ГБ оперативной памяти, попробуйте загрузить в ОЗУ столько, сколько сможете, и отсортировать его там, а затем записать обратно на диск.

Ответ №4:

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

Это несколько похоже на hashsort (я думаю).