@araq,

I missed the live stream, but watched the recording on youtube. Thank you for taking the time to do the presentation! Very awesome.

The really hard part is replacing the existing runtime with one with a different performance profile ("yay, deterministic freeing, yay more efficient multi threading possibilities, ugh, overall slower?!")

Can you go into more detail about why the new destructor based string implementation is slower than the current GC string implementation?

More generally, what is the performance profile of the destructor based runtime? Why is it, "overall slower" as you say?

Thank you again, super awesome presentation!

2017-10-21 00:08:56
@Araq I wanted to "show my appreciation" for this new development, but BoutySource doesn't let me leave a comment. I'm "skunkiferous" there; I think "monster" was already taken...
2017-10-21 09:13:06
@rayman22201 what I have seen is, that each proc that has a var of a type which is handled by a destructor needs a hidden try finally block (currently even if the var is not used). This can be a big overhead for small routines. The c target needs setjump/longjump which is a big overhead. The cpp target is better here, because it uses native exception handling.
2017-10-21 11:04:39

More thorough tests are required but theoretically speaking the determinism can cost cycles. Most modern GCs do not emit write barriers for stack slots (this is true for Nim's GC too) but C++ like overloaded assignments/moves do not distinguish between stack slots and heap slots... The different solutions to get memory safety are really not all that different, you need to track the dangerous pointers somehow and most static analysis quickly need to give up. ("Of course things can escape the local scopes, that's why I'm using a heap in the first place.")

The fact that the default allocation strategy changes from "thread local" to "can be shared between threads" does not help either.

2017-10-22 08:29:20

@Araq,

I found your earlier blog posts after reading the newest one. (those should really be more visible btw! they are very interesting!)

Specifically your post on write tracking. It's obviously a really old post (from 2013), and it looks like it was never fully implemented.

What happened with that project?

you need to track the dangerous pointers somehow and most static analysis quickly need to give up.

Would the write tracking help solve any of the problems you mention with the move semantics? I have a vague intuition that write tracking might help take the static analysis further.

The fact that the default allocation strategy changes from "thread local" to "can be shared between threads" does not help either.

It seems like you could detect writes between threads with the write tracking system you described, or possibly a variation of that system. Though that very quickly starts to sound like the Rust borrow checker...

What are your thoughts on this?

2017-10-26 22:20:09

Specifically your post on write tracking. It's obviously a really old post (from 2013), and it looks like it was never fully implemented.

It was implemented and produced impressive results. It makes Nim's effect system even more complex though and doesn't help much with destructors: It only computes "may escape" and not "does always escape" (the analysis is control flow agnostic) and so we're left with pessimistic destructor injections.

2017-10-27 10:51:41

@rayman22201 As far as I know, destructors can be slower in no-single-ownership environments. That's why some languages (e.x. Rust) do the opposite of what Nim is doing now --- they introduce optional GC for cases when it's useful / more natural.

@Araq > Destructors, assignment operators, the move optimization are coming Did I misunderstood you when you once said move optimization already here? I also think regions would still be nice to have as, if I get the idea behind them, they can serve as a memory pool, which is a nice optimization.

I remember you always saying people who want to limit GC usage just don't get it and it'll be fast anyway so why bother. Of course destructors have advantages of their own (like deterministic freeing you mentioned) but if you say Nim's GC is so blazingly fast (I don't doubt it, I just no real experience with GCs) --- why bother about performance? Couldn't destructors just be used where performance doesn't matter as much and you want them for other reasons? I mean, you wrote you'd like to avoid ref "as far as reasonable" --- isn't it turning Nim upside down? You also mentioned slices, which we were talking about once (well, I'm quite shocked you're convinced to this idea in the end). Also, I can see you'd like to utilize Rust-like move instead of C++-like (or so does sink analysis suggest).

By the way: you also mentioned using var more in the blog post. I have to admit I like it very much, var is nice. The same for avoiding returning (although abstracting them away would be better, I guess).

2017-11-04 23:08:49

I remember you always saying people who want to limit GC usage just don't get it and it'll be fast anyway so why bother. Of course destructors have advantages of their own (like deterministic freeing you mentioned) but if you say Nim's GC is so blazingly fast (I don't doubt it, I just no real experience with GCs) --- why bother about performance? Couldn't destructors just be used where performance doesn't matter as much and you want them for other reasons?

We could do that but I eventually want to have a simpler, more consistent language that does not provide every feature under the sun. If I can get a unified solution for resource management that costs 5-10% performance (before I optimized it to use custom allocators etc.) I'm willing to pay the price. Others may not.

2017-11-05 02:06:36
bpr

@Udiknedormin Rust has absolutely no tracing GC at all.

@Araq I'm not understanding, are you saying that destructors and move semantics are the resource management of Nim in the future? If so, what happens to the tracing GC, regions, and all that? If not, I don't know which uniform solution you are proposing.

2017-11-05 02:43:38

I'm not understanding, are you saying that destructors and move semantics are the resource management of Nim in the future? If so, what happens to the tracing GC, regions, and all that? If not, I don't know which uniform solution you are proposing.

Yes, that's what I am saying for the future -- and future here most likely means Nim version 2. How to do regions remains unclear but since assignments are under the programmer's control some overloaded assignment operators can enforce at runtime that no object mixes regions with incompatible lifetimes.

The tracing GC could be replaced with atomic reference counting with a cycle collector. That's of course still a GC but one that plays as nice with deterministic destruction as possible.

2017-11-05 15:56:21