Читать строку ввода быстрее, чем fgets? - PullRequest
11 голосов
/ 09 апреля 2009

Я пишу программу, в которой производительность очень важна, но не критична. В настоящее время я читаю текст из строки FILE* строка за строкой и использую fgets для получения каждой строки. После использования некоторых инструментов для повышения производительности я обнаружил, что 20–30% времени работы моего приложения оно находится внутри fgets.

Есть ли более быстрые способы получить строку текста? Мое приложение является однопоточным без намерения использовать несколько потоков. Ввод может быть из стандартного ввода или из файла. Заранее спасибо.

Ответы [ 8 ]

7 голосов
/ 09 апреля 2009

Вы не говорите, на какой платформе вы находитесь, но если она похожа на UNIX, то вы можете попробовать системный вызов read (), который не выполняет дополнительный уровень буферизации, как fgets () и др. делать. Это может немного ускорить процесс, с другой стороны, это может замедлить ход событий - единственный способ выяснить это - сосать и смотреть.

4 голосов
/ 09 апреля 2009

Считать весь файл за один раз в буфер.

Обработка строк из этого буфера.

Это самое быстрое решение.

4 голосов
/ 09 апреля 2009
  1. Используйте fgets_unlocked (), но внимательно прочитайте, что он делает первым

  2. Получите данные с помощью fgetc () или fgetc_unlocked () вместо fgets (). С помощью функции fgets () ваши данные дважды копируются в память: сначала библиотека времени выполнения C из файла во внутренний буфер (потоковый ввод-вывод буферизуется), затем из этого внутреннего буфера в массив вашей программы

3 голосов
/ 09 апреля 2009

Вы можете попытаться минимизировать количество времени, которое вы тратите на чтение с диска, читая большие объемы данных в ОЗУ, а затем работая над этим. Чтение с диска происходит медленно, поэтому минимизируйте время, которое вы тратите на это, читая (в идеале) весь файл один раз, а затем работая над ним.

Что-то вроде того, как кэш ЦП минимизирует время, когда ЦП фактически возвращается в ОЗУ, вы можете использовать ОЗУ, чтобы минимизировать количество обращений к диску.

2 голосов
/ 09 апреля 2009

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

Это синтаксис -

setvbuf (InputFile, NULL, _IOFBF, BUFFER_SIZE);

Где InputFile - это ФАЙЛ * для файла, только что открытого с помощью fopen (), а BUFFER_SIZE - размер буфера (который выделяется этим вызовом для вас).

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

2 голосов
/ 09 апреля 2009

Если данные поступают с диска, вы можете быть привязаны к IO.

Если это так, получите более быстрый диск (но сначала убедитесь, что вы максимально используете свой существующий ... некоторые дистрибутивы Linux не оптимизируют доступ к диску из коробки) ), поместите данные в память (скажем, скопировав их на RAM-диск) заблаговременно или будьте готовы ждать.


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

Это немного за пределами моей компетенции, так что вам стоит немного почитать или подождать, чтобы получить более знающую помощь.

Кстати: вы можете заняться большим трудом, чем эта проблема того стоит; может быть, более быстрая машина решит все ваши проблемы ...

NB-- Не ясно, что вы можете отобразить в память стандартный ввод либо ...

0 голосов
/ 18 мая 2009

Посмотри в фред (). Для меня он читается намного быстрее, особенно если буфер для fread установлен на 65536. Минусы: вам нужно проделать большую работу и, по сути, написать собственную функцию getline для преобразования из двоичного чтения в текстовое. Проверить: файл ввода / вывода

0 голосов
/ 29 апреля 2009

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

start asynchronous read
loop:
  wait for asynchronous read to complete
  if end of file goto exit
  start asynchronous read
  do stuff with data read from file
  goto loop
exit:

Если у вас более одного ЦП, то один ЦП читает файл и разбирает данные на строки, а другой ЦП берет каждую строку и обрабатывает ее.

...