Hacker News new | ask | show | jobs
by 3eb7988a1663 386 days ago
That reddit thread has some amazing benchmarks.

The GNU-yes

  $ yes | pv > /dev/null
  ... [10.2GiB/s] ...
The way I (not a C programmer) would have written it

  void main() {
      while(write(1, "y\n", 2)); // 1 is stdout
  }

  $ gcc yes.c -o yes
  $ ./yes | pv > /dev/null
  ... [6.21 MiB/s] ...
5 comments

As a non-system-programmer, here's my attempt in Odin.

  yes | pv > /dev/null
  0:00:15 [1.12GiB/s]
  build/yes | pv > /dev/null
  0:00:20 [1.03GiB/s]


  package main
  
  import "core:sys/linux"
  import "core:os"
  import "core:strings"
  
  main :: proc() {
    msg := "y" if len(os.args) == 1 else os.args[1]
    msg = strings.concatenate({msg, "\n"})
  
    buf := transmute([]u8) strings.repeat(msg, 8192)
    for {
      linux.write(linux.STDOUT_FILENO, buf)
    }
  }
Replace `write(..)` with `puts("y")` and you'll be an order of magnitude faster. This is due to `puts` (`printf` too) being buffered (data isn't written to term/file immediately but retained in memory until some point). Improving this process (as seen in the reddit thread) gets GNU-yes.
It's line buffered when it prints to terminal.
One rarely needs yes' output to be a terminal.
Don't you actively want it to flush asap since you're usually piping into another program?

I suspect what you suggest creates a more voluminous dump but is slower in the desired use case

  yes &
A few times is still my favorite way to push a cpu to max temperature for testing. Used it a lot to detect faulty Core 2 Duo MacBook back in the day. They would short circuit some CPU sensor due to thermal expansion or melting of the wire insulation. Yes was an easy way to get the CPU’s hot enough.
If you compile your variant with -O3 I imagine it will be much faster? Iirc, the default is for GCC is to not optimise
No, it will be about the same. The algorithm is wrong (calling write repeatedly) and -O3 isn't sufficient to rewrite that.
Which implies you get pretty much 3M syscall per second. Which is a good order magnitude to know
I don't believe puts is performing unbuffered I/O though. It's a libc function, not a direct syscall. Correct me if I'm wrong of course
The write(2) libc function is just a C wrapper for the syscall. It's the functions from stdio.h that are buffered.
Ah ok sorry I got confused by the comments nesting level. I thought we were talking about the OpenBSD's version which uses puts