How big is the pipe buffer?Turn off buffering in pipeIn what order do piped commands run?When would you use...
How do my husband and I get over our fear of having another difficult baby?
Why has Speaker Pelosi been so hesitant to impeach President Trump?
A word that refers to saying something in an attempt to anger or embarrass someone into doing something that they don’t want to do?
What does it mean by "my days-of-the-week underwear only go to Thursday" in this context?
Would a 737 pilot use flaps in nose dive?
Implementation of a Thread Pool in C++
Phonetic distortion when words are borrowed among languages
How to bring home documents from work?
What are one's options when facing religious discrimination at the airport?
Can you cure a Gorgon's Petrifying Breath before it finishes turning a target to stone?
Can an energy drink or chocolate before an exam be useful ? What sort of other edible goods be helpful?
How to study endgames?
How can I visualize an ordinal variable predicting a continuous outcome?
How do we know neutrons have no charge?
Create the same subfolders in another folder
Is there an in-universe explanation of how Frodo's arrival in Valinor was recorded in the Red Book?
Why is STARTTLS used when it can be downgraded very easily?
The differences amongst f[x_], f[x__], and f[x___]
grounded outlets and code compliance
What action is recommended if your accommodation refuses to let you leave without paying additional fees?
If a spaceship ran out of fuel somewhere in space between Earth and Mars, does it slowly drift off to the Sun?
Are devices supposed to automatically be removed from iCloud when all content and settings are erased?
How to level a picture frame hung on a single nail?
Why would an airline put 15 passengers at once on standby?
How big is the pipe buffer?
Turn off buffering in pipeIn what order do piped commands run?When would you use an additional file descriptor?On-the-fly stream compression that doesn't spill over into hardware resources?How to copy a directory which root can't access to a directory that only root can access?Understanding piped commands in Unix/Linuxoutput to file, then use file for inputCompare awk vs. grepI'm confused as to why “| true” in a makefile has the same effect as “|| true”How does Bash pipe large amounts of data?Non-blocking buffered named pipe?broken pipe error with popen and JS ffiWhy do we need two file descriptors when creating an unnamed pipe?Named pipes: several experiments leads to confusionRead everything in a pipe's buffer without waitingOpening named pipe blocks forever, if pipe is deleted without being connectedCan DD be used to add a buffer to a pipe?How can I time a pipe?Read until pipe is closedFlush the pipe/printf buffers externally for already running process with known PID
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}
As a comment in I'm confused as to why "| true" in a makefile has the same effect as "|| true" user cjm wrote:
Another reason to avoid | true is that if the command produced enough output to fill up the pipe buffer, it would block waiting for true to read it.
Do we have some way of finding out what the size of the pipe buffer is?
pipe buffer
add a comment
|
As a comment in I'm confused as to why "| true" in a makefile has the same effect as "|| true" user cjm wrote:
Another reason to avoid | true is that if the command produced enough output to fill up the pipe buffer, it would block waiting for true to read it.
Do we have some way of finding out what the size of the pipe buffer is?
pipe buffer
add a comment
|
As a comment in I'm confused as to why "| true" in a makefile has the same effect as "|| true" user cjm wrote:
Another reason to avoid | true is that if the command produced enough output to fill up the pipe buffer, it would block waiting for true to read it.
Do we have some way of finding out what the size of the pipe buffer is?
pipe buffer
As a comment in I'm confused as to why "| true" in a makefile has the same effect as "|| true" user cjm wrote:
Another reason to avoid | true is that if the command produced enough output to fill up the pipe buffer, it would block waiting for true to read it.
Do we have some way of finding out what the size of the pipe buffer is?
pipe buffer
pipe buffer
edited Apr 13 '17 at 12:36
Community♦
1
1
asked Apr 24 '11 at 23:11
Kit SundeKit Sunde
1,7649 gold badges23 silver badges31 bronze badges
1,7649 gold badges23 silver badges31 bronze badges
add a comment
|
add a comment
|
7 Answers
7
active
oldest
votes
The capacity of a pipe buffer varies across systems (and can even vary on the same system). I am not sure there is a quick, easy, and cross platform way to just lookup the capacity of a pipe.
Mac OS X, for example, uses a capacity of 16384 bytes by default, but can switch to 65336 byte capacities if large write are made to the pipe, or will switch to a capacity of a single system page if too much kernel memory is already being used by pipe buffers (see xnu/bsd/sys/pipe.h
, and xnu/bsd/kern/sys_pipe.c
; since these are from FreeBSD, the same behavior may happen there, too).
One Linux pipe(7) man page says that pipe capacity is 65536 bytes since Linux 2.6.11 and a single system page prior to that (e.g. 4096 bytes on (32-bit) x86 systems). The code (include/linux/pipe_fs_i.h
, and fs/pipe.c
) seems to use 16 system pages (i.e. 64 KiB if a system page is 4 KiB), but the buffer for each pipe can be adjusted via a fcntl on the pipe (up to a maximum capacity which defaults to 1048576 bytes, but can be changed via /proc/sys/fs/pipe-max-size
)).
Here is a little bash/perl combination that I used to test the pipe capacity on my system:
#!/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: %dn"
"$1" "$bytes_written"
Here is what I found running it with various write sizes on a Mac OS X 10.6.7 system (note the change for writes larger than 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
The same script on 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
Note: The PIPE_BUF
value defined in the C header files (and the pathconf value for _PC_PIPE_BUF
), does not specify the capacity of pipes, but the maximum number of bytes that can be written atomically (see POSIX write(2)).
Quote from 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. */
14
Great answer. Especially for the link to POSIX write(2), which says: The effective size of a pipe or FIFO (the maximum amount that can be written in one operation without blocking) may vary dynamically, depending on the implementation, so it is not possible to specify a fixed value for it.
– Mikel
Apr 25 '11 at 5:59
5
Thanks for mentioningfcntl()
on Linux; I had spent a while looking for userspace buffering programs because I thought the built-in pipes didn't have a large enough buffer. Now I see that they do, if I have CAP_SYS_RESOURCE or root is willing to expand the maximum pipe size. As what I want will only be run on a specific Linux computer (mine), this shouldn't be a problem.
– Daniel H
Aug 4 '13 at 18:43
1
Can you please explain the basic idea of your script? I am staring at it and I cannot figure out how it works? Especially what is the purpose using curly brackets here VAR=$({})? Thank you.
– Wakan Tanka
Mar 12 '15 at 0:24
@WakanTanka: It is a bit much to describe in a comment, but that particular construct is a parameter assignment (var=…
) of the output of a command substitution ($(…)
) that includes grouped commands ({…}
, and(…)
). It also uses several (less common) redirections (i.e.0<&-
and3>&1
).
– Chris Johnsen
Mar 12 '15 at 0:51
2
@WakanTanka: The Perl program writes to its stdout (a shell-created pipe—the one that is being tested) in blocks of a given size and reports to its stderr a running total of how much it has written (until it gets an error—usually because the pipe’s buffer is full or possibly because the reading end of the pipe has been closed after a short time (exec 0<&-
)). The final report is collected (tail -1
) and printed along with the write size.
– Chris Johnsen
Mar 12 '15 at 1:27
|
show 3 more comments
this shell-line can show pipe buffer size too:
M=0; while true; do dd if=/dev/zero bs=1k count=1 2>/dev/null;
M=$(($M+1)); echo -en "r$M KB" 1>&2; done | sleep 999
(sending 1k chunks to blocked pipe until buffer full) ...some test outputs:
64K (intel-debian), 32K (aix-ppc), 64K (jslinux bellard.org) ...Ctrl+C.
shortest bash-one-liner using printf:
M=0; while printf A; do >&2 printf "r$((++M)) B"; done | sleep 999
11
Very nice!(dd if=/dev/zero bs=1 | sleep 999) &
then wait a second andkillall -SIGUSR1 dd
gives65536 bytes (66 kB) copied, 5.4987 s, 11.9 kB/s
- same as your solution, but at 1 byte resolution ;)
– frostschutz
Apr 17 '13 at 23:21
2
For the record, on Solaris 10/11 SPARC/x86 thedd
command blocks at 16 KiB. On Fedora 23/25 x86-64, it blocks at 64 KiB.
– maxschlepzig
Jan 1 '17 at 12:08
1
@frostschutz: That's a nice simplification. Pragmatically, you could just rundd if=/dev/zero bs=1 | sleep 999
in the foreground, wait a second, then press^C
. If you wanted a one-liner on Linux and BSD/macOS (more robust than usingkillall
):dd if=/dev/zero bs=1 | sleep 999 & sleep 1 && pkill -INT -P $$ -x dd
– mklement0
Jan 23 '17 at 18:39
add a comment
|
Here are some further alternatives to explore the actual pipe buffer capacity using shell commands only:
# get pipe buffer size using Bash
yes produce_this_string_as_output | tee >(sleep 1) | wc -c
# portable version
( (sleep 1; exec yes produce_this_string_as_output) & echo $! ) |
(pid=$(head -1); sleep 2; kill "$pid"; wc -c </dev/stdin)
# get buffer size of named pipe
sh -c '
rm -f fifo
mkfifo fifo
yes produce_this_string_as_output | tee fifo | wc -c &
exec 3<&- 3<fifo
sleep 1
exec 3<&-
rm -f fifo
'
# Mac OS X
#getconf PIPE_BUF /
#open -e /usr/include/limits.h /usr/include/sys/pipe.h
# PIPE_SIZE
# BIG_PIPE_SIZE
# SMALL_PIPE_SIZE
# PIPE_MINDIRECT
On Solaris 10,getconf PIPE_BUF /
prints5120
which matches theulimit -a | grep pipe
output but doesn't match the 16 KiB after whichdd .. | sleep ...
blocks.
– maxschlepzig
Jan 1 '17 at 12:16
On Fedora 25, your firstyes
method prints73728
instead of the 64 KiB determined withdd if=/dev/zero bs=4096 status=none | pv -bn | sleep 1
– maxschlepzig
Jan 1 '17 at 12:30
add a comment
|
This is a quick and dirty hack on Ubuntu 12.04, YMMV
cat >pipesize.c
#include <unistd.h>
#include <errno.h>
#include </usr/include/linux/fcntl.h>
#include <stdio.h>
void main( int argc, char *argv[] ){
int fd ;
long pipesize ;
if( argc>1 ){
// if command line arg, associate a file descriptor with it
fprintf( stderr, "sizing %s ... ", argv[1] );
fd = open( argv[1], O_RDONLY|O_NONBLOCK );
}else{
// else use STDIN as the file descriptor
fprintf( stderr, "sizing STDIN ... " );
fd = 0 ;
}
fprintf( stderr, "%ld bytesn", (long)fcntl( fd, F_GETPIPE_SZ ));
if( errno )fprintf( stderr, "Uh oh, errno is %dn", errno );
if( fd )close( fd );
}
gcc -o pipesize pipesize.c
mkfifo /tmp/foo
./pipesize /tmp/foo
>sizing /tmp/foo ... 65536 bytes
date | ./pipesize
>sizing STDIN ... 65536 bytes
add a comment
|
$ ulimit -a | grep pipe
pipe size (512 bytes, -p) 8
So on my Linux box I have 8*512 = 4096 byte pipes by default.
Solaris and many other systems have a similar ulimit function.
2
This prints(512 bytes, -p) 8
on Fedora 23/25 and512 bytes, -p) 10
on Solaris 10 - and those values don't match the buffer sizes experimentally derived with a blockingdd
.
– maxschlepzig
Jan 1 '17 at 12:13
add a comment
|
If you need the value in Python>=3.3, here's a simple method (assuming you can run call out to dd
):
from subprocess import Popen, PIPE, TimeoutExpired
p = Popen(["dd", "if=/dev/zero", "bs=1"], stdin=PIPE, stdout=PIPE)
try:
p.wait(timeout=1)
except TimeoutExpired:
p.kill()
print(len(p.stdout.read()))
add a comment
|
Then you can read the stream file to live stream the output from subprocess command.
stream_file = "stream.log"
sys.stdout = open(stream_file, 'w+')
process = subprocess.Popen(shlex.split(command), stdout=sys.stdout, stderr=sys.stdout)
process.communicate()
New contributor
add a comment
|
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f11946%2fhow-big-is-the-pipe-buffer%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
7 Answers
7
active
oldest
votes
7 Answers
7
active
oldest
votes
active
oldest
votes
active
oldest
votes
The capacity of a pipe buffer varies across systems (and can even vary on the same system). I am not sure there is a quick, easy, and cross platform way to just lookup the capacity of a pipe.
Mac OS X, for example, uses a capacity of 16384 bytes by default, but can switch to 65336 byte capacities if large write are made to the pipe, or will switch to a capacity of a single system page if too much kernel memory is already being used by pipe buffers (see xnu/bsd/sys/pipe.h
, and xnu/bsd/kern/sys_pipe.c
; since these are from FreeBSD, the same behavior may happen there, too).
One Linux pipe(7) man page says that pipe capacity is 65536 bytes since Linux 2.6.11 and a single system page prior to that (e.g. 4096 bytes on (32-bit) x86 systems). The code (include/linux/pipe_fs_i.h
, and fs/pipe.c
) seems to use 16 system pages (i.e. 64 KiB if a system page is 4 KiB), but the buffer for each pipe can be adjusted via a fcntl on the pipe (up to a maximum capacity which defaults to 1048576 bytes, but can be changed via /proc/sys/fs/pipe-max-size
)).
Here is a little bash/perl combination that I used to test the pipe capacity on my system:
#!/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: %dn"
"$1" "$bytes_written"
Here is what I found running it with various write sizes on a Mac OS X 10.6.7 system (note the change for writes larger than 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
The same script on 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
Note: The PIPE_BUF
value defined in the C header files (and the pathconf value for _PC_PIPE_BUF
), does not specify the capacity of pipes, but the maximum number of bytes that can be written atomically (see POSIX write(2)).
Quote from 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. */
14
Great answer. Especially for the link to POSIX write(2), which says: The effective size of a pipe or FIFO (the maximum amount that can be written in one operation without blocking) may vary dynamically, depending on the implementation, so it is not possible to specify a fixed value for it.
– Mikel
Apr 25 '11 at 5:59
5
Thanks for mentioningfcntl()
on Linux; I had spent a while looking for userspace buffering programs because I thought the built-in pipes didn't have a large enough buffer. Now I see that they do, if I have CAP_SYS_RESOURCE or root is willing to expand the maximum pipe size. As what I want will only be run on a specific Linux computer (mine), this shouldn't be a problem.
– Daniel H
Aug 4 '13 at 18:43
1
Can you please explain the basic idea of your script? I am staring at it and I cannot figure out how it works? Especially what is the purpose using curly brackets here VAR=$({})? Thank you.
– Wakan Tanka
Mar 12 '15 at 0:24
@WakanTanka: It is a bit much to describe in a comment, but that particular construct is a parameter assignment (var=…
) of the output of a command substitution ($(…)
) that includes grouped commands ({…}
, and(…)
). It also uses several (less common) redirections (i.e.0<&-
and3>&1
).
– Chris Johnsen
Mar 12 '15 at 0:51
2
@WakanTanka: The Perl program writes to its stdout (a shell-created pipe—the one that is being tested) in blocks of a given size and reports to its stderr a running total of how much it has written (until it gets an error—usually because the pipe’s buffer is full or possibly because the reading end of the pipe has been closed after a short time (exec 0<&-
)). The final report is collected (tail -1
) and printed along with the write size.
– Chris Johnsen
Mar 12 '15 at 1:27
|
show 3 more comments
The capacity of a pipe buffer varies across systems (and can even vary on the same system). I am not sure there is a quick, easy, and cross platform way to just lookup the capacity of a pipe.
Mac OS X, for example, uses a capacity of 16384 bytes by default, but can switch to 65336 byte capacities if large write are made to the pipe, or will switch to a capacity of a single system page if too much kernel memory is already being used by pipe buffers (see xnu/bsd/sys/pipe.h
, and xnu/bsd/kern/sys_pipe.c
; since these are from FreeBSD, the same behavior may happen there, too).
One Linux pipe(7) man page says that pipe capacity is 65536 bytes since Linux 2.6.11 and a single system page prior to that (e.g. 4096 bytes on (32-bit) x86 systems). The code (include/linux/pipe_fs_i.h
, and fs/pipe.c
) seems to use 16 system pages (i.e. 64 KiB if a system page is 4 KiB), but the buffer for each pipe can be adjusted via a fcntl on the pipe (up to a maximum capacity which defaults to 1048576 bytes, but can be changed via /proc/sys/fs/pipe-max-size
)).
Here is a little bash/perl combination that I used to test the pipe capacity on my system:
#!/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: %dn"
"$1" "$bytes_written"
Here is what I found running it with various write sizes on a Mac OS X 10.6.7 system (note the change for writes larger than 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
The same script on 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
Note: The PIPE_BUF
value defined in the C header files (and the pathconf value for _PC_PIPE_BUF
), does not specify the capacity of pipes, but the maximum number of bytes that can be written atomically (see POSIX write(2)).
Quote from 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. */
14
Great answer. Especially for the link to POSIX write(2), which says: The effective size of a pipe or FIFO (the maximum amount that can be written in one operation without blocking) may vary dynamically, depending on the implementation, so it is not possible to specify a fixed value for it.
– Mikel
Apr 25 '11 at 5:59
5
Thanks for mentioningfcntl()
on Linux; I had spent a while looking for userspace buffering programs because I thought the built-in pipes didn't have a large enough buffer. Now I see that they do, if I have CAP_SYS_RESOURCE or root is willing to expand the maximum pipe size. As what I want will only be run on a specific Linux computer (mine), this shouldn't be a problem.
– Daniel H
Aug 4 '13 at 18:43
1
Can you please explain the basic idea of your script? I am staring at it and I cannot figure out how it works? Especially what is the purpose using curly brackets here VAR=$({})? Thank you.
– Wakan Tanka
Mar 12 '15 at 0:24
@WakanTanka: It is a bit much to describe in a comment, but that particular construct is a parameter assignment (var=…
) of the output of a command substitution ($(…)
) that includes grouped commands ({…}
, and(…)
). It also uses several (less common) redirections (i.e.0<&-
and3>&1
).
– Chris Johnsen
Mar 12 '15 at 0:51
2
@WakanTanka: The Perl program writes to its stdout (a shell-created pipe—the one that is being tested) in blocks of a given size and reports to its stderr a running total of how much it has written (until it gets an error—usually because the pipe’s buffer is full or possibly because the reading end of the pipe has been closed after a short time (exec 0<&-
)). The final report is collected (tail -1
) and printed along with the write size.
– Chris Johnsen
Mar 12 '15 at 1:27
|
show 3 more comments
The capacity of a pipe buffer varies across systems (and can even vary on the same system). I am not sure there is a quick, easy, and cross platform way to just lookup the capacity of a pipe.
Mac OS X, for example, uses a capacity of 16384 bytes by default, but can switch to 65336 byte capacities if large write are made to the pipe, or will switch to a capacity of a single system page if too much kernel memory is already being used by pipe buffers (see xnu/bsd/sys/pipe.h
, and xnu/bsd/kern/sys_pipe.c
; since these are from FreeBSD, the same behavior may happen there, too).
One Linux pipe(7) man page says that pipe capacity is 65536 bytes since Linux 2.6.11 and a single system page prior to that (e.g. 4096 bytes on (32-bit) x86 systems). The code (include/linux/pipe_fs_i.h
, and fs/pipe.c
) seems to use 16 system pages (i.e. 64 KiB if a system page is 4 KiB), but the buffer for each pipe can be adjusted via a fcntl on the pipe (up to a maximum capacity which defaults to 1048576 bytes, but can be changed via /proc/sys/fs/pipe-max-size
)).
Here is a little bash/perl combination that I used to test the pipe capacity on my system:
#!/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: %dn"
"$1" "$bytes_written"
Here is what I found running it with various write sizes on a Mac OS X 10.6.7 system (note the change for writes larger than 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
The same script on 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
Note: The PIPE_BUF
value defined in the C header files (and the pathconf value for _PC_PIPE_BUF
), does not specify the capacity of pipes, but the maximum number of bytes that can be written atomically (see POSIX write(2)).
Quote from 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. */
The capacity of a pipe buffer varies across systems (and can even vary on the same system). I am not sure there is a quick, easy, and cross platform way to just lookup the capacity of a pipe.
Mac OS X, for example, uses a capacity of 16384 bytes by default, but can switch to 65336 byte capacities if large write are made to the pipe, or will switch to a capacity of a single system page if too much kernel memory is already being used by pipe buffers (see xnu/bsd/sys/pipe.h
, and xnu/bsd/kern/sys_pipe.c
; since these are from FreeBSD, the same behavior may happen there, too).
One Linux pipe(7) man page says that pipe capacity is 65536 bytes since Linux 2.6.11 and a single system page prior to that (e.g. 4096 bytes on (32-bit) x86 systems). The code (include/linux/pipe_fs_i.h
, and fs/pipe.c
) seems to use 16 system pages (i.e. 64 KiB if a system page is 4 KiB), but the buffer for each pipe can be adjusted via a fcntl on the pipe (up to a maximum capacity which defaults to 1048576 bytes, but can be changed via /proc/sys/fs/pipe-max-size
)).
Here is a little bash/perl combination that I used to test the pipe capacity on my system:
#!/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: %dn"
"$1" "$bytes_written"
Here is what I found running it with various write sizes on a Mac OS X 10.6.7 system (note the change for writes larger than 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
The same script on 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
Note: The PIPE_BUF
value defined in the C header files (and the pathconf value for _PC_PIPE_BUF
), does not specify the capacity of pipes, but the maximum number of bytes that can be written atomically (see POSIX write(2)).
Quote from 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. */
edited Mar 24 '15 at 8:26
Jakob
3252 silver badges5 bronze badges
3252 silver badges5 bronze badges
answered Apr 25 '11 at 5:32
Chris JohnsenChris Johnsen
15.7k6 gold badges52 silver badges48 bronze badges
15.7k6 gold badges52 silver badges48 bronze badges
14
Great answer. Especially for the link to POSIX write(2), which says: The effective size of a pipe or FIFO (the maximum amount that can be written in one operation without blocking) may vary dynamically, depending on the implementation, so it is not possible to specify a fixed value for it.
– Mikel
Apr 25 '11 at 5:59
5
Thanks for mentioningfcntl()
on Linux; I had spent a while looking for userspace buffering programs because I thought the built-in pipes didn't have a large enough buffer. Now I see that they do, if I have CAP_SYS_RESOURCE or root is willing to expand the maximum pipe size. As what I want will only be run on a specific Linux computer (mine), this shouldn't be a problem.
– Daniel H
Aug 4 '13 at 18:43
1
Can you please explain the basic idea of your script? I am staring at it and I cannot figure out how it works? Especially what is the purpose using curly brackets here VAR=$({})? Thank you.
– Wakan Tanka
Mar 12 '15 at 0:24
@WakanTanka: It is a bit much to describe in a comment, but that particular construct is a parameter assignment (var=…
) of the output of a command substitution ($(…)
) that includes grouped commands ({…}
, and(…)
). It also uses several (less common) redirections (i.e.0<&-
and3>&1
).
– Chris Johnsen
Mar 12 '15 at 0:51
2
@WakanTanka: The Perl program writes to its stdout (a shell-created pipe—the one that is being tested) in blocks of a given size and reports to its stderr a running total of how much it has written (until it gets an error—usually because the pipe’s buffer is full or possibly because the reading end of the pipe has been closed after a short time (exec 0<&-
)). The final report is collected (tail -1
) and printed along with the write size.
– Chris Johnsen
Mar 12 '15 at 1:27
|
show 3 more comments
14
Great answer. Especially for the link to POSIX write(2), which says: The effective size of a pipe or FIFO (the maximum amount that can be written in one operation without blocking) may vary dynamically, depending on the implementation, so it is not possible to specify a fixed value for it.
– Mikel
Apr 25 '11 at 5:59
5
Thanks for mentioningfcntl()
on Linux; I had spent a while looking for userspace buffering programs because I thought the built-in pipes didn't have a large enough buffer. Now I see that they do, if I have CAP_SYS_RESOURCE or root is willing to expand the maximum pipe size. As what I want will only be run on a specific Linux computer (mine), this shouldn't be a problem.
– Daniel H
Aug 4 '13 at 18:43
1
Can you please explain the basic idea of your script? I am staring at it and I cannot figure out how it works? Especially what is the purpose using curly brackets here VAR=$({})? Thank you.
– Wakan Tanka
Mar 12 '15 at 0:24
@WakanTanka: It is a bit much to describe in a comment, but that particular construct is a parameter assignment (var=…
) of the output of a command substitution ($(…)
) that includes grouped commands ({…}
, and(…)
). It also uses several (less common) redirections (i.e.0<&-
and3>&1
).
– Chris Johnsen
Mar 12 '15 at 0:51
2
@WakanTanka: The Perl program writes to its stdout (a shell-created pipe—the one that is being tested) in blocks of a given size and reports to its stderr a running total of how much it has written (until it gets an error—usually because the pipe’s buffer is full or possibly because the reading end of the pipe has been closed after a short time (exec 0<&-
)). The final report is collected (tail -1
) and printed along with the write size.
– Chris Johnsen
Mar 12 '15 at 1:27
14
14
Great answer. Especially for the link to POSIX write(2), which says: The effective size of a pipe or FIFO (the maximum amount that can be written in one operation without blocking) may vary dynamically, depending on the implementation, so it is not possible to specify a fixed value for it.
– Mikel
Apr 25 '11 at 5:59
Great answer. Especially for the link to POSIX write(2), which says: The effective size of a pipe or FIFO (the maximum amount that can be written in one operation without blocking) may vary dynamically, depending on the implementation, so it is not possible to specify a fixed value for it.
– Mikel
Apr 25 '11 at 5:59
5
5
Thanks for mentioning
fcntl()
on Linux; I had spent a while looking for userspace buffering programs because I thought the built-in pipes didn't have a large enough buffer. Now I see that they do, if I have CAP_SYS_RESOURCE or root is willing to expand the maximum pipe size. As what I want will only be run on a specific Linux computer (mine), this shouldn't be a problem.– Daniel H
Aug 4 '13 at 18:43
Thanks for mentioning
fcntl()
on Linux; I had spent a while looking for userspace buffering programs because I thought the built-in pipes didn't have a large enough buffer. Now I see that they do, if I have CAP_SYS_RESOURCE or root is willing to expand the maximum pipe size. As what I want will only be run on a specific Linux computer (mine), this shouldn't be a problem.– Daniel H
Aug 4 '13 at 18:43
1
1
Can you please explain the basic idea of your script? I am staring at it and I cannot figure out how it works? Especially what is the purpose using curly brackets here VAR=$({})? Thank you.
– Wakan Tanka
Mar 12 '15 at 0:24
Can you please explain the basic idea of your script? I am staring at it and I cannot figure out how it works? Especially what is the purpose using curly brackets here VAR=$({})? Thank you.
– Wakan Tanka
Mar 12 '15 at 0:24
@WakanTanka: It is a bit much to describe in a comment, but that particular construct is a parameter assignment (
var=…
) of the output of a command substitution ($(…)
) that includes grouped commands ({…}
, and (…)
). It also uses several (less common) redirections (i.e. 0<&-
and 3>&1
).– Chris Johnsen
Mar 12 '15 at 0:51
@WakanTanka: It is a bit much to describe in a comment, but that particular construct is a parameter assignment (
var=…
) of the output of a command substitution ($(…)
) that includes grouped commands ({…}
, and (…)
). It also uses several (less common) redirections (i.e. 0<&-
and 3>&1
).– Chris Johnsen
Mar 12 '15 at 0:51
2
2
@WakanTanka: The Perl program writes to its stdout (a shell-created pipe—the one that is being tested) in blocks of a given size and reports to its stderr a running total of how much it has written (until it gets an error—usually because the pipe’s buffer is full or possibly because the reading end of the pipe has been closed after a short time (
exec 0<&-
)). The final report is collected (tail -1
) and printed along with the write size.– Chris Johnsen
Mar 12 '15 at 1:27
@WakanTanka: The Perl program writes to its stdout (a shell-created pipe—the one that is being tested) in blocks of a given size and reports to its stderr a running total of how much it has written (until it gets an error—usually because the pipe’s buffer is full or possibly because the reading end of the pipe has been closed after a short time (
exec 0<&-
)). The final report is collected (tail -1
) and printed along with the write size.– Chris Johnsen
Mar 12 '15 at 1:27
|
show 3 more comments
this shell-line can show pipe buffer size too:
M=0; while true; do dd if=/dev/zero bs=1k count=1 2>/dev/null;
M=$(($M+1)); echo -en "r$M KB" 1>&2; done | sleep 999
(sending 1k chunks to blocked pipe until buffer full) ...some test outputs:
64K (intel-debian), 32K (aix-ppc), 64K (jslinux bellard.org) ...Ctrl+C.
shortest bash-one-liner using printf:
M=0; while printf A; do >&2 printf "r$((++M)) B"; done | sleep 999
11
Very nice!(dd if=/dev/zero bs=1 | sleep 999) &
then wait a second andkillall -SIGUSR1 dd
gives65536 bytes (66 kB) copied, 5.4987 s, 11.9 kB/s
- same as your solution, but at 1 byte resolution ;)
– frostschutz
Apr 17 '13 at 23:21
2
For the record, on Solaris 10/11 SPARC/x86 thedd
command blocks at 16 KiB. On Fedora 23/25 x86-64, it blocks at 64 KiB.
– maxschlepzig
Jan 1 '17 at 12:08
1
@frostschutz: That's a nice simplification. Pragmatically, you could just rundd if=/dev/zero bs=1 | sleep 999
in the foreground, wait a second, then press^C
. If you wanted a one-liner on Linux and BSD/macOS (more robust than usingkillall
):dd if=/dev/zero bs=1 | sleep 999 & sleep 1 && pkill -INT -P $$ -x dd
– mklement0
Jan 23 '17 at 18:39
add a comment
|
this shell-line can show pipe buffer size too:
M=0; while true; do dd if=/dev/zero bs=1k count=1 2>/dev/null;
M=$(($M+1)); echo -en "r$M KB" 1>&2; done | sleep 999
(sending 1k chunks to blocked pipe until buffer full) ...some test outputs:
64K (intel-debian), 32K (aix-ppc), 64K (jslinux bellard.org) ...Ctrl+C.
shortest bash-one-liner using printf:
M=0; while printf A; do >&2 printf "r$((++M)) B"; done | sleep 999
11
Very nice!(dd if=/dev/zero bs=1 | sleep 999) &
then wait a second andkillall -SIGUSR1 dd
gives65536 bytes (66 kB) copied, 5.4987 s, 11.9 kB/s
- same as your solution, but at 1 byte resolution ;)
– frostschutz
Apr 17 '13 at 23:21
2
For the record, on Solaris 10/11 SPARC/x86 thedd
command blocks at 16 KiB. On Fedora 23/25 x86-64, it blocks at 64 KiB.
– maxschlepzig
Jan 1 '17 at 12:08
1
@frostschutz: That's a nice simplification. Pragmatically, you could just rundd if=/dev/zero bs=1 | sleep 999
in the foreground, wait a second, then press^C
. If you wanted a one-liner on Linux and BSD/macOS (more robust than usingkillall
):dd if=/dev/zero bs=1 | sleep 999 & sleep 1 && pkill -INT -P $$ -x dd
– mklement0
Jan 23 '17 at 18:39
add a comment
|
this shell-line can show pipe buffer size too:
M=0; while true; do dd if=/dev/zero bs=1k count=1 2>/dev/null;
M=$(($M+1)); echo -en "r$M KB" 1>&2; done | sleep 999
(sending 1k chunks to blocked pipe until buffer full) ...some test outputs:
64K (intel-debian), 32K (aix-ppc), 64K (jslinux bellard.org) ...Ctrl+C.
shortest bash-one-liner using printf:
M=0; while printf A; do >&2 printf "r$((++M)) B"; done | sleep 999
this shell-line can show pipe buffer size too:
M=0; while true; do dd if=/dev/zero bs=1k count=1 2>/dev/null;
M=$(($M+1)); echo -en "r$M KB" 1>&2; done | sleep 999
(sending 1k chunks to blocked pipe until buffer full) ...some test outputs:
64K (intel-debian), 32K (aix-ppc), 64K (jslinux bellard.org) ...Ctrl+C.
shortest bash-one-liner using printf:
M=0; while printf A; do >&2 printf "r$((++M)) B"; done | sleep 999
edited Oct 27 '17 at 12:53
answered Apr 17 '13 at 22:52
Asain KujovicAsain Kujovic
1,07411 silver badges16 bronze badges
1,07411 silver badges16 bronze badges
11
Very nice!(dd if=/dev/zero bs=1 | sleep 999) &
then wait a second andkillall -SIGUSR1 dd
gives65536 bytes (66 kB) copied, 5.4987 s, 11.9 kB/s
- same as your solution, but at 1 byte resolution ;)
– frostschutz
Apr 17 '13 at 23:21
2
For the record, on Solaris 10/11 SPARC/x86 thedd
command blocks at 16 KiB. On Fedora 23/25 x86-64, it blocks at 64 KiB.
– maxschlepzig
Jan 1 '17 at 12:08
1
@frostschutz: That's a nice simplification. Pragmatically, you could just rundd if=/dev/zero bs=1 | sleep 999
in the foreground, wait a second, then press^C
. If you wanted a one-liner on Linux and BSD/macOS (more robust than usingkillall
):dd if=/dev/zero bs=1 | sleep 999 & sleep 1 && pkill -INT -P $$ -x dd
– mklement0
Jan 23 '17 at 18:39
add a comment
|
11
Very nice!(dd if=/dev/zero bs=1 | sleep 999) &
then wait a second andkillall -SIGUSR1 dd
gives65536 bytes (66 kB) copied, 5.4987 s, 11.9 kB/s
- same as your solution, but at 1 byte resolution ;)
– frostschutz
Apr 17 '13 at 23:21
2
For the record, on Solaris 10/11 SPARC/x86 thedd
command blocks at 16 KiB. On Fedora 23/25 x86-64, it blocks at 64 KiB.
– maxschlepzig
Jan 1 '17 at 12:08
1
@frostschutz: That's a nice simplification. Pragmatically, you could just rundd if=/dev/zero bs=1 | sleep 999
in the foreground, wait a second, then press^C
. If you wanted a one-liner on Linux and BSD/macOS (more robust than usingkillall
):dd if=/dev/zero bs=1 | sleep 999 & sleep 1 && pkill -INT -P $$ -x dd
– mklement0
Jan 23 '17 at 18:39
11
11
Very nice!
(dd if=/dev/zero bs=1 | sleep 999) &
then wait a second and killall -SIGUSR1 dd
gives 65536 bytes (66 kB) copied, 5.4987 s, 11.9 kB/s
- same as your solution, but at 1 byte resolution ;)– frostschutz
Apr 17 '13 at 23:21
Very nice!
(dd if=/dev/zero bs=1 | sleep 999) &
then wait a second and killall -SIGUSR1 dd
gives 65536 bytes (66 kB) copied, 5.4987 s, 11.9 kB/s
- same as your solution, but at 1 byte resolution ;)– frostschutz
Apr 17 '13 at 23:21
2
2
For the record, on Solaris 10/11 SPARC/x86 the
dd
command blocks at 16 KiB. On Fedora 23/25 x86-64, it blocks at 64 KiB.– maxschlepzig
Jan 1 '17 at 12:08
For the record, on Solaris 10/11 SPARC/x86 the
dd
command blocks at 16 KiB. On Fedora 23/25 x86-64, it blocks at 64 KiB.– maxschlepzig
Jan 1 '17 at 12:08
1
1
@frostschutz: That's a nice simplification. Pragmatically, you could just run
dd if=/dev/zero bs=1 | sleep 999
in the foreground, wait a second, then press ^C
. If you wanted a one-liner on Linux and BSD/macOS (more robust than using killall
): dd if=/dev/zero bs=1 | sleep 999 & sleep 1 && pkill -INT -P $$ -x dd
– mklement0
Jan 23 '17 at 18:39
@frostschutz: That's a nice simplification. Pragmatically, you could just run
dd if=/dev/zero bs=1 | sleep 999
in the foreground, wait a second, then press ^C
. If you wanted a one-liner on Linux and BSD/macOS (more robust than using killall
): dd if=/dev/zero bs=1 | sleep 999 & sleep 1 && pkill -INT -P $$ -x dd
– mklement0
Jan 23 '17 at 18:39
add a comment
|
Here are some further alternatives to explore the actual pipe buffer capacity using shell commands only:
# get pipe buffer size using Bash
yes produce_this_string_as_output | tee >(sleep 1) | wc -c
# portable version
( (sleep 1; exec yes produce_this_string_as_output) & echo $! ) |
(pid=$(head -1); sleep 2; kill "$pid"; wc -c </dev/stdin)
# get buffer size of named pipe
sh -c '
rm -f fifo
mkfifo fifo
yes produce_this_string_as_output | tee fifo | wc -c &
exec 3<&- 3<fifo
sleep 1
exec 3<&-
rm -f fifo
'
# Mac OS X
#getconf PIPE_BUF /
#open -e /usr/include/limits.h /usr/include/sys/pipe.h
# PIPE_SIZE
# BIG_PIPE_SIZE
# SMALL_PIPE_SIZE
# PIPE_MINDIRECT
On Solaris 10,getconf PIPE_BUF /
prints5120
which matches theulimit -a | grep pipe
output but doesn't match the 16 KiB after whichdd .. | sleep ...
blocks.
– maxschlepzig
Jan 1 '17 at 12:16
On Fedora 25, your firstyes
method prints73728
instead of the 64 KiB determined withdd if=/dev/zero bs=4096 status=none | pv -bn | sleep 1
– maxschlepzig
Jan 1 '17 at 12:30
add a comment
|
Here are some further alternatives to explore the actual pipe buffer capacity using shell commands only:
# get pipe buffer size using Bash
yes produce_this_string_as_output | tee >(sleep 1) | wc -c
# portable version
( (sleep 1; exec yes produce_this_string_as_output) & echo $! ) |
(pid=$(head -1); sleep 2; kill "$pid"; wc -c </dev/stdin)
# get buffer size of named pipe
sh -c '
rm -f fifo
mkfifo fifo
yes produce_this_string_as_output | tee fifo | wc -c &
exec 3<&- 3<fifo
sleep 1
exec 3<&-
rm -f fifo
'
# Mac OS X
#getconf PIPE_BUF /
#open -e /usr/include/limits.h /usr/include/sys/pipe.h
# PIPE_SIZE
# BIG_PIPE_SIZE
# SMALL_PIPE_SIZE
# PIPE_MINDIRECT
On Solaris 10,getconf PIPE_BUF /
prints5120
which matches theulimit -a | grep pipe
output but doesn't match the 16 KiB after whichdd .. | sleep ...
blocks.
– maxschlepzig
Jan 1 '17 at 12:16
On Fedora 25, your firstyes
method prints73728
instead of the 64 KiB determined withdd if=/dev/zero bs=4096 status=none | pv -bn | sleep 1
– maxschlepzig
Jan 1 '17 at 12:30
add a comment
|
Here are some further alternatives to explore the actual pipe buffer capacity using shell commands only:
# get pipe buffer size using Bash
yes produce_this_string_as_output | tee >(sleep 1) | wc -c
# portable version
( (sleep 1; exec yes produce_this_string_as_output) & echo $! ) |
(pid=$(head -1); sleep 2; kill "$pid"; wc -c </dev/stdin)
# get buffer size of named pipe
sh -c '
rm -f fifo
mkfifo fifo
yes produce_this_string_as_output | tee fifo | wc -c &
exec 3<&- 3<fifo
sleep 1
exec 3<&-
rm -f fifo
'
# Mac OS X
#getconf PIPE_BUF /
#open -e /usr/include/limits.h /usr/include/sys/pipe.h
# PIPE_SIZE
# BIG_PIPE_SIZE
# SMALL_PIPE_SIZE
# PIPE_MINDIRECT
Here are some further alternatives to explore the actual pipe buffer capacity using shell commands only:
# get pipe buffer size using Bash
yes produce_this_string_as_output | tee >(sleep 1) | wc -c
# portable version
( (sleep 1; exec yes produce_this_string_as_output) & echo $! ) |
(pid=$(head -1); sleep 2; kill "$pid"; wc -c </dev/stdin)
# get buffer size of named pipe
sh -c '
rm -f fifo
mkfifo fifo
yes produce_this_string_as_output | tee fifo | wc -c &
exec 3<&- 3<fifo
sleep 1
exec 3<&-
rm -f fifo
'
# Mac OS X
#getconf PIPE_BUF /
#open -e /usr/include/limits.h /usr/include/sys/pipe.h
# PIPE_SIZE
# BIG_PIPE_SIZE
# SMALL_PIPE_SIZE
# PIPE_MINDIRECT
answered Oct 28 '14 at 14:16
chanchan
711 silver badge1 bronze badge
711 silver badge1 bronze badge
On Solaris 10,getconf PIPE_BUF /
prints5120
which matches theulimit -a | grep pipe
output but doesn't match the 16 KiB after whichdd .. | sleep ...
blocks.
– maxschlepzig
Jan 1 '17 at 12:16
On Fedora 25, your firstyes
method prints73728
instead of the 64 KiB determined withdd if=/dev/zero bs=4096 status=none | pv -bn | sleep 1
– maxschlepzig
Jan 1 '17 at 12:30
add a comment
|
On Solaris 10,getconf PIPE_BUF /
prints5120
which matches theulimit -a | grep pipe
output but doesn't match the 16 KiB after whichdd .. | sleep ...
blocks.
– maxschlepzig
Jan 1 '17 at 12:16
On Fedora 25, your firstyes
method prints73728
instead of the 64 KiB determined withdd if=/dev/zero bs=4096 status=none | pv -bn | sleep 1
– maxschlepzig
Jan 1 '17 at 12:30
On Solaris 10,
getconf PIPE_BUF /
prints 5120
which matches the ulimit -a | grep pipe
output but doesn't match the 16 KiB after which dd .. | sleep ...
blocks.– maxschlepzig
Jan 1 '17 at 12:16
On Solaris 10,
getconf PIPE_BUF /
prints 5120
which matches the ulimit -a | grep pipe
output but doesn't match the 16 KiB after which dd .. | sleep ...
blocks.– maxschlepzig
Jan 1 '17 at 12:16
On Fedora 25, your first
yes
method prints 73728
instead of the 64 KiB determined with dd if=/dev/zero bs=4096 status=none | pv -bn | sleep 1
– maxschlepzig
Jan 1 '17 at 12:30
On Fedora 25, your first
yes
method prints 73728
instead of the 64 KiB determined with dd if=/dev/zero bs=4096 status=none | pv -bn | sleep 1
– maxschlepzig
Jan 1 '17 at 12:30
add a comment
|
This is a quick and dirty hack on Ubuntu 12.04, YMMV
cat >pipesize.c
#include <unistd.h>
#include <errno.h>
#include </usr/include/linux/fcntl.h>
#include <stdio.h>
void main( int argc, char *argv[] ){
int fd ;
long pipesize ;
if( argc>1 ){
// if command line arg, associate a file descriptor with it
fprintf( stderr, "sizing %s ... ", argv[1] );
fd = open( argv[1], O_RDONLY|O_NONBLOCK );
}else{
// else use STDIN as the file descriptor
fprintf( stderr, "sizing STDIN ... " );
fd = 0 ;
}
fprintf( stderr, "%ld bytesn", (long)fcntl( fd, F_GETPIPE_SZ ));
if( errno )fprintf( stderr, "Uh oh, errno is %dn", errno );
if( fd )close( fd );
}
gcc -o pipesize pipesize.c
mkfifo /tmp/foo
./pipesize /tmp/foo
>sizing /tmp/foo ... 65536 bytes
date | ./pipesize
>sizing STDIN ... 65536 bytes
add a comment
|
This is a quick and dirty hack on Ubuntu 12.04, YMMV
cat >pipesize.c
#include <unistd.h>
#include <errno.h>
#include </usr/include/linux/fcntl.h>
#include <stdio.h>
void main( int argc, char *argv[] ){
int fd ;
long pipesize ;
if( argc>1 ){
// if command line arg, associate a file descriptor with it
fprintf( stderr, "sizing %s ... ", argv[1] );
fd = open( argv[1], O_RDONLY|O_NONBLOCK );
}else{
// else use STDIN as the file descriptor
fprintf( stderr, "sizing STDIN ... " );
fd = 0 ;
}
fprintf( stderr, "%ld bytesn", (long)fcntl( fd, F_GETPIPE_SZ ));
if( errno )fprintf( stderr, "Uh oh, errno is %dn", errno );
if( fd )close( fd );
}
gcc -o pipesize pipesize.c
mkfifo /tmp/foo
./pipesize /tmp/foo
>sizing /tmp/foo ... 65536 bytes
date | ./pipesize
>sizing STDIN ... 65536 bytes
add a comment
|
This is a quick and dirty hack on Ubuntu 12.04, YMMV
cat >pipesize.c
#include <unistd.h>
#include <errno.h>
#include </usr/include/linux/fcntl.h>
#include <stdio.h>
void main( int argc, char *argv[] ){
int fd ;
long pipesize ;
if( argc>1 ){
// if command line arg, associate a file descriptor with it
fprintf( stderr, "sizing %s ... ", argv[1] );
fd = open( argv[1], O_RDONLY|O_NONBLOCK );
}else{
// else use STDIN as the file descriptor
fprintf( stderr, "sizing STDIN ... " );
fd = 0 ;
}
fprintf( stderr, "%ld bytesn", (long)fcntl( fd, F_GETPIPE_SZ ));
if( errno )fprintf( stderr, "Uh oh, errno is %dn", errno );
if( fd )close( fd );
}
gcc -o pipesize pipesize.c
mkfifo /tmp/foo
./pipesize /tmp/foo
>sizing /tmp/foo ... 65536 bytes
date | ./pipesize
>sizing STDIN ... 65536 bytes
This is a quick and dirty hack on Ubuntu 12.04, YMMV
cat >pipesize.c
#include <unistd.h>
#include <errno.h>
#include </usr/include/linux/fcntl.h>
#include <stdio.h>
void main( int argc, char *argv[] ){
int fd ;
long pipesize ;
if( argc>1 ){
// if command line arg, associate a file descriptor with it
fprintf( stderr, "sizing %s ... ", argv[1] );
fd = open( argv[1], O_RDONLY|O_NONBLOCK );
}else{
// else use STDIN as the file descriptor
fprintf( stderr, "sizing STDIN ... " );
fd = 0 ;
}
fprintf( stderr, "%ld bytesn", (long)fcntl( fd, F_GETPIPE_SZ ));
if( errno )fprintf( stderr, "Uh oh, errno is %dn", errno );
if( fd )close( fd );
}
gcc -o pipesize pipesize.c
mkfifo /tmp/foo
./pipesize /tmp/foo
>sizing /tmp/foo ... 65536 bytes
date | ./pipesize
>sizing STDIN ... 65536 bytes
edited Sep 11 '14 at 2:31
drs
3,4286 gold badges30 silver badges62 bronze badges
3,4286 gold badges30 silver badges62 bronze badges
answered Sep 11 '14 at 2:06
JeffJeff
1,1181 gold badge8 silver badges7 bronze badges
1,1181 gold badge8 silver badges7 bronze badges
add a comment
|
add a comment
|
$ ulimit -a | grep pipe
pipe size (512 bytes, -p) 8
So on my Linux box I have 8*512 = 4096 byte pipes by default.
Solaris and many other systems have a similar ulimit function.
2
This prints(512 bytes, -p) 8
on Fedora 23/25 and512 bytes, -p) 10
on Solaris 10 - and those values don't match the buffer sizes experimentally derived with a blockingdd
.
– maxschlepzig
Jan 1 '17 at 12:13
add a comment
|
$ ulimit -a | grep pipe
pipe size (512 bytes, -p) 8
So on my Linux box I have 8*512 = 4096 byte pipes by default.
Solaris and many other systems have a similar ulimit function.
2
This prints(512 bytes, -p) 8
on Fedora 23/25 and512 bytes, -p) 10
on Solaris 10 - and those values don't match the buffer sizes experimentally derived with a blockingdd
.
– maxschlepzig
Jan 1 '17 at 12:13
add a comment
|
$ ulimit -a | grep pipe
pipe size (512 bytes, -p) 8
So on my Linux box I have 8*512 = 4096 byte pipes by default.
Solaris and many other systems have a similar ulimit function.
$ ulimit -a | grep pipe
pipe size (512 bytes, -p) 8
So on my Linux box I have 8*512 = 4096 byte pipes by default.
Solaris and many other systems have a similar ulimit function.
answered Dec 16 '16 at 11:58
Sam WatkinsSam Watkins
1056 bronze badges
1056 bronze badges
2
This prints(512 bytes, -p) 8
on Fedora 23/25 and512 bytes, -p) 10
on Solaris 10 - and those values don't match the buffer sizes experimentally derived with a blockingdd
.
– maxschlepzig
Jan 1 '17 at 12:13
add a comment
|
2
This prints(512 bytes, -p) 8
on Fedora 23/25 and512 bytes, -p) 10
on Solaris 10 - and those values don't match the buffer sizes experimentally derived with a blockingdd
.
– maxschlepzig
Jan 1 '17 at 12:13
2
2
This prints
(512 bytes, -p) 8
on Fedora 23/25 and 512 bytes, -p) 10
on Solaris 10 - and those values don't match the buffer sizes experimentally derived with a blocking dd
.– maxschlepzig
Jan 1 '17 at 12:13
This prints
(512 bytes, -p) 8
on Fedora 23/25 and 512 bytes, -p) 10
on Solaris 10 - and those values don't match the buffer sizes experimentally derived with a blocking dd
.– maxschlepzig
Jan 1 '17 at 12:13
add a comment
|
If you need the value in Python>=3.3, here's a simple method (assuming you can run call out to dd
):
from subprocess import Popen, PIPE, TimeoutExpired
p = Popen(["dd", "if=/dev/zero", "bs=1"], stdin=PIPE, stdout=PIPE)
try:
p.wait(timeout=1)
except TimeoutExpired:
p.kill()
print(len(p.stdout.read()))
add a comment
|
If you need the value in Python>=3.3, here's a simple method (assuming you can run call out to dd
):
from subprocess import Popen, PIPE, TimeoutExpired
p = Popen(["dd", "if=/dev/zero", "bs=1"], stdin=PIPE, stdout=PIPE)
try:
p.wait(timeout=1)
except TimeoutExpired:
p.kill()
print(len(p.stdout.read()))
add a comment
|
If you need the value in Python>=3.3, here's a simple method (assuming you can run call out to dd
):
from subprocess import Popen, PIPE, TimeoutExpired
p = Popen(["dd", "if=/dev/zero", "bs=1"], stdin=PIPE, stdout=PIPE)
try:
p.wait(timeout=1)
except TimeoutExpired:
p.kill()
print(len(p.stdout.read()))
If you need the value in Python>=3.3, here's a simple method (assuming you can run call out to dd
):
from subprocess import Popen, PIPE, TimeoutExpired
p = Popen(["dd", "if=/dev/zero", "bs=1"], stdin=PIPE, stdout=PIPE)
try:
p.wait(timeout=1)
except TimeoutExpired:
p.kill()
print(len(p.stdout.read()))
answered Mar 22 '17 at 13:52
unhammerunhammer
16211 bronze badges
16211 bronze badges
add a comment
|
add a comment
|
Then you can read the stream file to live stream the output from subprocess command.
stream_file = "stream.log"
sys.stdout = open(stream_file, 'w+')
process = subprocess.Popen(shlex.split(command), stdout=sys.stdout, stderr=sys.stdout)
process.communicate()
New contributor
add a comment
|
Then you can read the stream file to live stream the output from subprocess command.
stream_file = "stream.log"
sys.stdout = open(stream_file, 'w+')
process = subprocess.Popen(shlex.split(command), stdout=sys.stdout, stderr=sys.stdout)
process.communicate()
New contributor
add a comment
|
Then you can read the stream file to live stream the output from subprocess command.
stream_file = "stream.log"
sys.stdout = open(stream_file, 'w+')
process = subprocess.Popen(shlex.split(command), stdout=sys.stdout, stderr=sys.stdout)
process.communicate()
New contributor
Then you can read the stream file to live stream the output from subprocess command.
stream_file = "stream.log"
sys.stdout = open(stream_file, 'w+')
process = subprocess.Popen(shlex.split(command), stdout=sys.stdout, stderr=sys.stdout)
process.communicate()
New contributor
New contributor
answered 20 mins ago
Noufal_SNoufal_S
11 bronze badge
11 bronze badge
New contributor
New contributor
add a comment
|
add a comment
|
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f11946%2fhow-big-is-the-pipe-buffer%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown