5 ms·
The second one (written by me) is actually JIT-compiled assembly. So little of the runtime is spent in the C code that -O0 vs -O3 makes no difference at all; an
by bonzini 5y ago
The second one (written by me) is actually JIT-compiled assembly. So little of the runtime is spent in the C code that -O0 vs -O3 makes no difference at all; and even if you wrote the glue code in Python it would not be much slower than the C code.
Also the third entry is not the one in Rust. It's just that the Rust entry came later and thus was not included in the plot. The third entry is https://codegolf.stackexchange.com/a/215236/56694 https://codegolf.stackexchange.com/a/215236/56694; it is also C.
> displace the C implementation in Rust or any other language besides C/C++/ASM
This is not a language contest, it's an algorithmic contest: that is, it's the best algorithm that wins, not the best compiler. The top entry, converted into C or Rust by mostly menial work, would probably be only a few % slower and would displace the C implementation.
- stavros 5y agoNow I'm kind of hoping that someone will rewrite the glue in Python so that Python is the second fastest implementation of them all, just for the laughs.
- sillysaurusx 5y agoI would love to see a Python implementation that approaches the C code. It would be educational on so many levels. Would anyone be interested in trying? Also, why is the ASM version so much faster if the glue code doesn't make much difference? I suppose it matters at the margins...
- bonzini 5y ago> why is the ASM version so much faster if the glue code doesn't make much difference The remark on the glue code only applies to my entry (the second). The assembly entry uses a completely different (and much more complicated) algorithm than the C entry.
- hectormalot 5y agoIf you read the description you’ll see that it’s optimizing around certain syscalls like memcopy (which is otherwise limiting and reduces speed by 5x). I think it’s less language choice, and more low level optimization that is making a difference here. (To check, I wrote a Go program that doen nothing else than fmt.Print($largebody) in a for loop and it tops out at around 10GB/s)
- tux3 5y agoNote that memcpy is not a syscall. Common syscalls do copies. The fast implementation uses the vmsplice syscall as a clever way to pump a pipe with data, because it doesn't copy.
- tialaramex 5y agoIndeed. Today for most systems memcpy is in fact a compiler intrinsic. C's standard library offers a memcpy but the reality is that your C standard library was likely supplied by your C compiler vendor, and when you ask for memcmp() in C you get their preferred intrinsic inlined into your program unless you've been very firm in declining that optimisation. In Rust this memcpy intrinsic is required (for the core language, not just the standard library) because Rust clearly has arbitrarily large data structures you can literally copy, so, somebody has to take responsibility for doing that work, Rust says it's the compiler back-end's job. On a toy CPU the memcpy might really just be a trivial read->register->write loop because that's adequate.
- tialaramex 5y agoOops, I notice hours too late to edit it, that this says memcmp() in one place where it mostly says memcpy(). In fact your C compiler likely has intrinsics for both, but I did mean memcpy() everywhere in the comment.
- Qem 5y agoThe Python implementation posted among the answers is about 85 MiB/sec, under PyPy.
- animal531 5y agoSo what we're seeing is that a specialized handcoded assembler version is 10x faster than a generic C version? If so that makes me a bit sad, because in the modern day we'd want to assume that compilers have gotten a little better at optimization.
- jiggawatts 5y agoRead the assembly. Seriously. It's eye-popping. It's eldritch madness. It's black wizardry. The blackest of the black arts. The "fastest FizzBuzz" implementation isn't merely "fast". It's faster than memcpy()!!! Expecting compilers to outperform this tour-de-force is asking a tad too much from compiler writers...
- btilly 5y agoFrom the article, "The application produced 64 bytes of FizzBuzz for every 4 CPU clock cycles. The author states the ultimate bottleneck of performance is based on the throughput of the CPU's L2 cache." For comparison, that time is on par with integer multiplication.
- noduerme 5y agoIt's actually really nice the way the author commented it. It's a cool insight into their mental process. I've never coded in Assembly and I can't normally follow it. But reading these comments I can understand how the author is surgically managing registers and operating off a complete mental map of what's there, the same way a coder would with, say, a very large database they have a complete mental model of. All I mean is that I appreciate the author making their thought process accessible. It certainly looks like virtuosity, but I'm not competent enough to judge.
- bonzini 5y ago> assume that compilers have gotten a little better at optimization Again: you're comparing the performance of different algorithms. A compiler won't turn bubblesort into quicksort.
- 5y ago