Функция printf()
, скорее всего, отобразит ваш запрос на один вызов write()
, не используя буферизацию, но и не замедляя работу. Если вы хотите увидеть эффект не буферизации, используйте односимвольный ввод / вывод:
for (int i = 0; string[i] != '\0'; i++)
putc(string[i], fp);
При небуферизованном вводе / выводе это будет показывать разницу, потому что каждый вызов putc()
требует write()
системный вызов, потому что доступен только один байт.
Обратите внимание, что приведенный ниже код не работает со строкой - он работает с байтовым массивом (без нулевого терминатора). Разница не важна для производительности; он требует некоторой осторожности при обработке данных.
Код также использует обычный fopen()
вместо использования freopen()
на stdout
. Опять же, это не будет (крайне маловероятно) существенно повлиять на производительность.
slow11.c
#include <stdio.h>
#define FLOPPY_SIZE (2 * 80 * 18 * 512) // 2 sides, 80 tracks, 18 sectors, 512 bytes
int main(void)
{
char string[FLOPPY_SIZE];
for (size_t i = 0; i < FLOPPY_SIZE; i++)
string[i] = (i % 64) + '0';
const char filename[] = "floppy.data";
FILE *fp = fopen(filename, "w");
setvbuf(fp, NULL, _IONBF, 0);
for (size_t i = 0; i < FLOPPY_SIZE; i++)
putc(string[i], fp);
fclose(fp);
return(0);
}
slow61.c
Я также создал запрограммируйте slow61.c
из slow11.c
, удалив строку setvbuf()
.
fast89.c
#include <stdio.h>
#define FLOPPY_SIZE (2 * 80 * 18 * 512) // 2 sides, 80 tracks, 18 sectors, 512 bytes
int main(void)
{
char string[FLOPPY_SIZE];
for (size_t i = 0; i < FLOPPY_SIZE; i++)
string[i] = (i % 64) + '0';
const char filename[] = "floppy.data";
FILE *fp = fopen(filename, "w");
setvbuf(fp, NULL, _IONBF, 0);
fprintf(fp, "%.*s", FLOPPY_SIZE, string);
fclose(fp);
return(0);
}
Примеры выполнения
Программа timecmd
является самогон; опция -u
сообщает время в микросекундах (-n
для наносекунд; -m
для миллисекунд, ничего за целые секунды). Это в первую очередь для длительно работающих программ, в которых полезно знать, когда была запущена команда, чтобы вы могли догадаться, когда она завершит sh (поэтому она сообщает информацию о запуске и окончании sh). Вы, вероятно, можете использовать вместо этого (стандарт POSIX) time
; формат вывода будет другим.
$ for i in 1 2 3 4 5 6 7 8 9 0; do timecmd -u -- fast89; timecmd -u slow61; timecmd -u slow11; done
2020-03-01 07:58:05.964614 [PID 14492] fast89
2020-03-01 07:58:05.978391 [PID 14492; status 0x0000] - 0.013777s
2020-03-01 07:58:05.986902 [PID 14494] slow61
2020-03-01 07:58:06.058328 [PID 14494; status 0x0000] - 0.071426s
2020-03-01 07:58:06.066949 [PID 14496] slow11
2020-03-01 07:58:09.788096 [PID 14496; status 0x0000] - 3.721147s
2020-03-01 07:58:09.795178 [PID 14498] fast89
2020-03-01 07:58:09.806464 [PID 14498; status 0x0000] - 0.011286s
2020-03-01 07:58:09.813784 [PID 14500] slow61
2020-03-01 07:58:09.882777 [PID 14500; status 0x0000] - 0.068993s
2020-03-01 07:58:09.890567 [PID 14502] slow11
2020-03-01 07:58:13.689083 [PID 14502; status 0x0000] - 3.798516s
2020-03-01 07:58:13.696225 [PID 14504] fast89
2020-03-01 07:58:13.708219 [PID 14504; status 0x0000] - 0.011994s
2020-03-01 07:58:13.715447 [PID 14506] slow61
2020-03-01 07:58:13.784190 [PID 14506; status 0x0000] - 0.068743s
2020-03-01 07:58:13.791485 [PID 14508] slow11
2020-03-01 07:58:17.495425 [PID 14508; status 0x0000] - 3.703940s
2020-03-01 07:58:17.502710 [PID 14510] fast89
2020-03-01 07:58:17.514147 [PID 14510; status 0x0000] - 0.011437s
2020-03-01 07:58:17.521541 [PID 14512] slow61
2020-03-01 07:58:17.589657 [PID 14512; status 0x0000] - 0.068116s
2020-03-01 07:58:17.596818 [PID 14514] slow11
2020-03-01 07:58:21.253654 [PID 14514; status 0x0000] - 3.656836s
2020-03-01 07:58:21.260930 [PID 14516] fast89
2020-03-01 07:58:21.272169 [PID 14516; status 0x0000] - 0.011239s
2020-03-01 07:58:21.279587 [PID 14518] slow61
2020-03-01 07:58:21.348507 [PID 14518; status 0x0000] - 0.068920s
2020-03-01 07:58:21.355832 [PID 14520] slow11
2020-03-01 07:58:25.041571 [PID 14520; status 0x0000] - 3.685739s
2020-03-01 07:58:25.048497 [PID 14522] fast89
2020-03-01 07:58:25.059680 [PID 14522; status 0x0000] - 0.011183s
2020-03-01 07:58:25.066855 [PID 14524] slow61
2020-03-01 07:58:25.135246 [PID 14524; status 0x0000] - 0.068391s
2020-03-01 07:58:25.142421 [PID 14526] slow11
2020-03-01 07:58:28.853268 [PID 14526; status 0x0000] - 3.710847s
2020-03-01 07:58:28.860497 [PID 14528] fast89
2020-03-01 07:58:28.872152 [PID 14528; status 0x0000] - 0.011655s
2020-03-01 07:58:28.879254 [PID 14530] slow61
2020-03-01 07:58:28.947534 [PID 14530; status 0x0000] - 0.068280s
2020-03-01 07:58:28.955126 [PID 14532] slow11
2020-03-01 07:58:33.236459 [PID 14532; status 0x0000] - 4.281333s
2020-03-01 07:58:33.243709 [PID 14534] fast89
2020-03-01 07:58:33.260364 [PID 14534; status 0x0000] - 0.016655s
2020-03-01 07:58:33.267575 [PID 14536] slow61
2020-03-01 07:58:33.336602 [PID 14536; status 0x0000] - 0.069027s
2020-03-01 07:58:33.344791 [PID 14538] slow11
2020-03-01 07:58:37.065292 [PID 14538; status 0x0000] - 3.720501s
2020-03-01 07:58:37.072215 [PID 14540] fast89
2020-03-01 07:58:37.083717 [PID 14540; status 0x0000] - 0.011502s
2020-03-01 07:58:37.090785 [PID 14542] slow61
2020-03-01 07:58:37.158659 [PID 14542; status 0x0000] - 0.067874s
2020-03-01 07:58:37.165790 [PID 14544] slow11
2020-03-01 07:58:41.024668 [PID 14544; status 0x0000] - 3.858878s
2020-03-01 07:58:41.032007 [PID 14566] fast89
2020-03-01 07:58:41.043518 [PID 14566; status 0x0000] - 0.011511s
2020-03-01 07:58:41.053114 [PID 14568] slow61
2020-03-01 07:58:41.128938 [PID 14568; status 0x0000] - 0.075824s
2020-03-01 07:58:41.136826 [PID 14570] slow11
2020-03-01 07:58:44.971013 [PID 14570; status 0x0000] - 3.834187s
$
Не нужно много умения, чтобы увидеть, что код slow11
занимает примерно в 300 раз больше времени, чем код fast89
, а также отсутствие буферизации является ключевым фактором, поскольку slow61
работает примерно в 6-7 раз медленнее, чем fast89
.
Тестирование на MacBook Pro с MacOS Mojave 10.14.6 с SSD и использованием G CC 9.2.0 .