La capacité d'un tampon de tuyauterie varie d'un système à l'autre (et peut même varier sur le même système). Je ne suis pas sûr qu'il existe un moyen rapide, simple et multiplateforme de simplement rechercher la capacité d'un tuyau.
Mac OS X, par exemple, utilise une capacité de 16 384 octets par défaut, mais peut passer à une capacité de 65 336 octets si une écriture de grande taille est effectuée dans le canal, ou passera à une capacité d'une seule page système si la mémoire du noyau est déjà trop importante. utilisé par les tampons de pipe (voir xnu/bsd/sys/pipe.h
, et xnu/bsd/kern/sys_pipe.c
; puisque ceux-ci proviennent de FreeBSD, le même comportement peut se produire là aussi).
Une page de manuel pipe (7) de Linux indique que la capacité de la conduite est de 65 536 octets depuis Linux 2.6.11 et d'une seule page système antérieure à celle-ci (par exemple, 4096 octets sur des systèmes x86 (32 bits)). Le code ( include/linux/pipe_fs_i.h
, et fs/pipe.c
) semble utiliser 16 pages système (c’est-à-dire 64 Ko si une page système est de 4 Ko), mais le tampon de chaque conduite peut être ajusté via un fcntl sur la conduite (jusqu’à une capacité maximale de 1048576 par défaut) octets, mais peut être modifié via /proc/sys/fs/pipe-max-size
)).
Voici une petite combinaison bash / perl que j'ai utilisée pour tester la capacité de conduite de mon système:
#!/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"
Voici ce que j'ai trouvé en l'exécutant avec différentes tailles d'écriture sur un système Mac OS X 10.6.7 (notez le changement pour les écritures supérieures à 16 Ko):
% /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
Le même script sous 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
Remarque: La PIPE_BUF
valeur définie dans les fichiers d'en-tête C (et la valeur de pathconf pour _PC_PIPE_BUF
) ne spécifie pas la capacité des canaux, mais le nombre maximal d'octets pouvant être écrits de manière atomique (voir POSIX write (2) ).
Citation de 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()
sur Linux; J'avais passé un certain temps à rechercher des programmes de mise en mémoire tampon de l'espace utilisateur, car je pensais que les canaux intégrés ne disposaient pas d'une mémoire tampon suffisamment grande. Maintenant, je vois qu'ils le font, si j'ai CAP_SYS_RESOURCE ou si root est prêt à augmenter la taille maximale du tuyau. Comme ce que je veux ne sera exécuté que sur un ordinateur Linux spécifique (le mien), cela ne devrait pas poser de problème.var=…
) de la sortie d'une commande substitution ($(…)
) qui inclut des commandes groupées ({…}
, et(…)
). Il utilise également plusieurs redirections ( moins communes) (ie0<&-
et3>&1
).exec 0<&-
)). Le rapport final est collecté (tail -1
) et imprimé avec la taille d'écriture.cette ligne de commande peut aussi montrer la taille du tampon de tuyau:
(envoi de 1 000 morceaux au tuyau bloqué jusqu’à saturation du tampon) ... certaines sorties de test:
le plus court bash-one-liner utilisant printf:
la source
(dd if=/dev/zero bs=1 | sleep 999) &
puis attendez une seconde etkillall -SIGUSR1 dd
donne65536 bytes (66 kB) copied, 5.4987 s, 11.9 kB/s
- identique à votre solution, mais à une résolution de 1 octet;)dd
commande est bloquée à 16 Ko. Sur Fedora 23/25 x86-64, il bloque à 64 Ko.dd if=/dev/zero bs=1 | sleep 999
au premier plan, attendre une seconde, puis appuyer sur^C
. Si vous vouliez un one-liner sur Linux et BSD / macOS (plus robuste que l’utilisationkillall
):dd if=/dev/zero bs=1 | sleep 999 & sleep 1 && pkill -INT -P $$ -x dd
Voici d'autres alternatives pour explorer la capacité réelle du tampon de pipe à l'aide de commandes shell uniquement:
la source
getconf PIPE_BUF /
impressions5120
correspondent à laulimit -a | grep pipe
sortie mais ne correspondent pas aux 16 Ko après lesquels desdd .. | sleep ...
blocs.yes
méthode imprime73728
au lieu des 64 Ko déterminés avecdd if=/dev/zero bs=4096 status=none | pv -bn | sleep 1
Ceci est un hack rapide et sale sur Ubuntu 12.04, YMMV
la source
Donc, sur ma machine Linux, j'ai 8 * 512 = 4096 octets de canaux par défaut.
Solaris et de nombreux autres systèmes ont une fonction ulimit similaire.
la source
(512 bytes, -p) 8
sur Fedora 23/25 et512 bytes, -p) 10
sur Solaris 10 - et ces valeurs ne correspondent pas aux tailles de mémoire tampon déduites de manière expérimentale avec un blocagedd
.Si vous avez besoin de la valeur dans Python> = 3.3, voici une méthode simple (en supposant que vous puissiez exécuter call out to
dd
):la source