• Log in | Sign up@lemmy.world
    link
    fedilink
    arrow-up
    1
    ·
    1 day ago

    Roc has runtime overhead to do garbage collection, it says so right on their own page.

    I was sceptical about your assertion because the language authors made a design decision not do do garbage collection. So I did a google search for garbage on roc-lang.org to try and find evidence of your claim. It doesn’t say it does garbage collection. It does say overhead, but you’re talking about it like it’s a big slow thing that takes up time and makes thread pauses, but it’s a small thing like array bounds checking. You do believe in array bounds checking, don’t you?

    So no, that’s not what it says and you’re using the phrase garbage collection to mean a much wider class of things than is merited. Garbage collection involves searching the heap for data which has fallen out of scope and freeing that memory up. It’s slow and it necessitates pausing the main thread, causing unpredictably long delays. Roc does not do this.

    Here’s what the website actually says on the topic.

    https://www.roc-lang.org/fast

    Roc is a memory-safe language with automatic memory management. Automatic memory management has some unavoidable runtime overhead, and memory safety based on static analysis rules out certain performance optimizations—which is why unsafe Rust can outperform safe Rust. This gives Roc a lower performance ceiling than languages which support memory unsafety and manual memory management, such as C, C++, Zig, and Rust.

    Just in case you missed it, that was unsafe rust that lacks the overheads. If you’re advocating for using unsafe to gain a tiny performance benefit, you may as well be writing C, or zig, which at least has some tools to cope with all that stuff.

    https://www.roc-lang.org/fast

    When benchmarking compiled Roc programs, the goal is to have them normally outperform the fastest mainstream garbage-collected languages (for example, Go, C#, Java, and JavaScript)

    Just in case you missed it, roc is not in the list of garbage collected languages.

    https://www.roc-lang.org/platforms

    The bigger benefit is tailoring memory management itself based on the domain. For example, nea is a work-in-progress Web server which performs arena allocation on each request handler. In Roc terms, this means the host’s implementation of malloc can allocate into the current handler’s arena, and free can be a no-op. Instead, the arena can be reset when the response has been sent.

    In this design, heap allocations in a Web server running on nea are about as cheap as stack allocations, and deallocations are essentially free. This is much better for the server’s throughput, latency, and predictability than (for example) having to pay for periodic garbage collection!

    Summary: roc doesn’t have the performance disadvantages of garbage collected languages because it’s not a garbage collected language.

    • CanadaPlus@lemmy.sdf.org
      link
      fedilink
      arrow-up
      2
      ·
      edit-2
      1 day ago

      Just in case you missed it, that was unsafe rust that lacks the overheads.

      It says some overheads. It’s different overheads, because Rust does not have reference counting garbage collection, even when safe.

      Either you should go back and read what I said about reference counting being a runtime garbage collecting algorithm, or I think we’re just done. Why say more if it’s ignored anyway?

      I don’t think I’m the zealot here.

      • Log in | Sign up@lemmy.world
        link
        fedilink
        arrow-up
        1
        ·
        24 hours ago

        Well if you’re calling any form of automatic memory management garbage collection, then it’s only C that doesn’t have garbage collection.

        Rust does have explicit reference counting with Rc<T> and Arc<T>.

        I’m trying to explain to you that static analysis that limits references to one can be done in a similar way without the limit of one (especially with the assumption of immutability) whilst retaining in-place mutation where the count really is one. It upsets you when I try to explain that it’s a generalisation of the borrow checker (without the programmer pain) by calling the borrow checker a static (compile time) reference counter with a limit of one. I’m making a comparison. But don’t be surprised if a lot of programming languages implement their boolean variables as an unsigned int with a maximum of one.

        If roc does the equivalent of putting a call to drop where there were two or three references that fell out of scope rather than one, in what sense is that more overhead than rust calling drop when one reference went out of scope? Rust is still “garbage collecting” the references that turned up on the RHS of assignment statements as it goes along.

        The overhead we’re talking about with reference counting is like DEC r BRZ. It’s like array bounds checking. Yes, it’s an overhead, but no, it’s not worth making a big deal about it if you get to allocate arrays of sizes unknown at compile time or you get to make multiple references without messing with keywords and reference symbols, fighting the borrow checker all day long or manually adding clones.

        It says some overheads. It’s different overheads,

        What? Overheads are overheads. Either they’re small and useful like roc’s reference counting when it turns out to need to be at runtime or array bounds checking, or rust calling drop when some variable falls out of scope, or they’re big, stop the main thread at random points and take a long time, like garbage collection in garbage collected languages like java.

        Why say more if it’s ignored anyway?

        I know - I wrote a whole bunch of stuff and this other person just ignored every single nuance and explanation and kept saying the same thing again and again without trying to understand a new thing they didn’t know about before, just repeating their favourite criticisms of other programming languages whether they applied or not. Oh wait, that was you.

        I don’t think I’m the zealot here.

        Interesting.

        • CanadaPlus@lemmy.sdf.org
          link
          fedilink
          arrow-up
          1
          ·
          edit-2
          9 hours ago

          I’ve never actually written anything in Rust, FYI - previous projects have been in C/C++ and Haskell. If you’re looking for someone deeply invested in Rust to argue with it’s not me.

          If you actually are trying to explain desirable features of a new language, and not just tear down an old-ish one, I feel like you’ve gone about it the wrong way.

          Why is reference counting in Roc better than in, for example, Python?

          • Log in | Sign up@lemmy.world
            link
            fedilink
            arrow-up
            1
            ·
            5 hours ago

            Afaik, python does both (regular) garbage collection and reference counting. But that’s not why Python is much slower. Python is much slower because it’s interpreted rather than compiled. Like Java, bytecode is interpreted at runtime. Your jit won’t beat compiled haskell, c or rust in most cases. It’s good because it’s based on real profiling of your actual running code, which not every hand rolled premature optimisation is, but it’s limited. I don’t see the spineless tagless G machine (or whatever the geniuses in Glasgow have come up with these days for ghc’s runtime under the hood), as an interpreter, and haskell compiles the whole thing down to native machine code anyway. Machine code is just faster unless you’ve made some asymptotic error.

            I don’t think rust is old, and I’m not trying to tear it down. I’m saying that you can have in place mutation, free on leaving scope, no garbage collection but yet no linear (affine) type system and hence no cumbersome terminology and notation. You can just write lovely functional code and it’s all compiled very well.

            Roc is like Haskell without the monad transformer stack, just one do-everything monad for each application domain (so no one needs to know what a monad is), partial application but you get to specify which argument is to be filled (not just the final one), and you don’t need to know whether you wanted =#~ or &+~ to change something in your nested data structure. Add super fast compilation (seconds, not minutes, even the first time) and genuinely helpful error messages (you know what I mean if you’ve used elm much).