Live data from Hacker News

Nimrod: A new approach to metaprogramming

nimrod-lang.org

41–50 of 58 posts

Re: Nimrod: A new approach to metaprogramming

#42
post #9
post #8

Some very interesting features of Nimrod which I would like to emphasize: - clean Pythonic syntax (whitespace relevant but tabs are forbidden) - native Perl syntax for regular expressions (slide 42) - subrange types as in Ada - set types as in Pascal - strings as case (switch) selectors - easy C interface with automatic type conversion (only functions as parameters need additional compiler pragmas) - typed macros (te…

For embedded use it's probably ok, anywhere C is ok. It statically links the bits of the stdlib you use but dead code elimination seems to work pretty well. A simple word counting script I just wrote compiles down to about 52k on 64bit OS X. (Src: https://gist.github.com/tylereaves/7711302 )

I also wonder about Nimrod on embedded. The dealbreaker is dynamic memory allocation; if Nimrod does that as a non-negotiable part of its runtime, it can't be used.

Re: Nimrod: A new approach to metaprogramming

#43
It has a lot of cool stuff, and I'm intrigued by its approach to threading. (Per-thread heaps and message passing, with an unsafe shared heap if you need it.)

How does dynamic typing work in Nimrod, if it has it? What's the equivalent of being able to call Write() on any io.Writer in Go, for example? [Edit: just found the explanation at http://nimrod-lang.org/tut2.html#dynamic-dispatch but have not yet read and digested.]

I'd love to see some open-source projects that've been written in it--the Nimrod tools and stdlib are obviously a good start. I think one of the things that really helped Go was having lots of n00b-friendly content (the tour, a short "spec", Effective Go doc, blog posts, talks); you could call it "marketing", but it really helped me, at least.

Re: Nimrod: A new approach to metaprogramming

#44

Earlier quoted context omitted.

But you lose the promptness of deallocation. Furthermore, I think the biggest overhead of reference counting is not the count manipulation (especially if you aren't making it thread safe), it's the inability to handle cycles, which DRC does not address.

You are correct that you won't get the immediacy of reference counting; that's a problem of all memory schemes that aren't naive reference counting. But no, the biggest constant time overhead for naive reference counting comes from the RC updates for literally any pointer manipulation. Not just the overhead of having increments, decrements, and possibly failed branch predictions for every single pointer assignment, b…

Pause time is a form of overhead. It reduces both latency and throughput.

Furthermore, the RC updates needed for DRC have to be thread-safe in a concurrent scenario. I understand that Nimrod has chosen not to have a thread-safe GC, but I don't think that'll scale for systems programming: too many algorithms want shared memory, and manual memory management is much more difficult in a concurrent setting. Once you go thread-safe, RC updates become extremely expensive, while concurrent GC is well-studied and performant.

Re: Nimrod: A new approach to metaprogramming

#45

Earlier quoted context omitted.

Wait, if the RC scheme has a cycle collector, how do you ensure there are no CC pauses for acyclic data? Every CC algorithm I know of uses heuristics to determine when to scan the heap for cycles (usually when an RC drops from >2 to 1) and those can result in pauses proportional to the size of the live set on the heap, even when there are no cycles.

I am not sufficiently familiar with the inner details of Nimrod's GC implementation to give you a full answer, but, no, you don't have to scan the entire live heap to reclaim cycles. The technique is called "trial deletion" and only has to traverse potential cycles. Strictly speaking, a type-agnostic implementation may have to traverse all objects reachable from an object whose reference count was decremented since t…

It's still proportional to the live set in the general case. In practice cycle collectors tend to have to scan a lot, leading to some severe pause times (30ms in Firefox used to be common until the ad-hoc ForgetSkippable was added). Heuristics that cycle collectors use tend to fall down a lot in practice, unfortunately.

Re: Nimrod: A new approach to metaprogramming

#47

Earlier quoted context omitted.

You are correct that you won't get the immediacy of reference counting; that's a problem of all memory schemes that aren't naive reference counting. But no, the biggest constant time overhead for naive reference counting comes from the RC updates for literally any pointer manipulation. Not just the overhead of having increments, decrements, and possibly failed branch predictions for every single pointer assignment, b…

Pause time is a form of overhead. It reduces both latency and throughput. Furthermore, the RC updates needed for DRC have to be thread-safe in a concurrent scenario. I understand that Nimrod has chosen not to have a thread-safe GC, but I don't think that'll scale for systems programming: too many algorithms want shared memory, and manual memory management is much more difficult in a concurrent setting. Once you go th…

Once you go thread-safe, RC updates become extremely expensive, while concurrent GC is well-studied and performant.

This is simply false. In fact, concurrent versions of deferred reference counting have been known and studied for years [1]. The simple solution is to store the RC updates in a buffer and execute them only during a collection phase.

Pause time is a form of overhead. It reduces both latency and throughput.

Yes, but for many applications (e.g., HPC) only amortized cost is relevant.

Note also that you can do cycle detection concurrently with the mutator's operation (again, see [1]). Concurrent cycle detection makes the implementation more complicated, but no more so than a concurrent tracing scheme. Moreover, if your program is indeed performance-critical, RC schemes allow you to minimize the impact on cycle detection by designing your code so as to avoid cycles (either by using acyclic data structures exclusively or by using weak pointers). Conversely, tracing schemes make it difficult to programmatically influence worst case pause time.

[1] E.g., http://researcher.watson.ibm.com/researcher/files/us-bacon/B...

Re: Nimrod: A new approach to metaprogramming

#48

Earlier quoted context omitted.

Pause time is a form of overhead. It reduces both latency and throughput. Furthermore, the RC updates needed for DRC have to be thread-safe in a concurrent scenario. I understand that Nimrod has chosen not to have a thread-safe GC, but I don't think that'll scale for systems programming: too many algorithms want shared memory, and manual memory management is much more difficult in a concurrent setting. Once you go th…

Once you go thread-safe, RC updates become extremely expensive, while concurrent GC is well-studied and performant. This is simply false. In fact, concurrent versions of deferred reference counting have been known and studied for years [1]. The simple solution is to store the RC updates in a buffer and execute them only during a collection phase. Pause time is a form of overhead. It reduces both latency and throughpu…

> Note also that you can do cycle detection concurrently with the mutator's operation (again, see [1]). Concurrent cycle detection makes the implementation more complicated, but no more so than a concurrent tracing scheme.

I disagree—it's much more complicated. Concurrent GC is not trivial, but it doesn't have seven different colors and two different tests (sigma and delta test).

A good concurrent reference counting system is just as complex as a good tracing garbage collector, because it requires the same runtime machinery—precise stack maps, write barriers, etc., to perform backup tracing. But it also has the reference counts to deal with. It ends up being more complex overall.

> Moreover, if your program is indeed performance-critical, RC schemes allow you to minimize the impact on cycle detection by designing your code so as to avoid cycles (either by using acyclic data structures exclusively or by using weak pointers).

No, that's my point—even if you use acyclic data structures, there is no guarantee that you won't have the CC run because you had multiple references to an object and you dropped one, making the cycle collector suspect it was part of a cycle. This is the entire reason why ForgetSkippable was added to Firefox: this happened a lot in practice. The solution was to add a bunch of ad-hoc code to make the cycle collector drop objects from the purple buffer, much like the "acyclic" pragma does in Nimrod—but now you have the possibility of leaks unless this is done very carefully.

> Conversely, tracing schemes make it difficult to programmatically influence worst case pause time.

In collectors like Metronome, it's extremely easy: set the pause time to what you want it to be. That's the only solution that's really scalable in my view: working around the collector by manually telling the CC not to scan certain types feels too error-prone.

Re: Nimrod: A new approach to metaprogramming

#49
post #8

Some very interesting features of Nimrod which I would like to emphasize: - clean Pythonic syntax (whitespace relevant but tabs are forbidden) - native Perl syntax for regular expressions (slide 42) - subrange types as in Ada - set types as in Pascal - strings as case (switch) selectors - easy C interface with automatic type conversion (only functions as parameters need additional compiler pragmas) - typed macros (te…

> I am working with Nimrod right now Cool! Is what you're working on public?

Not yet. I am working on a replacement for the Asciidoc/Docbook toolchain which I am not satisfied with. It handles an extended version of Asciidoc and aims to produce code for a few output formats (HTML, TeX).
Post reply on HN