Какой самый быстрый способ чтения 10 ГБ файла с диска? - PullRequest
11 голосов
/ 29 августа 2009

Нам нужно читать и считать разные типы сообщений / запустить немного статистики для текстового файла 10 ГБ, например, FIX движок журнал. Мы используем Linux, 32-битные, 4 процессора, Intel, кодирование на Perl, но язык на самом деле не имеет значения.

Я нашел несколько интересных советов у Тима Брея Проект WideFinder . Тем не менее, мы обнаружили, что с помощью отображения памяти ограничен 32-битной архитектурой.

Мы попытались использовать несколько процессов, которые, кажется, работают быстрее, если мы обрабатываем файл параллельно, используя 4 процесса на 4 процессорах. Добавление многопоточности замедляет, может быть из-за стоимости переключения контекста. Мы пытались изменить размер пула потоков, но это все еще медленнее, чем простая многопроцессная версия.

Часть отображения памяти не очень стабильна, иногда она занимает 80 секунд, а иногда 7 секунд для файла размером 2 ГБ, может быть из ошибки страницы или что-то, связанное с использованием виртуальной памяти. Во всяком случае, Mmap не может масштабироваться выше 4 ГБ на 32-битной архитектура.

Мы попробовали Perl IPC :: Mmap и Sys :: Mmap . Смотрел в Map-Reduce, но проблема действительно в I / O связана, сама обработка достаточно быстро.

Поэтому мы решили попробовать оптимизировать базовый ввод-вывод, настроив размер буфера, тип и т. д.

Может ли кто-нибудь, кто знает о существующем проекте, где это проблема была эффективно решена на любом языке / платформе указать полезную ссылку или предложить направление?

Ответы [ 13 ]

9 голосов
/ 30 августа 2009

В большинстве случаев вы будете связаны с вводом / выводом, а не с процессором, поэтому просто прочитайте этот файл через обычный ввод / вывод Perl и обработайте его в одном потоке. Если вы не докажете, что можете выполнять больше операций ввода-вывода, чем работа с одним процессором, не тратьте впустую больше времени. Во всяком случае, вы должны спросить: почему на земле это в одном огромном файле? Почему на Земле они не разделяют это разумным способом, когда они генерируют это? Это будет стоить больше работы. Затем вы можете поместить его в отдельные каналы ввода-вывода и использовать больше процессоров (если вы не используете какой-либо RAID 0 или NAS или ...).

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

4 голосов
/ 30 августа 2009

Все зависит от того, какую предварительную обработку вы можете выполнить и когда. На некоторых из наших систем мы распаковываем такие большие текстовые файлы, уменьшая их от 1/5 до 1/7 от их первоначального размера. Частично это позволяет нам не обрабатывать эти файлы. до тех пор, пока часы не будут созданы, а во время создания у нас не будет никакой другой нагрузки на машины.

Их обработка выполняется более или менее по принципу zcat thatfiles | наша обработка. (хорошо это делается через сокеты Unix, хотя с помощью специального zcat). Он тратит время процессора на время дискового ввода-вывода и для нашей системы, которое стоило хорошо . Конечно, существует множество переменных, которые могут сделать это очень плохим дизайном для конкретной системы.

3 голосов
/ 29 августа 2009

Хотелось бы, чтобы я знал больше о содержимом вашего файла, но, не зная, кроме текста, это звучит как отличная проблема MapReduce.

PS, самое быстрое чтение любого файла - линейное чтение. cat file > /dev/null должна быть скорость чтения файла.

3 голосов
/ 29 августа 2009

Возможно, вы уже читали эту ветку форума, но если нет:

http://www.perlmonks.org/?node_id=512221

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

О, возможно ли обработать файл из массива RAID? Если у вас есть несколько зеркальных дисков, скорость чтения может быть улучшена. Конкуренция за дисковые ресурсы может быть причиной того, что ваша многопоточная попытка не работает.

Удачи.

2 голосов
/ 29 августа 2009

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

1 голос
/ 16 декабря 2013

Поскольку вы сказали, что платформа и язык не имеют значения ...

