Почему fwrite libc функция быстрее, чем функция записи syscall?

Что помогло мне:

sudo -E apt-key adv --keyserver-options http-proxy="http://<username>:<password>@<proxy_server_addr>:<proxy_port>" --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys <key_to_import>
22
задан Michael Dorgan 16 June 2015 в 00:27
поделиться

3 ответа

Время моего приложения с вводом Размером 10 Мб и повторяя его на / dev / null и убедитесь, что файл в не кешируется, я обнаружил, что libc frwite быстрее на БОЛЬШОМ масштабе, когда используя очень маленькие буферы (1 байт в case).

fwrite работает с потоками, которые буферизуются. Поэтому многие небольшие буферы будут работать быстрее, потому что они не будут выполнять дорогостоящий системный вызов, пока буфер не заполнится (или вы не очистите его или не закроете поток). С другой стороны, небольшие буферы, отправляемые на запись , будут запускать дорогостоящий системный вызов для каждого буфера - вот где вы теряете скорость. С буфером потока 1024 байта и записью буферов 1 байта вы смотрите на 1024 write вызовов для каждого килобайта , а не на 1024 fwrite вызовов, превращающихся в one write - видите разницу?

Для больших буферов разница будет небольшой, потому что буферизация будет меньше, и, следовательно, более постоянное количество системных вызовов между fwrite и write .

Другими словами, fwrite (3) - это просто библиотечная процедура, которая собирает разбивает вывод на фрагменты, а затем вызывает write (2) . Теперь write (2) - это системный вызов , который перехватывает ядро ​​. Вот где на самом деле происходит ввод-вывод. Есть некоторые накладные расходы на простой вызов ядра, а затем есть время, необходимое для фактической записи чего-либо. Если вы используете большие буферы, вы обнаружите, что write (2) работает быстрее, потому что в конечном итоге его нужно вызывать в любом случае, и если вы пишете один или несколько раз за fwrite, то накладные расходы на буферизацию fwrite просто равны : дополнительные накладные расходы.

Если вы хотите узнать об этом подробнее,

35
ответ дан 29 November 2019 в 03:50
поделиться

write (2) - это основная операция ядра.

fwrite (3) - это библиотечная функция, которая добавляет буферизацию поверх write (2).

Для небольших (например, построчно) байтов fwrite (3) работает быстрее из-за накладных расходов на простой вызов ядра.

Для большого количества байтов (блочный ввод-вывод) write (2) работает быстрее, потому что он не беспокоится о буферизации, и вам нужно вызывать ядро ​​в обоих случаях.

Если вы посмотрите на источник для cp (1), вы не увидите никакой буферизации.

Наконец, есть еще одно соображение: ISO C против Posix. Буферизованные библиотечные функции, такие как fwrite , указаны в ISO C, тогда как вызовы ядра, такие как write , являются Posix. Хотя многие системы заявляют о совместимости с Posix, особенно при попытке получить государственные контракты, на практике это характерно для Unix-подобных систем. Таким образом, буферные операции более портативны. В результате Linux cp обязательно будет использовать write , но программа на C, которая должна работать кросс-платформенно, может использовать fwrite.

15
ответ дан 29 November 2019 в 03:50
поделиться

Вы также можете отключить буферизацию с помощью функции setbuf (). Когда буферизация отключена, fwrite () будет работать так же медленно, как write (), если не медленнее.

Дополнительную информацию по этому вопросу можно найти здесь: http://www.gnu.org/s/libc /manual/html_node/Controlling-Buffering.html

11
ответ дан 29 November 2019 в 03:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: