Вопрос

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

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

Это было полезно?

Решение

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

Другие советы

  1. Используйте fgets_unlocked(), но сначала внимательно прочитайте, что она делает

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

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

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

Это самое быстрое из возможных решений.

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

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

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

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

setvbuf (InputFile, NULL, _IOFBF, BUFFER_SIZE);

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

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

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

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


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

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

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

ПРИМЕЧАНИЕ - Неясно, можете ли вы также отобразить в памяти стандартный ввод...

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

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

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:

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top