Если вам нужна стабильная производительность, настолько высокая, насколько позволяет исходный носитель, я знаю, что единственный способ сделать это в Windows - перекрывающиеся последовательные операции чтения без буферизации в ОС. Вероятно, вы можете получить несколько гигабайт / с с двумя или тремя буферами, кроме того, в какой-то момент вам понадобится кольцевой буфер (один модуль записи, 1+ читателей), чтобы избежать копирования. Точная реализация зависит от драйвера / API. Если происходит копирование памяти в потоке (как в ядре, так и в пользовательском режиме), имеющем дело с вводом-выводом, очевидно, что чем больше буфер для копирования, тем больше времени тратится на это, а не на ввод-вывод. Поэтому оптимальный размер буфера зависит от прошивки и драйвера. На Windows хорошие значения, которые нужно попробовать, кратны 32 КБ для дискового ввода-вывода. Буферизация файлов Windows, отображение памяти и все такое добавляет накладных расходов. Хорошо только в том случае, если выполняется одно или несколько одновременных чтений одних и тех же данных в режиме произвольного доступа. Так что для чтения большого файла последовательно один раз, вы не хотите, чтобы ОС что-то буферизировала или делала какие-либо memcpy. При использовании C # также существуют штрафы за вызов в ОС из-за маршалинга, поэтому код взаимодействия может нуждаться в некоторой оптимизации, если вы не используете C ++ / CLI.

Некоторые люди предпочитают бросать аппаратные средства при проблемах, но если у вас больше времени, чем денег, в некоторых сценариях можно оптимизировать вещи для повышения производительности в 100-1000 раз на одном компьютере уровня потребителя, чем на компьютерах с корпоративной ценой 1000. Причина в том, что если обработка также чувствительна к задержке, выход за пределы использования двух ядер, вероятно, добавляет задержку. Вот почему драйверы могут выдавать гигабайты / с, в то время как корпоративное программное обеспечение останавливается на мегабайтах / с к тому времени, когда все это сделано. Что бы ни делали отчеты, бизнес-логика и подобное корпоративное программное обеспечение, вероятно, также можно выполнить со скоростью гигабайт / с на двухъядерном потребительском процессоре, если вы пишете так, как вы вернулись в 80-е годы при написании игры. Самым известным примером, который я слышал о таком подходе ко всей их бизнес-логике, является биржа форекс LMAX, которая опубликовала часть своего кода на основе кольцевого буфера, который, как говорили, был вдохновлен драйверами сетевых карт.

Забывая всю теорию, если вы довольны <1 ГБ / с, одна возможная отправная точка для Windows, которую я нашел, - это просмотр источника readfile из winimage, если вы не хотите копаться в примерах sdk / driver. Может потребоваться исправление исходного кода для правильного расчета производительности на скоростях SSD. Экспериментируйте также с размерами буфера. Многопоточные коммутаторы / h и / o перекрываются (порт завершения) ввода-вывода с оптимальным размером буфера (попробуйте 32,64,128 КБ и т. Д.) Без использования буферизации файлов Windows, по моему опыту, дают лучшие результаты при чтении с SSD (холодные данные) при одновременной обработке (используйте / a для обработки Адлера, так как в противном случае он слишком привязан к процессору). </p>

1 голос
/ 29 сентября 2009

Если вы привязаны к вводу / выводу и ваш файл находится на одном диске, тогда делать особо нечего. Простое однопоточное линейное сканирование по всему файлу - самый быстрый способ получить данные с диска. Использование больших размеров буфера может немного помочь.

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

1 голос
/ 23 сентября 2009

хммм, а что не так с командой read () в C? Обычно имеет ограничение в 2 ГБ, так что просто позвоните 5 раз подряд. Это должно быть довольно быстро.

1 голос
/ 30 августа 2009

У меня есть сотрудник, который ускорил чтение FIX, перейдя на 64-битный Linux. Если это что-то стоящее, потратьте немного денег, чтобы получить более интересное оборудование.

1 голос
/ 29 августа 2009

Разобрать файл один раз, читая построчно. Положите результаты в таблицу в приличной базе данных. Запустите столько запросов, сколько пожелаете. Кормите зверя регулярно новыми поступающими данными.

Поймите, что манипулирование файлом 10 Гб, передача его по (даже локальной) сети, поиск сложных решений и т. Д. Требуют времени.

...