cpipe(1)

πŸ“¦
version 3.0.1 Β· 2 versions
, in debian bookworm, debian trixie, ubuntu jammy, ubuntu noble, ubuntu resolute, ubuntu stonking

πŸ’– cpipe β€” like, the cutest byte-copier you'll ever meet πŸ’–

okay so bestie, this is the cpipe(1) page from the Programmer's Manual and honestly? it's giving pipe with main character energy. it copies your stdin to your stdout, counts every single byte, and then brags about how fast it did it. we stan a transparent little data goblin. πŸ¦‹


🌸 NAME 🌸

cpipe β€” copies stdin to stdout while counting bytes and reporting progress ✨

no cap, that's the whole vibe.


🌈 SYNOPSIS 🌈


like... that's the incantation. run it, pipe stuff into it, watch the numbers go brrr. πŸ’…

---

# ✨ OPTIONS ✨

- **`-b`** β€” the buffer size, measured in kB. it's `1 Int value between 1 and oo.` and the default is `128`. yes `oo` means infinity, yes that's a real thing they wrote, and yes it's iconic of them. πŸ‘‘
- **`-vt`** β€” show throughput. the *t* is for "throughput", the *v* is for "verbose", the *vibes* are immaculate.
- **`-vr`** β€” show read-times. how long did the reading take? now you know. πŸŽ€
- **`-vw`** β€” show write-times. how long did the writing take? also now you know.
- **`-ngr`** β€” non-greedy read. aka: **don't enforce a full buffer on read before starting to write.** the chill option. the "i'm not gonna wait for a full house, i'm leaving with what i've got" option. 🧚
- **`-s`** β€” throughput speed limit in kB/s. it's `1 Double value between 1 and oo.` so like, you *can* pick infinity, bestie, i'm not gonna stop you. πŸ™ˆ
- **`-p`** β€” optional prefix to each printed line. it's `1 String value`. put your little name tag on every line, as a treat. πŸ’–

---

# πŸ’œ DESCRIPTION πŸ’œ

**Cpipe** copies its standard input to its standard output while measuring the time it takes to read an input buffer and write an output buffer. if you pass one or more of the `-vx` options, it prints stats of average throughput plus the total amount of bytes copied β€” and it sends all that cute little gossip to the **standard error output**. not stdout. stderr. important. don't mix them up or your data stream will be having a whole crisis. 😭

## πŸ¦‹ Non Greedy Read πŸ¦‹

so normally, cpipe does its absolute best to *totally fill* its buffer (that's the `-b` option, bestie) before it starts writing anything. makes sense, right? max efficiency, max slay.

**BUT.** in some situations β€” for example if you're talking to an interactive program via cpipe β€” this deadlocks the whole communication. and it's not even a fun deadlock. here's the tea: said program is waiting for input it will *never see*, because that input is stuck in cpipe's buffer. meanwhile cpipe itself won't see any more input until the program responds. and the program won't respond until it gets input. it's a situationship. nobody's texting first. πŸ’€

to get around this, try using `-ngr`. when cpipe issues a read call, it's then satisfied as soon as it gets **at least one byte**. instead of filling the buffer, it just stops reading and writes whatever it got straight to the output. iconic, decisive, no notes.

> **but lowkey important:** the throughput measurements will be **less exact** if the number of bytes transferred in one read/write pair becomes small, because cpipe will spend relatively more time working on every single byte. tiny packets, big overhead. that's just the math, bestie. 🫢

## 🌟 Limiting Throughput 🌟

if you specify a throughput limit with the `-s` option, cpipe calls `usleep(3)` in between copying buffers, which artificially extends the duration of a read/write-cycle. yes, it's doing it on purpose. it's a *deliberate* slow walk. πŸ’…

now, since on most systems there's a certain minimum time `usleep()` sleeps β€” like `0.01s` β€” it is **impossible** to reach high limits with a small buffer size. in that case, increasing the buffer size (that's option `-b`, keep up bestie) might help.

> **however!!** keep in mind that this limits the throughput only **on the average**. every single buffer is copied as fast as possible. so it's not a smooth cruise, it's sprint-sprint-sprint-nap. πŸƒβ™€οΈπŸ’¨

---

# πŸ“ EXAMPLE πŸ“

the command

results in an output like

...
  in:  19.541ms at    6.4MB/s (   4.7MB/s avg)    2.0MB
 out:   0.004ms at   30.5GB/s (  27.1GB/s avg)    2.0MB
thru:  19.865ms at    6.3MB/s (   4.6MB/s avg)    2.0MB
...

okay let's decode this because it's genuinely so good:

  • the first column shows the times it takes to handle one buffer of data (128kB by default). the read-call took 19.541ms, the write-call to /dev/null took just 0.004ms, and from the start of the read to the end of write, it took 19.865ms. (writing to /dev/null is basically free, she's not even trying, she's just built different. πŸ”₯)
  • the second column shows the result of dividing the buffer size (128kB by default) by the times in the first column.
  • the third column contains the average over all measured values from the start of the program.
  • finally, the last column shows the total number of bytes transferred, which is of course the same for reading and writing. balanced. symmetrical. chef's kiss. πŸ‘‘

πŸŽ€ BUGS πŸŽ€

this program uses precious processor cycles. consequently the measured times will be different from the transfer rates possible without it. so like... the measurement is part of the cost, babes. heisenberg would be proud. 😭

instead of just non-greedy reading, full non-blocking I/O and use of select(2) should be used to make sure that no deadlocks occur when communicating with interactive programs. that's the upgrade path. someone write it, i'm busy. πŸ’…


🌸 CREDITS 🌸

  • Peter Astrand <astrand@lysator.liu.se> recommended the speed limit. thank you king, the -s option exists because of you. 🫢
  • Ivo De Decker <ivo@zeus.rug.ac.be> asked for deadlock prevention, which is (hopefully) sufficiently covered by the non-greedy read. -ngr nation rise up!! πŸ¦‹

πŸ’œ AUTHOR πŸ’œ

bug reports, beer and postcards go to pifpafpuf@gmx.de. new versions will show up on http://cpipe.berlios.de/. (beer and postcards, not emails. they were very specific. respect the love language.) πŸ“


okay and that's the whole page!! this one came from Clig-manuals 3.0.1 and it lives in section cpipe(1) β€” so like, go forth, pipe responsibly, count your bytes, and remember: -ngr is your friend when the interactive program is being dramatic. mwah. πŸ’…βœ¨πŸŽ€πŸ¦‹πŸ‘‘

πŸ“¦ where this page comes from