News for hackers. Stuff that matters.
Re:How safe is Zig? by verdagon on Thursday June 23, 2022 @12:59PM (#31851951)
A lot of embedded devices and safety critical software sometimes don't even use a heap, and instead use pre-allocated chunks of memory whose size is calculated beforehand. It's memory safe, and has much more deterministic execution time.

This is also a popular approach in games, especially ones with entity-component-system architectures.

I'm excited about Zig for these use cases especially, it can be a much easier approach with much less complexity than using a borrow checker.

Re:How safe is Zig? by jorangreef on Thursday June 23, 2022 @01:39PM (#31852575)
This is almost what we do for TigerBeetle, a new distributed database being written in Zig. All memory is statically allocated at startup [1]. Thereafter, there are zero calls to malloc() or free(). We run a single-threaded control plane for a simple concurrency model, and because we use io_uring—multithreaded I/O is less of a necessary evil than it used to be.

I find that the design is more memory efficient because of these constraints, for example, our new storage engine can address 100 TiB of storage using only 1 GiB of RAM. Latency is predictable and gloriously smooth, and the system overall is much simpler and fun to program.

[1] “Let's Remix Distributed Database Design” https://www.youtube.com/channel/UC3TlyQ3h6lC_jSWust2leGg

Re:How safe is Zig? by infamouscow on Thursday June 23, 2022 @06:13PM (#31855757)
> Latency is predictable and gloriously smooth, and the system overall is much simpler and fun to program.

This has also been my experience building a database in Zig. It's such a joy.

Re:How safe is Zig? by catlifeonmars on Friday June 24, 2022 @09:57AM (#31861873)
> for example, our new storage engine can address 100 TiB of storage using only 1 GiB of RAM.

I’m a little confused by this statement. I assume by “address” you mean indexing, and the size of an index is related to the number of entries, not the amount of data being indexed. (For example, you could trivially address 100TiB using 1 address width of memory if all 100TiB belongs to the same key).

Re:How safe is Zig? by jorangreef on Friday June 24, 2022 @11:01AM (#31863209)
> I’m a little confused by this statement. I assume by “address” you mean indexing, and the size of an index is related to the number of entries, not the amount of data being indexed.

Thanks for the question!

What's in view here is an LSM-tree database storage engine. In general, these typically store keys between 8 and 32 bytes and values up to a few MiB.

In our case, the question is how much memory is required for the LSM-tree to be able to index 100 TiB worth of key/value storage, where:

  * keys are between 8 and 32 bytes,
  * values are between 8 and 128 bytes,
  * keys and values are stored in tables up to 64 MiB,
  * each table requires between 128 and 256 bytes of metadata to be kept in memory,
  * auxiliary data structures such as a mutable/immutable table must be kept in memory, and where
  * all memory required by the engine must be statically allocated.
That's alot of small keys and values!

Typically, a storage system might require at least an order of magnitude more than 1 GiB of memory to keep track of that many keys using an LSM-tree as index, even using dynamic allocation, which only needs to allocate as needed.

Another way to think of this is as a filesystem, since it's a very similar problem. Imagine you stored 100 TiB worth of 4096 byte files in ZFS. How much RAM would that require for ZFS to be able to keep track of everything?

Re:How safe is Zig? by catlifeonmars on Thursday June 30, 2022 @02:21PM (#31936418)
Thanks for taking the time to reply in detail! The metric makes much more sense when put into context.
Re:How safe is Zig? by jorangreef on Sunday July 03, 2022 @11:21AM (#31968370)
It's a pleasure. Let me know if you have any more questions about TigerBeetle. Our design doc is also here: https://github.com/coilhq/tigerbeetle/blob/main/docs/DESIGN....
Re:How safe is Zig? by pcwalton on Thursday June 23, 2022 @02:44PM (#31853473)
Even in this environment, you can still have dangling pointers to freed stack frames. There's no way around having a proper lifetime system, or a GC, if you want memory safety.
Re:How safe is Zig? by verdagon on Thursday June 23, 2022 @03:23PM (#31854020)
Yep, or generational references [0] which also protect against that kind of thing ;)

The array-centric approach is indeed more applicable at the high levels of the program.

Sometimes I wonder if a language could use an array-centric approach at the high levels, and then an arena-based approach for all temporary memory. Elucent experimented with something like this for Basil once [1] which was fascinating.

[0] https://verdagon.dev/blog/generational-references

[1] https://degaz.io/blog/632020/post.html

Re:How safe is Zig? by com2kid on Thursday June 23, 2022 @03:49PM (#31854292)
> Yep, or generational references [0] which also protect against that kind of thing ;)

First off, thank you for posting all your great articles on Vale!

Second off, I just read the generational references blog post for the 3rd time and now it makes complete sense, like stupid obvious why did I have problems understanding this before sense. (PS: The link to the benchmarks is dead :( )

I hope some of the novel ideas in Vale make it out to the programming language world at large!

Re:How safe is Zig? by verdagon on Thursday June 23, 2022 @04:14PM (#31854581)
Thank you! I just fixed the link, thanks for letting me know! And if any of my articles are ever confusing, feel welcome to swing by the discord or file an issue =)

I'm pretty excited about all the memory safety advances languages have made in the last few years. Zig is doing some really interesting things (see Andrew's thread above), D's new static analysis for zero-cost memory safety hit the front page yesterday, we're currently prototyping Vale's region borrow checker, and it feels like the space is really exploding. Good time to be alive!

Re:How safe is Zig? by yw3410 on Thursday June 23, 2022 @08:41PM (#31856722)
It feels like it would work really well (you could even swap between arenas per frame). I've been wanting to try something similar but it's early days.
Re:How safe is Zig? by im3w1l on Thursday June 23, 2022 @04:18PM (#31854641)
Well if get rid of not just the heap, but the stack too... turn all variables into global ones, then it will be safe.

This means we lose thread safety and functions become non-reentrant (but easy to prove safe - make sure graph of A-calls-B is a acyclical).

Re:How safe is Zig? by infamouscow on Thursday June 23, 2022 @06:28PM (#31855874)
> Even in this environment, you can still have dangling pointers to freed stack frames.

How frequently does this happen in real software? I learned not to return pointers to stack allocated variables when I was 12 years old.

> There's no way around having a proper lifetime system, or a GC, if you want memory safety.

If you're building an HTTP caching program where you know the expiration times of objects, a Rust-style borrow-checker or garbage collector is not helping anyone.

Re:How safe is Zig? by seoaeu on Thursday June 23, 2022 @10:31PM (#31857216)
> > Even in this environment, you can still have dangling pointers to freed stack frames.

> How frequently does this happen in real software? I learned not to return pointers to stack allocated variables when I was 12 years old.

This happens rarely. However, the reason it isn't an issue is because C programmers are (and have to be) extremely paranoid about this kind of thing.

Rust, however, lets you recklessly pass around pointers to local variables while guaranteeing that you won't accidentally use one as a return value. One example is scoped thread pools which let you spawn a bunch of worker threads and then pass them pointers to stack allocated variables that get concurrently accessed by all the threads. The Rust type system/borrow checker ensures both thread safety and memory safety.

Would you trust a novice C programmer to use something like that?

Re:How safe is Zig? by Arnavion on Thursday June 23, 2022 @06:39PM (#31855966)
>I learned not to return pointers to stack allocated variables when I was 12 years old.

So, if you slip while walking today, does that mean you didn't learn to walk when you were one year old?

Re:How safe is Zig? by infamouscow on Thursday June 23, 2022 @09:24PM (#31856941)
Your analogy doesn't answer the question. How frequently does this happens in real software?
Re:How safe is Zig? by brundolf on Thursday June 23, 2022 @01:19PM (#31852261)
Rust's borrow checker would be much calmer in these scenarios too, wouldn't it? If there are no lifetimes, there are no lifetime errors
Re:How safe is Zig? by thecatster on Thursday June 23, 2022 @01:40PM (#31852590)
Rust is definitely different (and calmer imho) on bare metal. That said (as much of a Rust fanboy I am), I also enjoy Zig.
Re:How safe is Zig? by the__alchemist on Thursday June 23, 2022 @05:36PM (#31855451)
Yep! We've entered a grey areas, where some Rust embedded libs are expanding the definitions of memory safety, and what the borrow checker should evaluate beyond what you might guess. Eg, structs that represent peripherals, that are now checked for ownership; the intent being to prevent race conditions. And Traits being used to enforce pin configuration.
Re:How safe is Zig? by snicker7 on Thursday June 23, 2022 @01:42PM (#31852612)
How exactly is pre-allocation safer? If you would ever like to re-use chunks of memory, then wouldn’t you still encounter “use-after-free” bugs?
Re:How safe is Zig? by verdagon on Thursday June 23, 2022 @01:54PM (#31852777)
The approach can reuse old elements for new instances of the same type, so to speak. Since the types are the same, any use-after-free becomes a plain ol' logic error. We use this approach in Rust a lot, with Vecs.
Re:How safe is Zig? by olig15 on Thursday June 23, 2022 @02:34PM (#31853345)
But if you have a structure that contains offsets into another buffer somewhere, or an index, whatever - the wrong value here could be just as bad as a use-after-free. I don’t see how this is any safer. If you use memory after free from a malloc, with any chance you’ll hit a page fault, and your app will crash. If you have a index/pointer to another structure, you could still end up reading past the end of that structure into the unknown.
Re:How safe is Zig? by verdagon on Thursday June 23, 2022 @02:47PM (#31853528)
That's just a logic error, and not memory unsafety which might risk UB or vulnerabilities. The type system enforces that if we use-after-"free" (remember, we're not free'ing or malloc'ing), we just get a different instance of the same type, which is memory-safe.

You do bring up a valid broader concern. Ironically, this is a reason that GC'd systems can sometimes be better for privacy than Ada or Rust which uses a lot more Vec+indexes. An index into a Vec<UserAccount> is riskier than a Java List<UserAccount>; a Java reference can never suddenly point to another user account like an index could.

But that aside, we're talking about memory safety, array-centric approaches in Zig and Rust can be appropriate for a lot of use cases.

Re:How safe is Zig? by veber-alex on Thursday June 23, 2022 @08:45PM (#31856749)
If you are holding indexes to a collection and plan to delete elements you will never use Vec.

There are dedicated data structures for this [1] that will not let you access another item by mistake.

[1] https://crates.io/crates/slotmap

Re:How safe is Zig? by verdagon on Thursday June 23, 2022 @09:08PM (#31856860)
You should never use Vec in that situation, but we see it all the time. People love indexing into Vecs and reusing elements.

One of my favorite alternatives is generational_arena [0] which also happens to be the library that inspired Vale's generational references!

[0] https://docs.rs/generational-arena/latest/generational_arena...

Re:How safe is Zig? by pjmlp on Thursday June 23, 2022 @02:56PM (#31853621)
In high integrity computing that is pretty much safety related, if that logic error causes someone to die due to corrupt data, like using the wrong radiation value.
Re:How safe is Zig? by tialaramex on Thursday June 23, 2022 @06:41PM (#31855987)
But, Java has exactly the same behaviour, the typical List in Java is ArrayList which sure enough has an indexed get() method.

There seems to be no practical difference here. Rust can do a reference to UserAccount, and Java can do an index into an ArrayList of UserAccounts. Or vice versa. As you wish.

Re:How safe is Zig? by verdagon on Thursday June 23, 2022 @07:24PM (#31856321)
In Java, you can hold onto a reference to the UserAccount directly, for as long as you want.

The borrow checker, however, forces you to hold onto an index instead.

Re:How safe is Zig? by anonymoushn on Thursday June 23, 2022 @07:55PM (#31856501)
Right, it sounds like you are circumventing the borrow checker and then experiencing some of the classes of bugs it was supposed to prevent. And this seems common: https://www.youtube.com/watch?v=4t1K66dMhWk
Re:How safe is Zig? by verdagon on Thursday June 23, 2022 @09:13PM (#31856878)
> Circumventing the borrow checker

Programs often require inherent state with data that refers to other data. In these cases, one must circumvent the borrow checker, whether it be with indices, IDs, Rc, or whatever. The borrow checker simply does not allow changing data when someone has a reference to it (except for the rare case where we can use Cell).

It's a myth that we can rewrite any program to not circumvent the borrow checker.

Re:How safe is Zig? by kaba0 on Thursday June 23, 2022 @03:20PM (#31853975)
These are 1000 times worse than even a segfault. These are the bugs you won’t notice until they crop up at a wildly different place, and you will have a very hard time tracking it back to their origin (slightly easier in Rust, as you only have to revalidate the unsafe parts, but it will still suck)
Re:How safe is Zig? by bsder on Thursday June 23, 2022 @04:56PM (#31855048)
Normally you do this on embedded so that you know exactly what your memory consumption is. You never have to worry about Out of Memory and you never have to worry about Use After Free since there is no free. That memory is yours for eternity and what you do with it is up to you.

It doesn't, however, prevent you from accidentally scribbling over your own memory (buffer overflow, for example) or from scribbling over someone else's memory.

Re:How safe is Zig? by nine_k on Thursday June 23, 2022 @02:01PM (#31852872)
No; every chunk is for single, pre-determined use.

Imagine all variables in your program declared as static. This includes all buffers (with indexes instead of pointers), all nested structures, etc.