2011-01-07 3 views
3

У меня есть папка с 3000 csv файлами размером от 1Kb до 100kb. Каждая строка в этих файлах имеет длину 43 символа. Они имеют общий размер 171Mb.C# Быстрое чтение CSV из многих файлов

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

Первоначально я попытался выполнить свою собственную реализацию, но не был доволен этими результатами. Затем я нашел LumenWorks.Framework.IO.Csv в StackOverflow. Он имеет смелые претензии:

Чтобы предоставить более простые цифры, с CSV-файлом 45 МБ, содержащим 145 полей и 50 000 записей, читатель обрабатывал около 30 МБ/с. Так что в целом, потребовалось 1,5 секунды! Характеристики машины были P4 3,0 ГГц, 1024 МБ.

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

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

Приветствия

+0

Когда вы говорите синтаксический анализ ... Можете ли вы рассказать о том, что вы делаете с каждым файлом? – Jay

+0

Прямо сейчас, ничего. Просто прочитав поля в строку [], а затем перейдем к следующей строке. – Mitch

+0

Как уже упоминалось ниже, кажется, что ваша проблема связана с IO, пытающейся разобрать файлы в RAMdisk и разыгрывать оттуда? http://superuser.com/questions/34388/whats-the-best-ramdisk-for-windows –

ответ

4

Анализ файлов CSV связан с вводом-выводом, определяется, насколько быстро вы можете считывать данные с диска. Самый быстрый, который может когда-либо быть, составляет от 50 до 60 МБ в секунду для жесткого диска потребительского уровня. Похоже, что LumenWorks близок к этому пределу.

Вы будете получать такую ​​пропускную способность только на хорошем чистом нефрагментированном диске с одним файлом. Так что голова считывателя дисков просто перекачивает данные, не перемещаясь много, а просто отслеживать движения. Перемещение головы - это медленная часть, обычно около 16 миллисекунд в среднем.

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

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

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

+0

Спасибо, согласен. Я чувствую, что резьба не улучшится. Я попробовал Parallel.For без реальных улучшений. Наш сервер-разработчик имеет два режима Xeon, и использование ЦП не сказывается вообще. Я чувствую, что проблема с I/O является проблемой, я просто не уверен, что делать ... – Mitch

+0

Должен заметить, что изначально я извлекал все эти файлы из архива rar с помощью unrar.exe. Интересно, могу ли я реализовать свой собственный код unrar, а затем разобрать все файлы из одного потока. – Mitch

+0

Отсутствие загрузки процессора - это slamdunk. Это ограничение ввода-вывода, как и должно быть. Вам нужно будет купить более быстрый диск. –

0

ли все файлы «появляются» сразу быть обработаны? Не могли бы вы не объединить их поэтапно, поскольку они «приходят» в один файл, который обрабатывается вашей программой? 10 минут - это длительное время для обработки +/- 7 МБ данных (наихудший сценарий из числа, который вы указали)?

0

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

+0

Я не думаю, что это улучшит производительность. –

0

Вы пытались использовать LogParser? Я не уверен, что это будет быстрее, но у меня был успех в некоторых сценариях. Возможно, стоит быстро проверить.

log parser 2.2

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

Смежные вопросы