Емкость конвейерного буфера варьируется в зависимости от системы (и может даже различаться в одной и той же системе). Я не уверен, что существует быстрый, простой и кроссплатформенный способ просто проверить емкость трубы.
Например, Mac OS X по умолчанию использует емкость 16384 байта, но может переключиться на емкость 65336 байтов, если в канал выполняется большая запись, или переключится на емкость одной системной страницы, если уже слишком много памяти ядра используется конвейерными буферами (см. xnu/bsd/sys/pipe.h
, и xnu/bsd/kern/sys_pipe.c
, поскольку они взяты из FreeBSD, там тоже может происходить то же самое).
Одна справочная страница Linux pipe (7) сообщает, что емкость канала составляет 65536 байт начиная с Linux 2.6.11 и одну системную страницу до этого (например, 4096 байт в (32-разрядных) системах x86). Код ( include/linux/pipe_fs_i.h
, и fs/pipe.c
), по-видимому, использует 16 системных страниц (т. Е. 64 КиБ, если системная страница равна 4 КиБ), но буфер для каждого канала можно настроить с помощью fcntl на канале (до максимальной емкости, которая по умолчанию равна 1048576 байт, но можно изменить через /proc/sys/fs/pipe-max-size
)).
Вот небольшая комбинация bash / perl, которую я использовал для проверки производительности канала в моей системе:
#!/bin/bash
test $# -ge 1 || { echo "usage: $0 write-size [wait-time]"; exit 1; }
test $# -ge 2 || set -- "$@" 1
bytes_written=$(
{
exec 3>&1
{
perl -e '
$size = $ARGV[0];
$block = q(a) x $size;
$num_written = 0;
sub report { print STDERR $num_written * $size, qq(\n); }
report; while (defined syswrite STDOUT, $block) {
$num_written++; report;
}
' "$1" 2>&3
} | (sleep "$2"; exec 0<&-);
} | tail -1
)
printf "write size: %10d; bytes successfully before error: %d\n" \
"$1" "$bytes_written"
Вот что я обнаружил, запустив его с различными размерами записи в системе Mac OS X 10.6.7 (обратите внимание на изменение для записи размером более 16 КБ):
% /bin/bash -c 'for p in {0..18}; do /tmp/ts.sh $((2 ** $p)) 0.5; done'
write size: 1; bytes successfully before error: 16384
write size: 2; bytes successfully before error: 16384
write size: 4; bytes successfully before error: 16384
write size: 8; bytes successfully before error: 16384
write size: 16; bytes successfully before error: 16384
write size: 32; bytes successfully before error: 16384
write size: 64; bytes successfully before error: 16384
write size: 128; bytes successfully before error: 16384
write size: 256; bytes successfully before error: 16384
write size: 512; bytes successfully before error: 16384
write size: 1024; bytes successfully before error: 16384
write size: 2048; bytes successfully before error: 16384
write size: 4096; bytes successfully before error: 16384
write size: 8192; bytes successfully before error: 16384
write size: 16384; bytes successfully before error: 16384
write size: 32768; bytes successfully before error: 65536
write size: 65536; bytes successfully before error: 65536
write size: 131072; bytes successfully before error: 0
write size: 262144; bytes successfully before error: 0
Тот же скрипт в Linux 3.19:
/bin/bash -c 'for p in {0..18}; do /tmp/ts.sh $((2 ** $p)) 0.5; done'
write size: 1; bytes successfully before error: 65536
write size: 2; bytes successfully before error: 65536
write size: 4; bytes successfully before error: 65536
write size: 8; bytes successfully before error: 65536
write size: 16; bytes successfully before error: 65536
write size: 32; bytes successfully before error: 65536
write size: 64; bytes successfully before error: 65536
write size: 128; bytes successfully before error: 65536
write size: 256; bytes successfully before error: 65536
write size: 512; bytes successfully before error: 65536
write size: 1024; bytes successfully before error: 65536
write size: 2048; bytes successfully before error: 65536
write size: 4096; bytes successfully before error: 65536
write size: 8192; bytes successfully before error: 65536
write size: 16384; bytes successfully before error: 65536
write size: 32768; bytes successfully before error: 65536
write size: 65536; bytes successfully before error: 65536
write size: 131072; bytes successfully before error: 0
write size: 262144; bytes successfully before error: 0
Примечание. PIPE_BUF
Значение, определенное в заголовочных файлах C (и значение pathconf для _PC_PIPE_BUF
), указывает не емкость каналов, а максимальное количество байтов, которые могут быть записаны атомарно (см. Запись POSIX (2) ).
Цитата из include/linux/pipe_fs_i.h
:
/* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
memory allocation, whereas PIPE_BUF makes atomicity guarantees. */