Live data from Hacker News

Zig: programming language designed for robustness optimality and clarity [video]

youtube.com

31–40 of 73 posts

Re: Zig: programming language designed for robustness optimality and clarity [video]

#31
post #20

Earlier quoted context omitted.

I may be wrong, but if I read the documentation correctly, Rust looks more memory-safe than Zig. What am I missing?

Rust has lifetimes and ownership as language concepts so that you have to be explicit about who owns a resource, for example memory, but it does not give you a lot of control about what to do when an allocation fails. Zig is designed so that you can still peogrammatically deal with a failing allocation, as does well-written C, but it does not have a ownership system like Rust.

Ok, got it. Apparently, espeed was using an unusual definition of "memory safety", which made their comment a bit odd :)

Re: Zig: programming language designed for robustness optimality and clarity [video]

#32
post #28
post #26

Earlier quoted context omitted.

> A `union(TagType)` in Zig is a tagged union and has safety checks on all accesses in debug mode. It is directly comparable to a Rust enum. Any differences are probably more down to the ways you are expected to access them and Rust's stronger pattern matching probably helps some here. But if I understand correctly, out-of-the-box, Zig's `union` doesn't get a tag type, right? That's what I meant by Rust's `enum` bein…

> But if I understand correctly, out-of-the-box, Zig's `union` doesn't get a tag type, right? That's what I meant by Rust's `enum` being safer: you can use it safely in Zig, but you have to actually request safety, because that's not the default behavior. Sure. I think that's more an effect of the choice of keyword defaults here. A straight union is very uncommon and is typically solely for C interoperability. > And…

> - `union` is an unchecked sum type, similar to a c union without a tag field.

My understanding was that Zig unions are tagged, but if you don't explicitly specify the tag type the compiler will choose for you. Indeed, the first example in the documentation suggests normal unions are tagged:

  // A union has only 1 active field at a time.
  const Payload = union {
      Int: i64,
      Float: f64,
      Bool: bool,
  };
  test "simple union" {
      var payload = Payload {.Int = 1234};
      // payload.Float = 12.34; // ERROR! field not active
      assert(payload.Int == 1234);
      // You can activate another field by assigning the entire union.
      payload = Payload {.Float = 12.34};
      assert(payload.Float == 12.34);
  }
Or do straight unions only get a hidden tag for debug/safe builds? My memory is a little fuzzy.

Re: Zig: programming language designed for robustness optimality and clarity [video]

#33
post #25

Earlier quoted context omitted.

> 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.

Right at about the 20m mark: https://youtu.be/Z4oYSByyRak?t=20m2s

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.

Re: Zig: programming language designed for robustness optimality and clarity [video]

#34
post #31

Earlier quoted context omitted.

Rust has lifetimes and ownership as language concepts so that you have to be explicit about who owns a resource, for example memory, but it does not give you a lot of control about what to do when an allocation fails. Zig is designed so that you can still peogrammatically deal with a failing allocation, as does well-written C, but it does not have a ownership system like Rust.

Ok, got it. Apparently, espeed was using an unusual definition of "memory safety", which made their comment a bit odd :)

What was unusual about that? Here is Wikipedia: "Memory safety is the state of being protected from various software bugs and security vulnerabilities when dealing with memory access, such as buffer overflows and dangling pointers.[1] For example, Java is said to be memory-safe because its runtime error detection checks array bounds and pointer dereferences."

This is the mainstream definition. Do you think Zig doesn't have this, or Rust has more of this than Zig?

What Rust does indeed have is freedom from race conditions, which can be viewed as a concurrent memory safety property. And what Rust also has is static checking of one of the above properties, namely dangling pointers (but not the other, namely buffer overflows). Do you think that if it's not statically checked, it's not safe? Because if you think that, you are wrong.

Re: Zig: programming language designed for robustness optimality and clarity [video]

#35
post #7

I've been building a toy project in zig in the last couple weeks. Zig is incredible. After only a short while working with it, it feels like deserves the title of a "better C". With no runtime overhead you get: * Type inference - var name = "Bob"; * Maybe types (from Elm/Haskell) that prevent NULL ptr bugs and syntactic sugar encourages its use for function return values. if (doit()) |result| { // result is always a…

Do nullable types and maybe types add much over checked dereferences (a la Java)? I imagine they might be good for performance (fewer checks), but does it really help with correctness/convenience/elegance/readability/etc?

