Kapasitas penyangga pipa bervariasi antar sistem (dan bahkan dapat bervariasi pada sistem yang sama). Saya tidak yakin ada cara cepat, mudah, dan lintas platform untuk hanya melihat kapasitas pipa.
Mac OS X, misalnya, menggunakan kapasitas 16384 byte secara default, tetapi dapat beralih ke kapasitas 65336 byte jika penulisan besar dilakukan ke pipa, atau akan beralih ke kapasitas halaman sistem tunggal jika terlalu banyak memori kernel sudah sedang digunakan oleh penyangga pipa (lihat xnu/bsd/sys/pipe.h
, dan xnu/bsd/kern/sys_pipe.c
; karena ini dari FreeBSD, perilaku yang sama juga bisa terjadi di sana).
Satu halaman manual pipa Linux (7) mengatakan bahwa kapasitas pipa adalah 65536 byte sejak Linux 2.6.11 dan satu halaman sistem sebelumnya (mis. 4096 byte pada (32-bit) sistem x86). Kode ( include/linux/pipe_fs_i.h
, dan fs/pipe.c
) tampaknya menggunakan 16 halaman sistem (yaitu 64 KiB jika halaman sistem adalah 4 KiB), tetapi buffer untuk setiap pipa dapat disesuaikan melalui fcntl pada pipa (hingga kapasitas maksimum yang default ke 1048576 byte, tetapi dapat diubah melalui /proc/sys/fs/pipe-max-size
)).
Berikut adalah sedikit kombinasi bash / perl yang saya gunakan untuk menguji kapasitas pipa pada sistem saya:
#!/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"
Inilah yang saya temukan menjalankannya dengan berbagai ukuran tulis pada sistem Mac OS X 10.6.7 (perhatikan perubahan untuk penulisan yang lebih besar dari 16KiB):
% /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
Skrip yang sama di 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
Catatan: PIPE_BUF
Nilai yang ditentukan dalam file header C (dan nilai pathconf untuk _PC_PIPE_BUF
), tidak menentukan kapasitas pipa, tetapi jumlah maksimum byte yang dapat ditulis secara atom (lihat POSIX write (2) ).
Kutipan dari 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. */
fcntl()
di Linux; Saya telah menghabiskan waktu mencari program buffering userspace karena saya pikir pipa bawaan tidak memiliki buffer yang cukup besar. Sekarang saya melihat mereka melakukannya, jika saya memiliki CAP_SYS_RESOURCE atau root bersedia untuk memperluas ukuran pipa maksimum. Seperti yang saya inginkan hanya akan berjalan di komputer Linux tertentu (milik saya), ini seharusnya tidak menjadi masalah.var=…
) dari output substitusi perintah ($(…)
) yang mencakup perintah dikelompokkan ({…}
, dan(…)
). Itu juga menggunakan beberapa pengalihan ( kurang umum) (yaitu0<&-
dan3>&1
).exec 0<&-
)). Laporan akhir dikumpulkan (tail -1
) dan dicetak bersama dengan ukuran penulisan.shell-line ini juga dapat menunjukkan ukuran buffer pipa:
(mengirim potongan 1k ke pipa yang diblokir sampai buffer penuh) ... beberapa hasil uji:
bash-one-liner terpendek menggunakan printf:
sumber
(dd if=/dev/zero bs=1 | sleep 999) &
lalu tunggu sebentar dankillall -SIGUSR1 dd
berikan65536 bytes (66 kB) copied, 5.4987 s, 11.9 kB/s
- sama seperti solusi Anda, tetapi pada resolusi 1 byte;)dd
blok perintah di 16 KiB. Pada Fedora 23/25 x86-64, ia memblokir di 64 KiB.dd if=/dev/zero bs=1 | sleep 999
di latar depan, tunggu sebentar, lalu tekan^C
. Jika Anda menginginkan one-liner di Linux dan BSD / macOS (lebih kuat daripada menggunakankillall
):dd if=/dev/zero bs=1 | sleep 999 & sleep 1 && pkill -INT -P $$ -x dd
Berikut adalah beberapa alternatif lebih lanjut untuk mengeksplorasi kapasitas buffer pipa yang sebenarnya menggunakan perintah shell saja:
sumber
getconf PIPE_BUF /
cetakan5120
yang cocok denganulimit -a | grep pipe
output tetapi tidak cocok dengan 16 KiB setelahdd .. | sleep ...
blok mana .yes
metode pertama Anda mencetak73728
bukannya 64 KiB yang ditentukan dengandd if=/dev/zero bs=4096 status=none | pv -bn | sleep 1
Ini adalah hack cepat dan kotor di Ubuntu 12.04, YMMV
sumber
Jadi pada kotak Linux saya, saya memiliki 8 * 512 = 4096 byte pipa secara default.
Solaris dan banyak sistem lainnya memiliki fungsi ulimit yang serupa.
sumber
(512 bytes, -p) 8
pada Fedora 23/25 dan512 bytes, -p) 10
pada Solaris 10 - dan nilai-nilai itu tidak cocok dengan ukuran buffer yang diperoleh secara eksperimental dengan pemblokirandd
.Jika Anda membutuhkan nilai dalam Python> = 3.3, berikut adalah metode sederhana (dengan asumsi Anda dapat menjalankan panggilan keluar ke
dd
):sumber