News for hackers. Stuff that matters.
Re:Zig: programming language designed for robustness optimal... by tom_mellior on Wednesday May 30, 2018 @05:43AM (#17186350)
> And as the SHA-256 demo tests in the talk show, Zig is as fast or faster than C.

Do you know at what timestamp (roughly) this is mentioned in the video? YouTube makes it hard to quickly skip around in the video to find this. Or, better, a link to a written source? I'd be interested in what exactly is being compared. It's easy to cheat on benchmarks, especially when you aren't doing it on purpose.

Re:Zig: programming language designed for robustness optimal... by espeed on Wednesday May 30, 2018 @07:10AM (#17186687)
Right at about the 20m mark: https://youtu.be/Z4oYSByyRak?t=20m2s
Re:Zig: programming language designed for robustness optimal... by tom_mellior on Wednesday May 30, 2018 @08:32AM (#17187140)
Thanks!

Grabbing the sources from https://www.nayuki.io/page/fast-sha2-hashes-in-x86-assembly and compiling them more or less as recommended (and unlike they are compiled in the talk):

    $ clang -O3 sha256-test.c sha256.c -o sha256-test ; for i in 1 2 3; do ./sha256-test ; done
    Self-check passed
    Speed: 197.2 MB/s
    Self-check passed
    Speed: 196.1 MB/s
    Self-check passed
    Speed: 196.1 MB/s
    $ gcc -O3 sha256-test.c sha256.c -o sha256-test ; for i in 1 2 3; do ./sha256-test ; done
    Self-check passed
    Speed: 209.7 MB/s
    Self-check passed
    Speed: 209.2 MB/s
    Self-check passed
    Speed: 209.1 MB/s
This is a baseline for us. It has nothing to do with Zig and nothing to do with Andrew's machine (hardware or compiler versions).

But wait, the page above suggests that adding -march=native might help. Indeed it does:

    $ clang -O3 -march=native sha256-test.c sha256.c -o sha256-test ; for i in 1 2 3; do ./sha256-test ; done
    Self-check passed
    Speed: 255.6 MB/s
    Self-check passed
    Speed: 259.0 MB/s
    Self-check passed
    Speed: 254.3 MB/s
    $ gcc -O3 -march=native sha256-test.c sha256.c -o sha256-test ; for i in 1 2 3; do ./sha256-test ; done
    Self-check passed
    Speed: 275.1 MB/s
    Self-check passed
    Speed: 268.4 MB/s
    Self-check passed
    Speed: 270.0 MB/s
In the talk Andrew suggests that the difference might be due to using rorx instructions, which Zig might be able to do due to aggressive loop unrolling. Does -funroll-all-loops help GCC? It turns out that it doesn't, and that it cannot, on this program, because the C code for sha256_compress is already fully unrolled.

But anyway, are we using rorx instructions at all? We are, but only with -march=native:

    $ clang -O3 -S sha256.c -o - | grep -c rorx
    0
    $ clang -O3 -march=native -S sha256.c -o - | grep -c rorx
    542
And:

    $ gcc -O3 -S sha256.c -o - | grep -c rorx
    0
    $ gcc -O3 -march=native -S sha256.c -o - | grep -c rorx
    576
[Edit: Changed the grep from "ror" to "rorx", which changed GCC's numbers a bit; it does generate "ror" without x without -march=native.]

So. Testable theories:

(a) On Andrew's machine, the same setup but with Clang using -march=native would outperform or at least match Zig.

(b) Zig's compiler internally uses the equivalent of -march=native, possibly implicitly, at least in --release-fast mode.

Nothing here is meant to imply that Andrew is dishonest. There are just lots of variables to take into account, and sometimes we don't. Also, "slower/faster than C" by a few percent is not very meaningful if even C compilers disagree by 6% or so, and the same C compiler with the right flags disagrees with itself by a lot more.