Yes, because you get told about problems at compile-time rather than at runtime.

Re: Zig: programming language designed for robustness optimality and clarity [video]

#36
post #31

Earlier quoted context omitted.

Ok, got it. Apparently, espeed was using an unusual definition of "memory safety", which made their comment a bit odd :)

What was unusual about that? Here is Wikipedia: "Memory safety is the state of being protected from various software bugs and security vulnerabilities when dealing with memory access, such as buffer overflows and dangling pointers.[1] For example, Java is said to be memory-safe because its runtime error detection checks array bounds and pointer dereferences." This is the mainstream definition. Do you think Zig doesn'…

I was referring to espeed's "Zig is similar to Rust, but with memory safety designed into the core, not bolted on as an afterthought", which he later explained with two examples, one of which actually justifies the words "bolted on as an afterthought", but refers to local handling of fallible allocation.

While local handling of fallible allocation is a desirable feature for many applications, I confirm that neither me nor Wikipedia had never heard it classified as "memory safety" :)

Re: Zig: programming language designed for robustness optimality and clarity [video]

#37
post #36

Earlier quoted context omitted.

What was unusual about that? Here is Wikipedia: "Memory safety is the state of being protected from various software bugs and security vulnerabilities when dealing with memory access, such as buffer overflows and dangling pointers.[1] For example, Java is said to be memory-safe because its runtime error detection checks array bounds and pointer dereferences." This is the mainstream definition. Do you think Zig doesn'…

I was referring to espeed's "Zig is similar to Rust, but with memory safety designed into the core, not bolted on as an afterthought", which he later explained with two examples, one of which actually justifies the words "bolted on as an afterthought", but refers to local handling of fallible allocation. While local handling of fallible allocation is a desirable feature for many applications, I confirm that neither m…

I agree that that aspect isn't relevant to what I would call memory safe. But how do you get from "espeed claimed something unreasonable" to "Rust looks more memory-safe than Zig"?

Re: Zig: programming language designed for robustness optimality and clarity [video]

#39
post #36

Earlier quoted context omitted.

What was unusual about that? Here is Wikipedia: "Memory safety is the state of being protected from various software bugs and security vulnerabilities when dealing with memory access, such as buffer overflows and dangling pointers.[1] For example, Java is said to be memory-safe because its runtime error detection checks array bounds and pointer dereferences." This is the mainstream definition. Do you think Zig doesn'…

I was referring to espeed's "Zig is similar to Rust, but with memory safety designed into the core, not bolted on as an afterthought", which he later explained with two examples, one of which actually justifies the words "bolted on as an afterthought", but refers to local handling of fallible allocation. While local handling of fallible allocation is a desirable feature for many applications, I confirm that neither m…

> I agree that that aspect isn't relevant to what I would call memory safe. But how do you get from "espeed claimed something unreasonable" to "Rust looks more memory-safe than Zig"?

Well, there are several reasons. For instance:

- Rust tries very hard to prevent accidental mutations through aliases. In all the common cases and most of the uncommon ones, it works quite well.

- Rust ensures that your memory can't be deallocated twice and that you can't dereference a dangling pointer.

- Rust ensures that any object that needs to be accessed from several threads is either read-only or somehow protected.

- Rust ensures that a context may not deallocate an object it does not own, nor mistakenly believe that it still has ownership of an object after it has transmitted this ownership to another context.

At this (early) stage in the development of Zig, I have the impression that these aspects of memory safety do not exist in Zig, hence my comment.

Now, I realize that Zig has at least one memory-safety check that `unsafe` Rust does not have, so it is entirely possible that both languages concentrate on different aspects of memory safety and/or different implementation techniques.

I also believe that Zig is interesting and has lots of potential. But I suspect that Zig needs to grow a little before anyone can claim that Zig is more memory-safe than Rust (which is what I understand from the comment I was answering).

Re: Zig: programming language designed for robustness optimality and clarity [video]

#40
Every time there is news about a language, the first thing I am interested in is reading the syntax, I don't really care about anything else.

Unfortunately it's often hard to find code examples.

Zig doesn't fail that rule, I browsed 3 or 4 pages or so on the website, and could not find decent code examples.

It's frustrating. You should be proud of the syntax choices you're making and it should be the first thing you see so that developer might get a little interested, look at rust and go and nim.

Post reply on HN