[HN Gopher] How Memory safety approaches speed up and slow down ...
       ___________________________________________________________________
        
       How Memory safety approaches speed up and slow down development
       velocity
        
       Author : signa11
       Score  : 126 points
       Date   : 2023-01-17 08:06 UTC (14 hours ago)
        
 (HTM) web link (verdagon.dev)
 (TXT) w3m dump (verdagon.dev)
        
       | amai wrote:
       | ,,MMM (manual memory management) isn't really advisable for
       | something exposed to the network."
       | 
       | Nowadays basically everything is exposed to the network.
        
       | phkahler wrote:
       | >> As you can see, software development can be much more
       | expensive than power usage, so it makes sense to primarily
       | optimize for development velocity.
       | 
       | No? Those developers can take time off, but the electricity can
       | not. I think he showed how important optimizing software
       | performance is at scale. When you electric bill is $3Billion, you
       | gotta write efficient code, not write more code as fast as
       | possible.
        
         | manholio wrote:
         | That example threw me off too because both the numbers and the
         | perspective are non-nonsensical. 90% of the energy draw of
         | those data-centers goes into things like inner video encoding
         | loops, SSD/memcache storage and retrieval, ML algorithms etc.
         | 
         | But the vast majority of those 27.000 engineers do not work on
         | such low level routines, but on things like millions of lines
         | of crufty Python that power Adsense analytics, which are
         | essential for maintaining a revenue stream. Yes, development
         | speed is very important but it's mostly orthogonal to other
         | operational costs if the right tools and architectures are
         | employed.
        
           | verdagon wrote:
           | Author here, that might actually make the comparison
           | stronger: not all energy in a data center is wasted by the
           | memory safety approach's drawbacks, meaning it makes less
           | sense to optimize for memory safety overhead.
           | 
           | But if I'm being pro-Rust, I would also say that not all
           | coding is affected by a memory safety approach's downsides;
           | there are some domains where the borrow checker doesn't slow
           | development velocity down at all.
           | 
           | Either way, I definitely agree that its orthogonal to many
           | operational costs. I'll mention this line of thought in the
           | article. Thanks!
        
       | jmyeet wrote:
       | So this particular problem is severely time-constrained.
       | Performance doesn't relaly matter. In those situations you tend
       | to use the highest level language you can. This isn't surprising.
       | 
       | The author argues it's similar for startups. I agree to a point.
       | For GC in particular I think the costs are underestimated.
       | Processes blowing up because of memory leaks (which can still
       | happen), dealing with stop-the-world ("STW") pauses and
       | inconsistent performance are all real problems.
       | 
       | So much of this is situational. For example, I think
       | Objective-C/Swift was so successful on iOS (vs Java on Android)
       | in part because it opts for reference counting instead of GC.
       | This is predictable performance and less complicated. But RC
       | isn't necessarily appropriate for a server as you may create hot
       | spots and degrade performance that way.
       | 
       | Rust by virtue of borrow checking isn't a panacea. It does
       | however greatly reduce the chances of making a whole class of
       | really important bugs (ie memory safety and all the entails like
       | buffer overruns). Comparing it to Python, Go or Java doesn't
       | necessarily make sense. Rust lives in the same domain as C/C++.
       | 
       | One funny side note:
       | 
       | > Google used 15.5 terawatt hours of electricity in 2020
       | 
       | Bitcoin used 200 TWh in 2022 [1]. Think about that.
       | 
       | [1]: https://www.cnet.com/personal-finance/crypto/bitcoin-
       | mining-...
        
       | FpUser wrote:
       | I like how automatic memory management / safety in general
       | implemented in Cone language.
        
         | Ygg2 wrote:
         | What does Cone do? First time hearing about it?
        
           | verdagon wrote:
           | Author here, Cone is a pretty fascinating language.
           | 
           | It builds a borrow checker on top of any user-specified
           | allocator, whether that be single ownership, reference
           | counting, arenas, garbage collection, or any other user-
           | specified strategy. A user can even code their own.
           | 
           | It's a very promising approach, because it preserves the
           | borrow checker's strengths while addressing its the borrow
           | checker's development velocity downsides. GC and RC often
           | make a program's overall architecture looser and more
           | flexible, but by offering borrow checking for everything
           | else, it allows a program to much more cut down on its memory
           | safety overhead.
           | 
           | What Cone does differently than other languages is that it
           | decouples the allocation strategy from the type of data
           | you're working with. This makes it much easier to change your
           | code to use different memory safety styles. In a way, it's
           | like Rust but allows for more flexibility on memory
           | management.
           | 
           | It's still in progress, but I encourage anyone interested in
           | languages and memory safety to take a look:
           | https://cone.jondgoodwin.com/
        
             | zozbot234 wrote:
             | User-specified local allocators are planned for Rust too.
             | Among other things, they're needed for feature parity with
             | C++.
        
               | FpUser wrote:
               | >"feature parity with C++"
               | 
               | I think Rust is missing a fair bit more than "user-
               | specified local allocators" to be on feature parity with
               | C++. Curious if it plans to be on full feature parity.
        
               | verdagon wrote:
               | I recommend taking a look at Cone in a little more
               | detail, its type system support for allocators are head
               | and shoulders above what Rust has. The language's
               | awareness of allocator allows it to decouple it from the
               | users code in a way no other language allows (except
               | perhaps Odin).
        
               | comex wrote:
               | Technically it's only the standard library that lacks
               | custom allocator support. Box and Vec and all the rest
               | are "just" types defined in the standard library, and if
               | you define your own, you can use any allocator you want
               | and still take advantage of the borrow checker and other
               | language features. This has been possible since 1.0.
               | 
               | ...Well, except for certain magic features that the
               | standard library types get that you can't (yet) replicate
               | in a custom type. This is an annoying wart, but they're
               | relatively minor.
               | 
               | But yeah, custom allocator support for standard library
               | containers is planned.
        
           | FpUser wrote:
           | google cone programmer language. Short answer - your general
           | computer language that is not ready for any practical use.
        
       | H4ZB7 wrote:
       | [flagged]
        
       | zozbot234 wrote:
       | Developer velocity is a crock. You want to write code that
       | actually works over the entire software lifecycle, not just crank
       | out piles of utterly broken sh!t that you'll have to fix later at
       | huge cost. Rust has it right, and Ada/SPARK even more so.
        
         | galangalalgol wrote:
         | If you know algorithmically what will work sure, but if you
         | don't, and you need to throw multiple approaches at a problem
         | until one sticks, then a prototyping language is extremely
         | helpful. The problem comes when management notices the
         | prototype mostly works, they want you to ship it rather than
         | make something sane now that you know which direction to head.
         | I find using matlab is useful for this. Managers seem to
         | understand that you don't ship matlab, where if I used numpy or
         | julia...
        
       | comex wrote:
       | > In an average Google Earth quarter, only 3-5% of bug reports
       | were traceable to memory safety problems, and Address Sanitizer
       | made them trivial to reproduce in development mode.
       | 
       |  _Bug reports_ , sure. But as for _security vulnerabilities_ ,
       | both Microsoft and Google have reported that roughly 70% of them
       | were memory safety issues.
       | 
       | Personally, as a Rust fan, I fully agree that the borrow checker
       | limits developer velocity, and I'd be happy to toss it if I
       | could. But verdagon has been promising memory safety with no
       | overhead for years; I'll believe it when I see it.
       | 
       | Edit: Okay, that was unfair to say without further context, so
       | let me add two things. First, although Vale is open source, the
       | design has changed over time and the implementation was described
       | as a "work-in-progress" as of two months ago. [1] Second, a month
       | before that, verdagon described the design as providing
       | "statistical safety", meaning use-after-frees may fail to be
       | caught but are caught "99.9999999999996% of the time". Now,
       | stochastic exploit mitigations such as ASLR and PAC are valid
       | defenses, as long as that 99...% also applies in the presence of
       | an active attacker. But the specific design described (allowing
       | generation counters to wrap) sounds like, in many scenarios, an
       | attacker could manipulate it to provide no protection at all.
       | There may be ways to mitigate this, but in context it does sound
       | like it's designed under the assumption that memory safety
       | violations will occur at random, rather than being designed to
       | defend against attacks. This might be good enough for (some)
       | games, but not for most Rust use cases.
       | 
       | [1] https://verdagon.dev/blog/zero-cost-memory-safety-regions-
       | ov...
       | 
       | [2] https://verdagon.dev/blog/generational-references
        
       | [deleted]
        
       | revskill wrote:
       | To me, my productive development process is like this:
       | 
       | - Experimentation on the idea, algorithm, data structure,...,
       | everything that actually produces some result.
       | 
       | - Improve and finalize the specification of input, output,
       | resource constraint, and eventually the high level architecture
       | (modularity).
       | 
       | - Refactoring, with best practices and patterns.
       | 
       | - Benchmark usage and eventually swap out the implementation into
       | safe languages.
        
       | snovv_crash wrote:
       | Memory isn't the only resource that needs management. File
       | handles, network sockets, locks, security codes and more, all
       | need to have deterministic lifetimes. If you language doesn't
       | support lifetime management via some mechanism then all of these
       | things are the next part that will bite, even if you have GC for
       | memory.
        
         | SigmundA wrote:
         | In .Net/C# this is done with IDisposable and the using
         | statement which works quite well.
         | 
         | Ex:                 using (var sr = new StreamReader(filename))
         | {          txt = sr.ReadToEnd();       }
         | 
         | https://learn.microsoft.com/en-us/dotnet/api/system.idisposa...
        
           | pjmlp wrote:
           | Modern C# version,                   using var sr = new
           | StreamReader(filename);              txt = sr.ReadToEnd();
           | 
           | And for the _" what about forgeting to call using?"_,
           | 
           | https://devblogs.microsoft.com/dotnet/infer-
           | interprocedural-...
           | 
           | No different from using all those static analisers in C and
           | C++ to keep the code free of memory corruptions and UB
           | issues.
        
         | galangalalgol wrote:
         | This gets missed a lot. Rust isn't memory safe, it is resource
         | safe.
        
           | snovv_crash wrote:
           | It's funny that people are assuming I was talking about Rust
           | when I was actually referring to modern C++. RAII is a
           | powerful concept.
        
             | galangalalgol wrote:
             | It is, I've written c++ as my primary language for 30
             | years. I skipped c++14 and I'm still using 17, but staying
             | up to date other than that. But RAII doesn't come anywhere
             | close to the borrow checker in the number of mistakes it
             | prevents.
        
           | hoseja wrote:
           | Isn't it the other way around?
        
             | galangalalgol wrote:
             | My point is that it is both. The borrow-checker protects
             | _every_ resource, not just memory.
        
             | vlovich123 wrote:
             | How so?
        
         | kaba0 wrote:
         | While I do love Rust-style resource management, Java's try-
         | with-resources blocks plus cleaners are not particularly worse.
        
           | amai wrote:
           | Could a Java version of the future maybe also manage memory
           | with a try-with-resources block ?
        
             | flanked-evergl wrote:
             | Java and the JVM has a garbage collector, and will likely
             | always have, and GC makes memory management a lot simpler
             | and safer, so while you could use try-with-resources for
             | some kind of memory related resource, it likely would not
             | be to make things safer, but to make things less safe and
             | faster, and if you start doing that you will have
             | significantly reduced safety compared to rust I think.
        
             | kaba0 wrote:
             | Your wish is granted :D
             | 
             | https://openjdk.org/jeps/424
             | 
             | Though there was nothing inherent to ever block you from
             | doing it (just create an object that implements Closeable,
             | and malloc in the constructor, free in the close method),
             | this new API makes it quite great. The basic API gives you
             | a SegmentScope which denotes a lifetime, and MemorySegments
             | that point to a memory region (pointer+size+layout+scope).
             | MemorySegments have both spatial and temporal safety, so
             | accessing memory out of boundary will only throw an
             | exception instead of corrupting memory, while any access
             | outside the lifetime of the scope is forbidden. Oh, and
             | they are also thread-safe, only optionally being shared
             | between threads.
             | 
             | So in practice it you can write something like
             | try (var arena = Arena.openConfined()) {
             | MemorySegment segment = arena.allocate(someLayout);
             | // use segment        } // memory will be deallocated here
        
               | zozbot234 wrote:
               | That's a nice improvement over sun.misc.Unsafe .
        
               | amai wrote:
               | Nice. Thank you for pointing that out.
        
           | snovv_crash wrote:
           | What about if you want your resource to be longer lived, but
           | still safely disposed of in a timely manner when it goes out
           | of scope, for example a port in a webserver class? Do you
           | have to keep the stack alive here to keep the resource, or
           | can you put it into an object somewhere to get a more RAII
           | style resource management?
        
           | pkolaczk wrote:
           | Try-with-resources is tied to a lexical scope. C++/Rust RAII
           | is not, you can move the resource e.g to another thread after
           | initialization, and that thread can outlive the scope that
           | created the resource. Also C++/Rust allows shared ownership
           | through recounted references, something try-with-resources
           | can't do.
        
           | hawk_ wrote:
           | Cleaners aren't deterministic, so that's meaningfully worse
           | than rust's resource mgt. Java's try with resources cleanup
           | only works if the resource is freed up before the callstack
           | is unwound. Currently that's only viable for the most trivial
           | of scenarios. Loom will make that applicable in more places
           | but still not as widely applicable as a borrow checker/rc
           | based deterministic resource management.
        
         | pjmlp wrote:
         | System languages with GC like D (one example among many others)
         | support RAII for resource management.
        
       | zamalek wrote:
       | > Unsupported Patterns
       | 
       | > Graphs; it generally only thrives with a strict tree hierarchy
       | of data.
       | 
       | This is actually now supported: https://doc.rust-
       | lang.org/std/rc/struct.Rc.html#method.new_c...
       | 
       | That being said, Rust has taught me that I was vastly overusing
       | graphs (structurally, not algorithmically) in my code. Graphs are
       | extremely difficult to reason about; a fact that I learned after
       | approaching an unfamiliar Rust codebase for the first time. It
       | was the brain equivalent of putting down a screwdriver and
       | picking up a powertool, my mind just _relaxed._
       | 
       | That alone is one reason I think that every developer should try
       | and "suffer" under that constraint for at least one or two real
       | problems (whether with Rust, or some other language). You'll end
       | up writing better code in your preferred language.
       | 
       | The removal of a feature is sometimes a feature. While roads
       | limit where you can drive, they also mean you don't have to
       | figure out how to traverse a mountain in a Lambo.
        
         | Jensson wrote:
         | That is how you write programs in competitive programming, just
         | put all the data you need in a nice table structure and use
         | indexes instead of references. It is very readable and easy to
         | reason about for simple programs and is extremely fast to write
         | and performant, that is how you are able to implement novel
         | algorithms in minutes. But it doesn't scale, indexes aren't
         | type checked nor do they tell you which collection they point
         | towards.
         | 
         | But yeah, knowing how to program like that is useful, learning
         | new style will never hurt, but being forced to code like you
         | code in competitive programming isn't a good thing for a
         | language.
        
       | warangal wrote:
       | I write most of my code in Nim language, and it generally
       | involves wrapping up some C codebase, or calling DLLs routines
       | and working with raw pointers. Although Nim has it own GC or ARC
       | to handle memory management for its native data-structures, i
       | find it really helpful to define a `destructor` for any arbitrary
       | objects/structs. Since language can track lifetime of any
       | object/struct during compilation and can call corresponding
       | `destructor` for that object, which generally is just a `free()`
       | or `some dll exposed routine`. I end up using language to handle
       | all the manual memory management even for existing C codebase.
       | With new ARC, all destructor calls are inserted with compilation
       | and hence no extra GC based runtime to deal with, and even works
       | flawlessly with GPU programming stuff too ! I haven't used many
       | programming languages, but personally find it really useful to
       | use any language as an assistant to help solve issues outside of
       | their intended context.
       | 
       | I also have written about patterns i find useful when dealing
       | with existing C codebases at
       | https://ramanlabs.in/static/blog/raw_memory_management_with_...
        
         | intelVISA wrote:
         | Nim is a sleeper, plenty of GC options from ORC to manual and
         | great C FFI.
         | 
         | Wish the big corps had backed it, or Zig, over drab stuff like
         | Go.
        
       | mprovost wrote:
       | This is a really interesting observation: "Stateless programs
       | like command line tools or low-abstraction domains like embedded
       | programming will have less friction with the borrow checker than
       | domains with a lot of interconnected state like apps, stateful
       | programs, or complex turn-based games."
       | 
       | In my book [0] teaching Rust, I manage to completely avoid using
       | lifetimes. Perhaps this is because it reimplements a command line
       | utility (head, wc, cat, ...) from the original BSD sources in
       | each chapter and none of them are stateful. Most of the classic
       | Unix utilities just process streams of bytes and barely use data
       | structures at all. Many don't even call malloc().
       | 
       | It feels like Rust is a good match for the problem domain but I
       | never made the connection with the stateless nature of these
       | tools before. This bodes well for eventually replacing the
       | coreutils with modern Rust implementations.
       | 
       | [0] https://rftgu.rs/
        
         | verdagon wrote:
         | This was a particularly fascinating realization of mine a few
         | years ago. I realized that for certain domains, the borrow
         | checker was a dream to use (command line tools and scripts, ECS
         | games), and in others it wasn't so much (GUI, turn-based
         | games).
         | 
         | I dove a little deeper, and the stateful/stateless distinction
         | seemed to be the best rule-of-thumb for predicting how much one
         | would be in conflict with the borrow checker's preferred
         | styles. It was also reminiscent of functional programming
         | languages, in a way.
         | 
         | I suspect this is why most discussion comparing Rust to other
         | languages devolves so quickly, and has become so polarized: it
         | depends on the domain. Users who try to use it for some domains
         | will hate it, and users who try it on other domains will love
         | it.
         | 
         | This is also why I recommend newer Rust programmers to not be
         | afraid of using Rc/RefCell in certain domains. Some domains
         | don't agree as much with the borrow checker, and Rc/RefCell can
         | make the architecture a lot looser and easier to work with.
        
           | Jensson wrote:
           | > I suspect this is why most discussion comparing Rust to
           | other languages devolves so quickly, and has become so
           | polarized: it depends on the domain.
           | 
           | The problem is that Rust proponents argues that Rust is
           | better for all domains. I don't think anyone says that Rust
           | doesn't have a place, the source of controversy is whether
           | every low level programming task is best done in Rust or not.
        
           | gavinray wrote:
           | I made almost this EXACT comment a few days ago, nice to see
           | I'm not crazy
           | 
           | https://news.ycombinator.com/item?id=34386997
           | 
           | For 98% of tasks Rust is incredible. But modeling those 2% of
           | problems that don't fit neatly into Rusts domain, the level
           | of "unsafe", "PhantomData", and advanced type-system hacks
           | you need feels obscene when I can use some pointers in C++.
           | 
           | I will openly say I think Rust is an all-around better
           | language. If you are building general-purpose systems
           | software, or just want to write fast software, use Rust.
           | 
           | If you are fiddling with bits, doing low-level concurrency,
           | writing a GC/Memory Manager etc, or have self-referential
           | datastructures like graphs or trees, you're going to have an
           | order of magnitude easier time writing it in C++. (Rust-
           | experts excepted)
        
       | planetis wrote:
       | > Lobster is using borrowing and other static analysis techniques
       | under the hood to eliminate a lot of reference counting overhead.
       | 
       | Nim is one of the first languages to use borrow checking to
       | prevent copies and ref counts, and it's done both explicitly with
       | the experimental 'views' feature and when permitted implicitly.
        
       | UltraViolence wrote:
       | "Rust has made the decision that safety is more important than
       | developer productivity. This is the right tradeoff to make in
       | many situations -- like building code in an OS kernel, or for
       | memory-constrained embedded systems -- but I don't think it's the
       | right tradeoff in all cases, especially not in startups where
       | velocity is crucial."
       | 
       | I completely disagree with this statement. If a Rust developer
       | takes longer to code some feature this time will eventually be
       | saved fixing memory bugs later on. And don't forget the
       | immaterial cost of losing customer confidence if the product
       | crashes or glitches because of memory instability.
       | 
       | And then I'm even glossing over the enormous benefit of Rust when
       | writing correct multi-threaded code, which is almost always a
       | minefield in C/C++. Code that looks and seems to work OK might in
       | production suddenly crash after a year or so. A complete
       | nightmare!
       | 
       | Memory safety is ALWAYS a good thing to have.
        
         | Tade0 wrote:
         | My take is that it was always about expanding the pool of
         | people capable of writing safe code, thus making it cheaper.
         | 
         | I spent most of my career in front-end, where such
         | considerations are way down the priority list, but even I was
         | able to produce something in Rust that compiles.
         | 
         | That being said I never understood why would anyone want to use
         | this language for web development - most problems are solved in
         | that space, so if you're not out to tackle tje unsolved ones,
         | it might not be worth it.
        
         | brabel wrote:
         | > If a Rust developer takes longer to code some feature this
         | time will eventually be saved fixing memory bugs later on.
         | 
         | You don't disagree at all. "Later on" may never come to your
         | start up , you're actually helping make that point for the
         | author.
        
       | roca wrote:
       | I agree that GC languages are faster for prototyping, but this
       | article downplays the disadvantages of GC. E.g. "deterministic
       | destruction" is listed as a benefit of reference counting, but it
       | really should be listed as a disadvantage of GC, since all the
       | other memory-management methods have it.
       | 
       | The "leaky abstractions" argument doesn't work for me. E.g. in a
       | Java API you don't commit (at the language level) to the
       | ownership of passed-in or returned mutable objects. In Rust, you
       | do, and the author claims this is a problem. I say that in fact
       | you depend on the ownership of the referenced object either way;
       | Rust forces you to write down what it is and enforce that the
       | callers honor it, while in Java you cannot. Arguably therefore
       | Rust is _less_ leaky in that hidden assumptions are documented
       | and enforced at the API layer.
       | 
       | I've had lots of good experiences refactoring Rust code. It's
       | probably more typing than other languages but the increased
       | assurance that you didn't break the code (especially in the
       | presence of parallelism) more than makes up for it.
        
         | masklinn wrote:
         | > The "leaky abstractions" argument doesn't work for me. E.g.
         | in a Java API you don't commit (at the language level) to the
         | ownership of passed-in or returned mutable objects.
         | 
         | Yep, and so you get all sorts of bugs or defensive code
         | everywhere. For that reason I also have a hard time with one
         | section being
         | 
         | > GC'd code can be more correct
         | 
         | But apparently issues like iterator invalidation and other
         | mutability conflicts don't rate.
        
           | brabel wrote:
           | The author mentions how experienced C developers use some
           | techiniques that drastically improve the correctness of their
           | code.
           | 
           | The same goes with Java: we never use mutability in modern
           | code bases anymore unless we have strong reasons to do so and
           | can keep that mutability as constrained locally as possible.
           | 
           | We also avoid inheritance these days, have your heard about
           | that!? Because yeah, inheritance can be helpful but tends to
           | bite you in the end.
        
           | verdagon wrote:
           | While technically true, I'm not sure that the iterator
           | invalidation argument is that strong in practice. Rust
           | doesn't seem to eliminate those problems, it more moves them
           | around and transforms them into different (though sometimes
           | easier) problems.
           | 
           | We often think that the borrow checker protects us from these
           | kinds of mutability conflict / single-threaded race
           | conditions, by making it so we don't have a reference to an
           | object while someone else might modify it. However, the
           | classic workaround is to turn one of those references into an
           | index/ID into a central collection. In real programming, that
           | index/ID is equivalent to the reference. But while I hold
           | that index/ID, the object can still change, which kind of
           | throws the benefit into question.
           | 
           | In other situations where we only have multiple read-only
           | references, there's not really a motivating problem to begin
           | with, even when coded in other languages that don't also
           | regard them as read-only.
           | 
           | I think the other benefits the article mentions (concurrency
           | benefits, plus encouraging into flatter, cleaner
           | architectures) are a bit more compelling.
        
           | bsder wrote:
           | > But apparently issues like iterator invalidation and other
           | mutability conflicts don't rate.
           | 
           | They don't, because you're using java.util.concurrent when
           | you need data structures that deal with concurrency.
           | 
           | I miss java.util.concurrent _terribly_ when I have to program
           | in any other language. I don 't miss Java, but I weep every
           | time I need the equivalent of ConcurrentHashMap or
           | CopyOnWriteArrayList in another language.
        
           | pornel wrote:
           | I get it about Rust, because Rust really won't let you hide
           | the fact that you're holding on to a temporary reference (GC
           | is an abstraction over lifetime of objects). Borrow checking
           | is also intentionally less flexible about getters (allowing
           | library author to do anything in the getter, but that makes
           | exclusive-mutable getters exclusive over the whole object not
           | just one field). So Java programmers are in for a shock --
           | public fields are encouraged, and APIs have to commit to a
           | particular memory management strategy.
           | 
           | But OTOH not having to worry about defensive programming is
           | so great. Nothing is NULL. Nothing will unexpectedly mutate.
           | Thread-safety is explicit. It's always clear when vectors and
           | objects are passed, copied, or only briefly inspected.
        
             | pjmlp wrote:
             | Welcome to ML derived languages with tracing GC, specially
             | pure ones.
             | 
             | Java isn't the be all end all of GC based languages.
        
               | moonchrome wrote:
               | I'd think that if you're dealing with immutable data/pure
               | functions GC becomes transparent even in Java ?
        
               | pjmlp wrote:
               | Yeah, however even with using Scala/Clojure, there is the
               | possibility to touch parts of the standard library that
               | fail to uphold such expectactions.
               | 
               | So then one ends up with the usual issue of guest
               | languages, where one needs to create wrappers for the
               | platform APIs to keep the code idiomatic and language
               | invariants.
        
         | za3faran wrote:
         | Even if you use a non-GC language, you are not guaranteed
         | deterministic destruction (e.g. in data structures with loops
         | or a highly variable number of nodes).
        
         | pjmlp wrote:
         | Because no two languages are implemented the same, and there
         | are plenty languages with tracing GC that also support
         | deterministic destruction.
         | 
         | Unfortunely people keep reading only about Java and then they
         | think they know something about GC based languages.
         | 
         | Modula-3 and Mesa/Cedar are two examples from the past, D one
         | from modern times, with many others in between.
        
           | ben-schaaf wrote:
           | Probably the same for the others; in D you have RAII but
           | destruction is only deterministic for stack/static variables.
           | There isn't deterministic destruction for heap allocated
           | stuff unless you count manually freeing.
        
             | pjmlp wrote:
             | Except the little detail that manual heap allocation with
             | RAII is also a thing.
        
               | gumby wrote:
               | That case isn't completely deterministic the way stack
               | is: for the stack you just shift the SP which is constant
               | time, while heap allocation and deallocation require
               | manipulation of a small database, possibly including a
               | system call.
               | 
               | This is a bit of hair splitting I admit.
        
               | pjmlp wrote:
               | It is as deterministic as RC algorithms, which is usually
               | the point being discussed.
               | 
               | Yep, splitting hairs. :)
        
               | ben-schaaf wrote:
               | In which case you're no longer using the GC. You don't
               | have GC & deterministic destruction, you have GC xor
               | determinism.
        
           | WalterBright wrote:
           | D is not a gc based language. GC is just another tool D makes
           | available to the programmer.
        
             | gavinray wrote:
             | For other folks who don't write D:
             | 
             | D has GC, no GC ("@nogc" mode), or Ref-Counting
             | (experimentally) with "@safe" and "@live" modes.
        
               | pjmlp wrote:
               | Which is exactly the point of GC enabled systems
               | programming languages since the Xerox PARC days.
               | 
               | Provide all the required features to write a full OS,
               | while having the convenience of a GC for most of the
               | code.
        
             | pjmlp wrote:
             | It is according to CS definition, and will keep being one
             | unless @nogc is enabled by default for everything.
        
               | WalterBright wrote:
               | Using the GC in D is entirely at the user's discretion.
               | You can also do functional programming in D, or not. The
               | same with OOP, or not. Or RAII, or not.
               | 
               | This is unlike Java, which forces the use of GC and OOP.
               | Or Haskell which forces functional style.
        
         | kaba0 wrote:
         | Manual memory management does close-couple memory
         | layout/ownership with the public API, and that will objectively
         | make refactors regarding that layout breaking changes, causing
         | many downstream changes required.
         | 
         | A quote from the GC Handbook: "modules should not have to know
         | the rules of the memory management game played by other
         | modules"
         | 
         | While Rust does make these refactors safe, it is nonetheless
         | work that simply doesn't have to be done in case of Java for
         | example.
        
         | anonymoushn wrote:
         | > The "leaky abstractions" argument doesn't work for me. E.g.
         | in a Java API you don't commit (at the language level) to the
         | ownership of passed-in or returned mutable objects. In Rust,
         | you do, and the author claims this is a problem. I say that in
         | fact you depend on the ownership of the referenced object
         | either way; Rust forces you to write down what it is and
         | enforce that the callers honor it, while in Java you cannot.
         | Arguably therefore Rust is less leaky in that hidden
         | assumptions are documented and enforced at the API layer.
         | 
         | A lot of programs and large parts of a lot more programs just
         | don't need these concepts at all and would run correctly with a
         | GC that did not collect any garbage, memory permitting. Most
         | Python code I write is in this genre.
         | 
         | On the flip side, at work we mainly work on a low-latency
         | networked application that has per-coroutine arenas created
         | once at startup and long-term state created once at startup.
         | The arenas are used mostly for deserializing messages into
         | native format to apply to the long-term state and serializing
         | messages to wire format. There's not much benefit to be had
         | from writing all the time that everything that isn't on the
         | stack belongs to the per-coroutine arena, except for all
         | instances of like 3 structs, which belong to the long-term
         | state.
        
         | georgeecollins wrote:
         | As an older dev who spent a lot of time with C on applications
         | where performance and timing was key, I have found the timing
         | of the overhead of GC hard to predict. So I tend to pre-
         | allocate a lot of variables and structures in advance and hold
         | them, so I don't have to worry about GC in a loop. If someone
         | knows a good tutorial of how to predict when garbage collection
         | will happen in my program, I would love to read it and learn
         | more.
        
         | UltraViolence wrote:
         | I disagree. It depends on the type of project you're working
         | on. If you're writing a public facing high-performance
         | application it MAY be more beneficial to use deterministic
         | memory management.
         | 
         | Most tools, even very technical tools like assemblers,
         | debuggers and compilers, don't need deterministic memory
         | management. Only operating systems, device drivers and some
         | time-critical applications (like video/audio encoding/decoding)
         | need deterministic memory management.
        
           | pkolaczk wrote:
           | The trick is, when you have deterministic destruction you can
           | use it for many more things than just memory management. E.g.
           | need to add a metric to measure how many "somethings" are
           | active - just attach a tracker to the struct representing
           | that "something" and the tracker can count itself because it
           | knows exactly when it is created and destroyed. We tried to
           | add such metrics system to a Java app another day, and it
           | turned out to be virtually impossible because due to GC
           | nondeterminism we couldn't tell when most of the objects die.
        
             | UltraViolence wrote:
             | Do you really need to know? All that matters is that the GC
             | will eventually clean up the used memory. When you're
             | interested in that sort of info you're using the wrong
             | language or asking the wrong kind of questions.
        
               | pkolaczk wrote:
               | Yes, of course I need to know. An important part of
               | production grade software is observability. And that
               | "something" doesn't have to be memory. It can be a
               | connection, file handle, semaphore permit or one of many
               | other things. But even for memory, typically there is not
               | just one global type of memory. Users want to know how
               | much memory is dedicated to X, Y and Z components, they
               | might also want to constrain memory use by logical
               | function. E.g separate buffer pools. This is where
               | automatic memory management with GC falls apart very
               | quickly - even the Java apps I work on actually use a
               | memory/resource abstraction layer on top and manage
               | everything manually, leaving just the last bit of
               | releasing the objects to GC. Which is the worst of both
               | worlds - we get all the disadvantages of MMM and all
               | disadvantages of tracing (pauses, cache thrashing, etc).
        
               | Jensson wrote:
               | Java doesn't sound right for your use case. Most programs
               | written in Java works just fine without tracking memory,
               | and if you have any issues you do a jvm memory dump to
               | see which object types are taking up all that memory and
               | then look at why they weren't collected.
        
               | pkolaczk wrote:
               | Sure, I know that. But sometimes you don't have a choice
               | because the decision was made years earlier by someone
               | else, and you obviously won't rewrite a 1M LOC codebase.
               | 
               | Nevertheless, after spending a year writing Rust, I'd
               | take Rust over Java for just any use case now, even
               | including CRUDs and GUIs (actually doing a GTK GUI for a
               | Rust app right now, and it is not any worse in terms of
               | dev speed than Java Swing was, despite what people say
               | about callbacks - I really don't mind an occasional
               | Rc/Refcell/clone here and there).
        
               | jandrewrogers wrote:
               | It comes up quite a lot in things like databases and
               | high-performance data infrastructure generally. The
               | instantaneous resource state is an important input
               | parameter to many types of dynamic optimization. Ideally,
               | you want to run close to the resource limits without
               | exceeding them for maximum throughput and robustness
               | while minimizing tail latencies. Knowing precisely how
               | many resources are available allows the code to
               | opportunistically apply that capacity to workload
               | optimization without risking resource starvation. Some
               | software will also adaptively switch entire strategies
               | based on this information. It is very useful information
               | if you are designing for performance.
               | 
               | If you have no idea how many resources are actually
               | available, you are forced to use conservative strategies
               | to protect the process. Guessing or ignoring resource
               | availability is an excellent way to greatly increase
               | performance variability and reduce throughput.
        
               | lelanthran wrote:
               | >> need to [...] attach a tracker to the struct
               | representing that "something" and the tracker can count
               | itself because it knows exactly when it is created and
               | destroyed.
               | 
               | > Do you really need to know?
               | 
               | He, uh, just said that. If you're tracking profiling
               | metrics like he is (lifetime of a call-stack, maybe?),
               | you _need_ to know.
               | 
               | > When you're interested in that sort of info you're
               | using the wrong language
               | 
               | Under that argument, Java is the wrong language for
               | everything.
        
         | zozbot234 wrote:
         | > in a Java API you don't commit (at the language level) to the
         | ownership of passed-in or returned mutable objects. In Rust,
         | you do[.]
         | 
         | That's only the default, of course. Rc is commonly used in Rust
         | to decouple ownership management from the simple use or passing
         | of objects throughout the program, much like in any GC
         | language. (Of course Rc on its own does not collect reference
         | cycles; thus, "proper" tracing GC is now becoming available,
         | with projects like Samsara https://redvice.org/2023/samsara-
         | garbage-collector/ that try to leverage Rc for the most part,
         | while efficiently tracing possibly-cyclical references.)
        
         | galangalalgol wrote:
         | It is more typing than julia or numpy maybe, but probably not
         | more than c#, maybe not more than go, and most certainly not
         | more than java.
         | 
         | I think even within GC languages developer velocity varies a
         | lot based on things like typing system, reflection, repl, and
         | maybe interpreted vs compiled. My experience is that this
         | variance is greater than what can be put at the feet of memory
         | management
        
           | kaba0 wrote:
           | Java is much much less verbose than Go, and contrary to
           | popular opinion, it really is not particularly verbose,
           | especially modern Java.
        
             | [deleted]
        
             | galangalalgol wrote:
             | I haven't written much go or much java (in this millennium
             | anyway). The little go I wrote didn't have many error
             | checks, is that what usually makes it verbose? The modern
             | java I wrote was a little more functional than 1999 java,
             | but it utilised reflection heavily, and it was a test
             | harness for a black box, so not idiomatic probably, but
             | there was still a lot of boilerplate. C# seems about normal
             | verbosity, and so does rust. Both are less verbose than a
             | lot of c++98 I run into because of lambdas and iterators
             | etc. Julia on the other hand is quite possibly the least
             | verbose language I have ever seen, apart from matlab (which
             | isn't truly general purpose) , and python/numpy/pytorch
             | close behind.
        
               | jcparkyn wrote:
               | > least verbose language I have ever seen
               | 
               | You'd love APL.
        
       | henry_viii wrote:
       | Surprised to see no mention of V. I assumed it was using a model
       | similar to Lobster?
        
       | CGamesPlay wrote:
       | One of the interesting things about MMM and borrow checking is
       | that it enables you to implement GC and RC. Rust has RC built in
       | of course, but the general consensus seems to be that it's "not
       | idiomatic". There's also crates for GC. Would a Rust project that
       | relied heavily on GC be able to sustain the sort of velocity that
       | a project in a native-GC language had? Would it even be close?
       | 
       | I love Rust's developer experience, frankly. The macros and build
       | system are the main reason I like the language. I hate the borrow
       | checker most of the time, for exactly the reasons listed in the
       | article. It's probably a terrible choice for a 7DRL project,
       | unless it was some sort of Rust core with content that was
       | primarily orchestrated from another language (possibly DSL).
        
         | kaba0 wrote:
         | I'm not sure regarding the benefits of adding such a library-GC
         | (that effectively does RC with cycle detection) to Rust. RC is
         | just very slow and there is a very good reason that no
         | performant managed runtime uses it. They are good in that they
         | need no explicit support from the runtime, but that only makes
         | them _possible_ , not performant.
         | 
         | I would wager introducing a small rust hot loop via FFI into a
         | managed language is a much saner route, using the respective
         | languages to the best of their abilities.
        
           | zozbot234 wrote:
           | Obligate ARC is slow. RC/ARC as used in Rust (ARC separately
           | marked, only used when required for thread safety; RC in
           | general only for objects that may need to be kept around by
           | multiple parts of the program, with no fixed "owner"; with
           | simple RAII used for everything else) is very fast,
           | comparable to manual memory management.
        
             | kaba0 wrote:
             | It can remove a few increments/decrements (more like a
             | single pair at inlining a function), but that's not what
             | makes it problematic.
             | 
             | If you do have a bigger object graph, not using it anymore
             | will recursively go on and decrement the counters, removing
             | potentially many objects from memory, totally killing the
             | given thread's cache/performance. All that is amortized
             | with a tracing GC. On top, atomic counters are very
             | expensive.
             | 
             | Of course you can probably get away with using (A)RC at few
             | places at most with Rust, but if you decide to track object
             | lifetimes with RC for loads of objects, it will have a
             | price (which may or may not be worthy. In my opinion, it is
             | better to stick to Rust for low-level programs)
        
           | CGamesPlay wrote:
           | Makes sense from a performance standpoint. But what about
           | development velocity? If the hypothesis is that wrestling
           | with the borrow checker is a big drain on productivity, then
           | bypassing it should restore that productivity.
        
         | toast0 wrote:
         | > I love Rust's developer experience, frankly. The macros and
         | build system are the main reason I like the language
         | 
         | On the contrary, I hate the macros, because the formater can't
         | format inside tokio select or some of the other macros, and
         | that means I have to do it manually, which is lame.
        
           | CGamesPlay wrote:
           | That's a pretty weak reason to hate macros, frankly. Seems
           | more like a deficiency in the formatter than in the language
           | feature.
           | 
           | As a side note, there's a poorly-documented behavior where
           | rustfmt will format macros that are wrapped in {} if it's
           | valid rust code. So you can even point the blame on tokio for
           | not using formatter-friendly macros.
        
             | timidger wrote:
             | I agree, that is a weak reason to dislike macros.
             | 
             | I dislike them primarily because of the additional
             | complexity they add that isn't always justified. All of the
             | more complex macros I wrote I regret, especially the one I
             | did at my last job since now others had to maintain it.
             | 
             | Some macro use can be justified, eg serde. But I try to
             | avoid using proc macros where I can (and certainly never
             | try write one anymore)
        
       | IshKebab wrote:
       | Interesting (though clearly biased) article. I suppose we
       | shouldn't be too surprised about the bias given the source.
       | 
       | My main issue with it is the focus on _short term_ developer
       | velocity. Fine if you are writing a game in a week and then
       | stopping. Most people are not doing that.
       | 
       | It has a great list of interesting new languages to look at!
        
       | fuklief wrote:
       | > In other words, CHERI can reduce memory-unsafety related
       | slowdowns by two thirds, which is pretty incredible. AMD CPUs are
       | even starting to have hardware support for it, bringing its run-
       | time overhead down to 6.8%.
       | 
       | Source on AMD CPUs having support for CHERI-style capabilities ?
       | Afaik, there is only the Arm Morello prototype out right now and
       | FPGAs.
        
         | pjmlp wrote:
         | Possible typo, the only known ones is ARM with the Monticello
         | project.
        
           | verdagon wrote:
           | Author here, that was indeed a typo, fixed now. Many thanks
           | for correcting that!
        
       | neonsunset wrote:
       | This article is biased in more than one way and misses a lot of
       | nuance and aspects of GC-based languages which are not limited to
       | pure GC and employ a lot of techniques for deterministic and
       | semi-deterministic memory management, and various trade-offs to
       | optimize for single/many-core and throughput/latency scenarios.
       | In fact, many modern garbage collectors are not dissimilar to
       | arena allocators making most of the allocations very cheap and
       | efficient.
       | 
       | In addition, Rust is difficult to use for iOS as it stands today
       | but you can for sure make it support a variety of scenarios with
       | delegates aka callbacks/function pointers/etc. Also RAII can be
       | supported with .drop() and more. Half of the cons are incorrect
       | and misrepresent current state of affairs.
       | 
       | It also recommends defaulting to Go over C# for making a web
       | server which my religious views compel me to publicly object to
       | :)
        
         | verdagon wrote:
         | Author here, you're correct that there are a lot of performance
         | tradeoffs involved with various GC'd languages, and also
         | correct that GC'd languages do have some support for
         | deterministic destruction (especially with defer).
         | 
         | The article was trying to focus on the general approach of GC
         | more than the GC'd languages themselves, and the article was
         | already pretty long so I tried to keep it scoped to just
         | developer velocity implications of the memory safety approaches
         | themselves.
         | 
         | I did mention some of those aspects, for example how C# is more
         | than just a GC'd language (it has value types to help avoid
         | GC), and Rust is more than just borrow checking (it has
         | RefCell). But I couldn't get as deeply into these other aspects
         | as I would like.
         | 
         | (It's also pretty funny that the article's been called biased
         | by both sides, in both directions now! Such is life.)
         | 
         | I also don't mean to specifically recommend Go over C#, and I
         | see the line that gives that impression, fixing now.
        
       | littlestymaar wrote:
       | I don't think this article is that interesting because it's
       | really biased, and doesn't even try to catch any kind of nuance,
       | especially regarding Rust.
       | 
       | Developer velocity in Rust is a complex topic, and yes sometimes
       | Rust will slow you down, but sometimes also it makes you move
       | much faster. You can find a lots of testimonial in all
       | directions, the majority of Rust users having a good opinion on
       | Rust on that topic (but we're biased too). But somehow this
       | article only chose to quote people complaining about developer
       | velocity with the language and completely ignore the other (and
       | larger) group of developers, praising the language user
       | experience and development velocity.
       | 
       | I don't think Rust is perfect, and I think that people talking
       | about how "Rust is the most loved language on Stack overflow for
       | the past N years" isn't really constructive. But a collection of
       | cherry-picked quotes showing how Rust is in fact a disaster isn't
       | bringing anything interesting to the discussion either...
        
         | verdagon wrote:
         | Author here, I tried to write this article to be as non-biased
         | as possible, though it was pretty difficult.
         | 
         | Most discussions and sources online compare Rust to easy
         | targets, like C, C++, or Python, so we never get to really dive
         | into the more interesting comparisons against stronger
         | languages (especially GC'd ones). There are also some studies
         | out there that try to measure Rust, but they measure the kinds
         | of complexity that wouldn't translate to real-life coding.
         | 
         | I actually like Rust (it's probably my favorite mainstream
         | language today besides Scala), and if you consider all the
         | dimensions together, there are a lot of situations where Rust
         | is the best choice. However, this article is about one specific
         | dimension (developer velocity) and on that, Rust unfortunately
         | has some drawbacks.
         | 
         | Also, the article does mention situations (concurrency) and
         | aspects (encourages top-down, flattened architectures) that
         | give Rust some advantages.
         | 
         | I tried to be un-biased. Perhaps it didn't quite show, also
         | since the conclusions recommended languages other than Rust
         | when focusing on developer velocity.
        
           | littlestymaar wrote:
           | I mean, that's OK to express criticisms on Rust developer
           | velocity (for instance, I totally agree that Rust doesn't
           | particularly shine for prototyping) but then you've assembled
           | from various parts of the internet a collection of TWENTY-ONE
           | testimonials from people complaining about developers
           | velocity in Rust, and _not a single one_ of people praising
           | Rust for the productivity boost it offers, though I can
           | definitely assure that there are, especially for refactoring
           | where Rust is commonly considered[1] to be first class.
           | 
           | Collecting pain point can be useful for the language, as it
           | helps the Rust team to get a better vision of what they can
           | improve, but doing such a one-sided list in an article about
           | _comparison_ to other languages and memory handling mechanism
           | is at best dubious.
           | 
           | > Most discussions and sources online compare Rust to easy
           | targets, like C, C++, or Python
           | 
           | My background is mostly Java then JavaScript and you can
           | quote me on the fact that I found Rust to be more productive
           | than both of them in average, especially when the project
           | last more than a few weeks. The biggest underlying reason is
           | different though, JS mostly suffering from dynamic typing +
           | overall questionable language and "standard library" design,
           | while Java is plagued by inheritance and dubious OOP
           | patterns. When using both of these languages after Rust I
           | also felt frustrated by the impossibility to assign strong
           | ownership to objects, making sure they aren't being watched
           | or mutated behind my back. Also, billion dollar mistake.
           | 
           | [1]:by rustaceans that is, it's not an objective measurement
           | of any kind, but we're talking about testimonials here.
        
             | verdagon wrote:
             | Like I mentioned in response to your other comment about
             | this, the anecdotes were added to the borrow checking
             | sections because that's what the initial readers were
             | surprised about. That in turn made those sections longer. I
             | also did mention the benefits of borrow checking (such as
             | the concurrency benefits and influencing us into cleaner
             | architectures), plus the downsides of garbage collection.
             | 
             | I didn't need any anecdotes for the borrow checker's
             | benefits because everybody already knows them. I see how
             | that can seem biased though, and next time I add citations
             | to the surprising parts of an article I'll also add them
             | more uniformly to the rest of the article as well.
             | 
             | Also, the article was about garbage collection itself
             | versus borrow checking itself, not any specific languages
             | that use them.
             | 
             | You make some valid comparisons between Rust and Java and
             | Javascript, but garbage collected languages don't need to
             | be dynamically typed, and don't need to have null, and
             | don't need to have OOP patterns. When you compare Rust to a
             | more modern language like Scala or Pony, you get a much
             | truer comparison of the approaches.
             | 
             | That's what the article is really comparing: borrow
             | checking versus garbage collection. Not the extra features
             | that are correlated with them in mainstream languages.
             | 
             | Cheers!
        
         | pjmlp wrote:
         | Is biased and incorrent in a few places, like disregarding
         | system programming languages with GC that also support
         | deterministic destruction of resources.
        
           | verdagon wrote:
           | This article was mainly about memory safety approaches (GC,
           | RC, borrow checking, etc) and their effects on development
           | velocity. It wasn't trying to compare all languages along all
           | dimensions. That would be quite a long article!
           | 
           | Anyway, I think you're referring to `defer`? Though perhaps
           | you're referring to something else, as defer also appears in
           | non-GC'd languages as well so it didn't seem like a very
           | relevant factor in this specific comparison. I do agree that
           | defer (and try-with-resources) can be stellar tools for GC'd
           | languages.
        
             | pjmlp wrote:
             | Nope, I am referring to C++/Ada style of RAII.
        
           | littlestymaar wrote:
           | I'm not surprised: when you read something and the part you
           | know about is bullshit, there's a good chance that the part
           | you don't know about is also bullshit even you can't see it.
           | 
           | What language have both GC and deterministic destructors, and
           | how does it works? I'd guess it couldn't be tracing GC
           | (because the GC runs whenever it wants, so you don't have
           | determinism, or at least that's my understanding). Or maybe
           | it's something like RAII for non-memory resources (with a
           | destructor that doesn't free memory), and a GC for memory
           | management?
        
             | pjmlp wrote:
             | Mesa/Cedar, Modula-3, Active Oberon, D, Nim, for example,
             | not to make an exhaustive list. C# also does provide some
             | mechanisms to dive into it, since version 7, although not
             | as easy.
             | 
             | Basically you can use GC heap as usual, or native heap with
             | untraced references, stack or global memory segments.
             | 
             | Value types with constructors/destructors pairs are also
             | supported.
             | 
             | So you have all the building blocks to do C++ style RAII
             | when needed, otherwise relax and enjoy the GC.
        
               | littlestymaar wrote:
               | thanks
        
         | UltraViolence wrote:
         | I believe Rust will ALWAYS be beneficial compared to MMM
         | languages because it will save time in the long run.
         | 
         | Programs with Rust will always be rock-stable, unlike many
         | C/C++ programs which are more like a house-of-cards.
        
           | zamalek wrote:
           | The borrow checker only prevents certain classes of memory
           | bugs. You can definitely still have logical bugs in Rust.
        
           | brabel wrote:
           | > Programs with Rust will always be rock-stable
           | 
           | How do you know that? Is there any data backing that up?
           | 
           | I've never seen any research showing that a programming
           | language, no matter how strict (Haskell, Ada, Rust) actually
           | improves the reliability of software, except for comparisons
           | between memory-safe and non-memory-safe languages. It almost
           | always goes down nearly entirely to development process and
           | team skills/experience, showing anything else convincingly
           | would be a huge breakthrough.
        
             | manholio wrote:
             | Well, here's my point of anecdata: despite Python being a
             | very productive language and very easy to use, despite it
             | existing for more than three decades and being perhaps the
             | most massively learned language by aspiring programmers
             | today, you hardly see any stand-alone application written
             | in it. I can name not a single application that I use on a
             | daily basis written in Python. It seems it's strongly
             | confined to the web-server, where the environments are well
             | controlled via containers, runtime bugs impact a single
             | page load and fixes can be applied continuously. People
             | don't ship Python standalone apps.
             | 
             | Based on the buggy and unstable Python desktop apps I have
             | used, I have a strong suspicion that developing large
             | applications in Python is strongly self-limiting after the
             | initial sprint.
        
             | UltraViolence wrote:
             | I'm speaking from my own experience here. I've tested a
             | couple of Rust programs which were developed in relatively
             | short order yet were quite complex (a Minecraft type game
             | being one) and there wasn't even the slightest hint of
             | instability.
             | 
             | Some of my own Rust code is moderately complex but never
             | showed any signs of instability during development. I often
             | have crashes now and again with my C++ programs. Sure, I
             | fix those afterwards but getting it flawless every time the
             | first time is (for me at least) unheard of.
        
           | littlestymaar wrote:
           | I'd agree with that too, but that's just my point of view and
           | I'd respect anyone else's _sensible_ argument of the
           | opposite.
           | 
           | But this article isn't that, and to make manual memory
           | management more appealing they had to ridiculously inflate
           | the issues that come with ownership-based memory
           | management...
        
             | brabel wrote:
             | I think it's you being biased against the article now. As I
             | read it, it was pretty honest and really trying to find
             | some sort of true, not just trying to bash Rust. Feels like
             | Rust fans are very defensive against criticism of any sort,
             | even when well intentioned as I think is the case here.
        
               | littlestymaar wrote:
               | Come on, there's literally 21 citations[1] of people
               | saying Rust slows them down, and ZERO citation of the
               | opposite.
               | 
               | There's not trying to hide that they are biaised, at this
               | point it's Kremlin-level of shameless bad faith.
               | 
               | [1] it looks like they've harvested Rust criticism for an
               | entire year at this point, since they end up even quoting
               | random discord comment from more than a year ago: https:/
               | /discord.com/channels/273534239310479360/818964227783...
        
               | verdagon wrote:
               | Author here, I tried to make this article as balanced as
               | possible, and even talked about Rust's advantages in
               | concurrency and encouraging cleaner architectures and the
               | disadvantages of MMM and GC approaches (plus other
               | aspects, see my other comment down-thread about this).
               | 
               | There are actually 45 citations in the article on all
               | angles, but I think you're talking specifically about the
               | anecdotes.
               | 
               | Regarding the anecdotes, I had to add more of those to
               | the borrow checking sections because it was the most
               | surprising to my initial readers. Very little discussion
               | online actually compares borrow checking to higher-level
               | languages with good development velocity; most discussion
               | online compares it to languages like C, C++, Javascript,
               | or Python, so this was new to most readers.
               | 
               | The article also explicitly mentioned that those were
               | anecdotes and colored them differently, so that people
               | didn't mistake them as data.
               | 
               | They also made that part of the article much longer than
               | it was originally.
               | 
               | I can see how that could come across as biased. Perhaps I
               | should have added citations to the other parts of the
               | article so their distribution was more uniform.
               | 
               | When you look at the content itself, it's pretty balanced
               | I'd say (hence the focusing on the other benefits of
               | borrow checking plus the downsides of GC), it's
               | unfortunate that's not coming through as much.
        
               | littlestymaar wrote:
               | Yeah, the issue is that you've given so much room for
               | critical citations that your article is basically a
               | pamphlet at that point.
        
               | UltraViolence wrote:
               | It may slow them down during their initial development
               | when they're new to Rust, but I'm convinced that it will
               | be much cheaper during the entire Application Lifecycle
               | (ALM), not to mention customer satisfaction.
        
       ___________________________________________________________________
       (page generated 2023-01-17 23:02 UTC)