Прочитать строку ввода быстрее, чем fgets?
Я пишу программу, где производительность очень важна, но не критическая. В настоящее время я читаю текст из строки FILE*
по очереди, и я использую fgets
для получения каждой строки. После использования некоторых инструментов производительности я обнаружил, что в 20-30% случаев, когда приложение работает, оно находится внутри fgets
.
Существуют ли более быстрые способы получения строки текста? Мое приложение однопоточное, без намерений использовать несколько потоков. Вход может быть из stdin или из файла. Спасибо заранее.
Ответы
Ответ 1
Вы не говорите, на какой платформе вы находитесь, но если она похожа на UNIX, тогда вы можете попробовать системный вызов read(), который не выполняет дополнительный уровень буферизации, который fgets() et al. делать. Это может немного ускорить процесс, с другой стороны, это может замедлить работу - единственный способ узнать это - сосать его и увидеть.
Ответ 2
-
Используйте fgets_unlocked(), но внимательно прочитайте, что он делает первым.
-
Получите данные с помощью fgetc() или fgetc_unlocked() вместо fgets(). С помощью функции fgets() ваши данные дважды копируются в память, сначала библиотекой времени выполнения C из файла во внутренний буфер (потоки ввода-вывода буферизуются), а затем из этого внутреннего буфера в массив в вашей программе
Ответ 3
Прочитайте весь файл за один проход в буфер.
Обработать строки из этого буфера.
Это самое быстрое решение.
Ответ 4
Вы можете попытаться свести к минимуму количество времени, которое вы тратите на чтение с диска, читая большие объемы данных в ОЗУ, а затем работая над этим. Чтение с диска происходит медленно, поэтому минимизируйте время, затрачиваемое на это, прочитав (в идеале) весь файл один раз, а затем обработав его.
Сортировка похожа на то, как кеш процессора сводит к минимуму время, в течение которого процессор фактически возвращается в ОЗУ, вы можете использовать ОЗУ, чтобы свести к минимуму количество раз, когда вы на самом деле переходите на диск.
Ответ 5
Если данные поступают с диска, вы можете быть привязаны к IO.
Если это так, получите более быстрый диск (но сначала проверьте, что вы получаете максимальную отдачу от своего существующего... некоторые дистрибутивы Linux не оптимизируют доступ к диску из коробки (hdparm
)), заранее поставите данные в память (например, скопировав их на RAM-диск) или будьте готовы подождать.
Если вы не привязаны к IO, вы можете тратить много времени на копирование. Вы могли бы воспользоваться так называемыми методами нулевой копии. Что-то вроде памяти отображает файл и получает доступ только через указатели.
Это немного отличается от моего опыта, поэтому вы должны немного прочитать или дождаться более знающей помощи.
Кстати. Вы можете получить больше работы, чем проблема стоит; возможно, более быстрая машина решит все ваши проблемы...
NB-- Неясно, что вы можете отображать на карте стандартный ввод...
Ответ 6
В зависимости от вашей среды использование setvbuf() для увеличения размера внутреннего буфера, используемого файловыми потоками, может или не может повысить производительность.
Это синтаксис -
setvbuf (InputFile, NULL, _IOFBF, BUFFER_SIZE);
Где InputFile является файлом * для файла, только что открытого с помощью функции fopen(), а BUFFER_SIZE - это размер буфера (который выделен этим вызовом для вас).
Вы можете попробовать различные размеры буфера, чтобы увидеть, имеют ли они какое-либо положительное влияние. Обратите внимание, что это совершенно необязательно, и ваше выполнение не может абсолютно ничего делать с этим вызовом.
Ответ 7
Если ОС поддерживает его, вы можете попробовать асинхронное чтение файла, то есть файл считывается в память, в то время как процессор занят чем-то другим. Итак, код выглядит примерно так:
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:
Если у вас несколько процессоров, тогда один процессор считывает файл и анализирует данные в строках, другой процессор берет каждую строку и обрабатывает ее.
Ответ 8
Посмотрите на fread(). Он читается намного быстрее для меня, особенно если для буфера для fread установлено значение 65536. Минусы: вам нужно много работать и, по сути, написать свою собственную функцию getline для преобразования из двоичного чтения в текст.
Проверьте: file I/O