[HN Gopher] Rusty ownership and the lifecycle's stone
___________________________________________________________________
Rusty ownership and the lifecycle's stone
Author : kapolos
Score : 86 points
Date : 2022-11-27 12:14 UTC (10 hours ago)
(HTM) web link (blogs.harvard.edu)
(TXT) w3m dump (blogs.harvard.edu)
| eternalban wrote:
| That kitty asked for "Pretty, please". Rust may be the wonder
| language but pretty it ain't.
| mellosouls wrote:
| (2021) btw in case any subsequent releases have changed anything.
| 29athrowaway wrote:
| This article is simply impossible to read.
| bornfreddy wrote:
| Ignoring (or hiding) the images, the explanation is actually
| the best one I have seen so far and well worth the read. I
| guess some people like the fun images too. /shrug
| IOT_Apprentice wrote:
| I found that not to be the case, and that the explanations were
| clear. I thought the images were contextually amusing. What
| specifically was problematic for you to read it?
| meindnoch wrote:
| I never thought I would feel like I'm watching TikTok when
| reading an article from Harvard, but here we go...
| harikb wrote:
| Rust fans, when you take a dig at Java or Python, be a bit nice
| and don't throw numbers without any basis
|
| > Python is two Orders of Magnitude (100x) slower than C.
| Suddenly, your $3,000 MacBook Pro barely beats an early-1990s-era
| 386DX computer.
|
| Right under Java logo
|
| > It is not just 60-frames-per-second games that long for high
| performance. Any CPU-bound or repeated process also requires it
| klysm wrote:
| You should be able to vaguely claim that Python and Java are
| inherently slower than Rust/C/Whatever. I agree claiming that
| it is 100x slower is a bit unfounded, but it's pretty easy to
| go find existing benchmarks that show results like this.
| kapolos wrote:
| Yes, it's exactly as you say.
|
| I did search for benchmark comparisons and bumped into one
| that had 2 orders of magnitude difference.
|
| But naturally, isolated benchmarks can't encapsulate the
| whole picture because there's a world of difference between
| testing how fast a loop runs and performance in production.
| codedokode wrote:
| I guess that arithmetic operations are not very slow in
| Python, but if you use objects, then Python performs
| complicated lookups for every field or method access.
| kapolos wrote:
| If I recall correctly, the first time I used Java it was way
| back in JDK 1.1. It was amazingly slow. Of course, today's Java
| is fast enough for its domain, but I still enjoy throwing a jab
| at it here and there :)
| tln wrote:
| I think the Java image should be associated the paragraph
| before...
|
| > In general, the garbage collector is an inefficient beast.
|
| The article has a tongue-in-cheek style, does the author really
| need to link to Benchmarks Game and CPU benchmarks?? Modern
| systems are way more than 100x faster than 386DX anyway.
| pflanze wrote:
| Speaking from my observations:
|
| You can't make typical Python programs two orders of magnitude
| faster by rewriting them in C, but that's because those use
| many bits that are already implemented in C (data structure
| implementations, regex engine, I/O, databases etc.).
|
| If however you would rewrite those bits in Python, which is
| what OP said ("that Python is now the only legal programming
| language in the world to code with"), things _would_ become two
| orders of magnitude slower (when using the current CPython
| implementation to run the Python program)! A program doing low-
| level work (e.g. a B-tree implementation) is that much faster
| when written in C over Python (if you don 't cheat and write
| bits of your Python program in C), assuming that the C program
| does take advantage of the optimizations that you _can_ do (and
| typically do) in C. It might be more like a factor of 60, but
| on a logarithmic scale that 's much closer to two magnitudes
| than one.
|
| This is assuming CPython, not PyPy or one of the subset-of-
| Python compilers that work more like C.
|
| PS. OTOH, I think a 386DX is more like 1/1000 of a modern CPU's
| speed (maybe 1/10000 if counting multiple cores and SIMD).
| codedokode wrote:
| > The biggest of said problems is that the garbage collector has
| the annoying habit to "pause the world".
|
| I think that main problem of garbage-collected programs is that
| they usually allocate several times more RAM than they use. This
| causes excessive swapping which produces more noticeable lags
| than just garbage collection. I vaguely remember reading
| somewhere that the difference can be 6x, but I am not sure if
| this is the correct number. This means that garbage-collected
| software is great for large expensive servers stuffed with RAM
| sticks but not so great for a personal computer having just 4 or
| 2 Gb.
| ok123456 wrote:
| Go solved this problem with a three color garbage collector.
| nayuki wrote:
| "Mob program" made me giggle. It must be the logical extension to
| pair programming.
| asplake wrote:
| https://en.wikipedia.org/wiki/Mob_programming
| Mxrtxn wrote:
| Best explanation I have ever heard! Really good examples. Hope to
| see more.
| timakro wrote:
| Small correction: contrary to what the post claims this does not
| compile: fn main() { let s =
| String::from("hello"); foo(s);
| println!("{}", s); } fn foo(le_string:
| String) -> String { println!("{}", le_string);
| le_string }
|
| This does, which is probably what the author meant:
| fn main() { let s = String::from("hello");
| let s = foo(s); println!("{}", s); }
| fn foo(le_string: String) -> String { println!("{}",
| le_string); le_string }
|
| Great post!
| kapolos wrote:
| Indeed, thank you for catching it! I will make an update.
|
| Thanks again!
| kapolos wrote:
| A tongue-in-cheek exploration of how Rust achieves memory safety
| & performance, for people interested in Rust coming from high-
| level (managed) languages.
| protortyp wrote:
| This is really one of the easiest-to-comprehend articles I have
| read so far on Rust ownership! I hope they put out more similar
| content.
| aaa_aaa wrote:
| Is it too much to ask for an article without memes, jokes and
| puns?
| fnordpiglet wrote:
| Wow. Yes, on the internet, it sort of is.
| kapolos wrote:
| What can I say, I like memes & jokes -\\_(tsu)_/-
|
| On a more serious note, I think lighthearted content is what's
| needed when it comes to intro stuff. There are no puns in the
| Rust Book ( https://doc.rust-lang.org/book/ ) ;)
| turtleyacht wrote:
| The _Head First_ series uses similar techniques to help aid
| book learning. At least there is precedent :)
| 29athrowaway wrote:
| "Let's get rusty" on YouTube has a really good intro to Rust,
| including this topic and others.
|
| Short videos that are simple and go to the point.
| taberiand wrote:
| There's a lot of talk in general how Rust has a steep learning
| curve, mainly due to the borrow checker and lifetimes - but is
| this as hard as it gets?
|
| Everything here seems logical and fairly self-explanatory, the
| only slightly alien thing is the lifetime annotation.
|
| Are there advanced gotchas that can actually trip up an
| experienced coder? Are there some aspects of real work that Rust
| makes difficult, or impossible?
|
| I mostly code in C# (which in my opinion is an excellent and
| productive ecosystem), but Rust seems to make a promise of
| providing a greater level of confidence in the code that is very
| alluring - I'd like to take the plunge, I'm just a bit worried
| about smashing into any hidden rocks at the deeper end
| ok123456 wrote:
| The ownership rules make it very difficult to write data
| structures.
|
| Even the most trivial singly linked lists have caused
| innumerable blog articles to be penned on how exactly to do
| that in the most idiomatic Rusty way.
|
| Personally, I don't see any problem with using unsafe Rust in
| these instances, because linear types are not appropriate model
| as you don't have a single source and sink.
| tcfhgj wrote:
| > Even the most trivial singly linked lists....
|
| Well you exactly named the most difficult to handle data
| structures for Rust.
|
| There are plenty that are easy
| ok123456 wrote:
| A linked list is the simplest data structure there is.
|
| Is a Red-Black tree simpler than a linked list to implement
| than a linked list in Rust? What about a Fibonacci heap?
| mtlmtlmtlmtl wrote:
| I think using data structures as an example is sort of
| missing the forest for the trees. It's definitely harder
| to do, but you generally don't need to as there's an
| excellent standard library and wider ecosystem of
| libraries that do this for you.
|
| And implementing data structures in any language is hard.
| It's just a harder thing to do than most things because
| there's always gonna be a lot of gnarly implementation
| details and edgecases.
| ok123456 wrote:
| > implementing data structures in any language is hard.
|
| Why make it harder.
|
| > excellent standard library.
|
| The standard library is intentionally bare-bones. They
| don't want to maintain libraries in std, and want you to
| use crates.
|
| > wider ecosystem of libraries
|
| The quality of these is quite poor in a lot of cases.
| People literally make blog posts into crates.
| mtlmtlmtlmtl wrote:
| As someone coming from C I find the stdlib is fine. It
| has all the datastructures you need for the vast majority
| of code. It doesn't have very domain specific things like
| the kind of structures a text editor might use, for
| instance. That's fine.
|
| As for the quality of crates, yes, this is the case in
| any language. Using a library includes the responsibility
| of making sure the quality is up to scratch. This is not
| unique to Rust.
| antonvs wrote:
| > Why make it harder.
|
| To achieve static memory safety.
|
| If you don't need or want that, you're probably better
| off sticking to other languages. Although hopefully, not
| something like C or C++ which the US government now
| advises against using for security reasons.
| howinteresting wrote:
| The simplest data structures are pairs (A, B) and
| Option<T>.
| ok123456 wrote:
| Wouldn't call those data structures. Those are data
| types.
| howinteresting wrote:
| They are structured data. The restriction of the term
| "data structures" to what's asked in interview puzzles is
| ridiculous IMHO.
|
| Edit: and even among "interview puzzle data structures",
| stacks and queues have much simpler semantics than linked
| lists.
| codedokode wrote:
| As I understand, in low-level languages the concept of
| ownership exists anyway, no matter whether the language
| allows to declare it explicitly or not. Rust just makes you
| write it out explicitly.
| tmtvl wrote:
| The only concept of ownership that exists in low level
| languages is that the kernel owns memory and gives your
| program a chunk of it. Aside from that I think the closest
| equivalent concept is the system break, but that just
| determines where in memory your stack and heap are divided.
| ok123456 wrote:
| Yes ownership exists, but the semantics of Rust's automatic
| ownership system are different as they're enforced as a
| linear type.
| fleventynine wrote:
| > Even the most trivial singly linked lists....
|
| Uh, a singly linked list is trivial to implement...
| struct LinkedListNode<T> { value: T, next:
| Option<Box<LinkedListNode<T>>>, }
|
| Any data structure where chunks of heap memory are owned by a
| single pointer (red black trees, singly-linked lists,
| vectors, deques, circular queues, etc) can be represented
| easily in safe rust.
|
| Implementing a double-linked list is where things get tricky,
| as the nodes don't have a singular owner.
| kapolos wrote:
| Imho, Rust is not hard as in "high complexity hard", but it
| _is_ hard as in "must practice to get good at".
|
| All the little rules and new concepts add up and in the
| beginning it can be frustrating to have the compiler
| complaining. On the plus side, it's like a motorcycle - it
| doesn't take long to drive it safely & efficiently.
|
| Learning Rust is fun, I wholeheartedly suggest it even if you
| don't end up using it at work.
| pitaj wrote:
| I don't think motorcycles are a great analogy. They're way
| more dangerous for the driver than a car and you have to be
| constantly vigilant about your surroundings.
| vladvasiliu wrote:
| Yeah. If you start to get a bit too confident for your
| level, you'll just get yelled at by the compiler instead of
| ending up in the ER (if you're still breathing).
|
| But I suppose the analogy is more along the lines of "it
| can be intimidating at first, but you can quickly figure
| out how to use it reasonably well".
| kapolos wrote:
| You are right, I should have found a better one. I was
| between "bicycle" and "motorcycle" and I felt that bicycle
| would imply that learning is a breeze, so I went with
| motorcycle.
| insanitybit wrote:
| Unless you're doing something tricky, this is basically it. If
| you want to implement data structures like cyclic graphs or
| doubly linked lists things could be trickier. Sometimes people
| struggle with async because they dive right into that early and
| it can be a bit tricky if you use async + closures and don't
| know what you're doing.
| howinteresting wrote:
| The biggest thing for me was not so much the ownership rules
| themselves but how to design your code structure around them.
| estebank wrote:
| I think this exactly it: the rules on their own are simple
| but their implications are far reaching and hard to recognize
| ahead of time until you practice writing code.
| oxff wrote:
| Borrow checking (lifetimes and references) are fairly easy for
| a beginner to Rust to grasp, I think it is basically a meme at
| this point that this stuff is hard. Entirely different thing if
| you are making some kind of async library though, that is when
| you will run into advanced gotchas.
|
| Rather than a nice steep curve, its more like a threshold
| function.
| mplanchard wrote:
| I came to rust mostly from higher level languages, and I didn't
| have as much of a hard time with lifetimes as I did with
| dynamic dispatch via trait objects. Lifetimes can certainly get
| hairy, but it's easy to get around them when you're learning by
| cloning a value, wrapping it in an Arc, or whatever. I have had
| multiple times where I wanted to use dynamic dispatch and
| discovered after a few days of work that my idea wouldn't work
| for one reason or another. Mostly this came down to some
| limitations on what trait objects can and can't do, but it has
| mostly ceased to be a problem now that I understand those
| limitations better.
| KingOfCoders wrote:
| You didn't have a hard time with the borrow checker because
| you used the Rust GC? Was that the argument?
|
| Actually I left Rust and moved to Go although I love Rust
| much more because every struct ended up sprinkled with Arc.
| pclmulqdq wrote:
| Cloning values and using Arc to wrap structs carry a huge
| performance costs. It's pretty easy to write correct Rust.
| It's a lot trickier to write fast Rust.
|
| That's where the learning curve started to get very steep for
| me.
| fbdab103 wrote:
| Is the performance difference meaningful? I write Python,
| so I suspect even poorly ported Rust will outperform
| artisanally crafted Python.
| pclmulqdq wrote:
| Yes. Most of the production use cases for Rust are aimed
| at C, C++, and Go users. In my past experience, even
| poorly-written Go tends to outperform poorly-written Rust
| for many tasks, not to mention C or C++.
|
| You're not exactly the target market if you're writing
| python.
| fbdab103 wrote:
| But that is kind of my point. There are plenty of reasons
| to use Rust that have nothing to do with performance. My
| brief toe-dip into the Rust world loves the static types,
| good dependency management, and single executable
| deployment. That it is faster than my standard language
| is just the cherry on top.
| pclmulqdq wrote:
| The unfortunate reality for many Rust fans is that a lot
| of people would prefer to use a less complicated language
| when performance doesn't matter.
|
| That Rust program you spent a day golfing to make
| beautiful use of iterators? Your friend wrote it in go in
| 15 minutes.
|
| They also get static types, good dependency management,
| and singe executable deployment. Cython + mypy basically
| gives you that with Python.
| tmtvl wrote:
| Yeah, but Python is the slowest language ever. I think
| that a decent language like D or Common Lisp would
| outperform poorly written Rust, and they're easier to
| handle.
| estebank wrote:
| It really depends on what you're building whether that perf
| cost is problematic or not, and usually it isn't. If 90% of
| your code is clean Rust and the last 10% outside of the
| critical path is a straightforward clone or Arc, then I see
| no reason not to go that way.
| ninkendo wrote:
| > Mostly this came down to some limitations on what trait
| objects can and can't do, but it has mostly ceased to be a
| problem now that I understand those limitations better.
|
| Care to recount what some of those misunderstandings were?
| I'm casually interested in Rust but only really observe from
| afar, since most of my day job is Swift. Don't get me wrong,
| Swift has some odd limitations around protocols (closest
| equivalent to traits) that may be similar, but I'm curious to
| see what some common pitfalls may be with Rust traits.
| protortyp wrote:
| In my experience it just gets really dirty when you want to
| work on a single data structure (like a vector) in a threaded
| way.
| insanitybit wrote:
| Interesting, I feel like "share vector across threads" is an
| area that rust excels in. There's `split_at_mut` and `rayon`,
| and now with GATs you should be able to create a lending
| iterator too.
| protortyp wrote:
| Hm interesting, I have to look into GATs then. Anyhow it
| also got easier with scoped threads. But doing it the old
| way was always a pain point for me.
| loeg wrote:
| I found a few things a little difficult. First, the compiler is
| not actually as smart / accepting of valid borrow patterns as
| should abstractly be possible. Things like borrowing different
| subfields of a struct in different and nonconflicting ways to
| different subroutines. This got a lot better in recent memory
| with non-lexical lifetimes but I think is still a problem.
|
| Two: splitting mut borrows. It's reasonable to take a mut
| borrow of some resource and divide it into two independent
| borrows of exclusive components. Think non-overlapping
| subarrays, or independent struct members. The language does not
| really provide this for you, but it is safe. (There are some
| APIs like this but last time I checked they didn't cover all
| usecases.)
|
| Structs containing a borrow are just weird and annoying to work
| with. Lifetime parameterization everywhere is verbose and it's
| difficult to determine where you've made a mistake. The syntax
| for describing lifetime relationships is non-obvious to me.
| bobbylarrybobby wrote:
| For someone looking for an example of this, here's a SO post:
| https://stackoverflow.com/questions/74592882/extend-a-
| string...
|
| Tl;dr Rust can't distinguish between a `Vec` whose length is
| mutable (which might need to reallocate) and one whose
| elements are mutable (which can provide mutable references to
| its elements but will never have to move them), so it
| prevents mutation in a case where it would be safe.
| zozbot234 wrote:
| Isn't the latter just a mutable slice?
| estebank wrote:
| > There are some APIs like this but last time I checked they
| didn't cover all usecases.
|
| This refers to[1] <&mut
| [T]>::split_at_mut(usize) -> (&mut [T], &mut [T])`
|
| used as let (first_42, rest) =
| mutable_slice.split_at_mut(42);
|
| but you can see that the inner logic is just a bit of pointer
| twiddling[2] let len = self.len();
| let ptr = self.as_ptr(); // SAFETY: Caller
| has to check that `0 <= mid <= self.len()` unsafe
| { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), len
| - mid)) }
|
| [1]: https://doc.rust-
| lang.org/std/primitive.slice.html#method.sp...
|
| [2]: https://doc.rust-
| lang.org/src/core/slice/mod.rs.html#1641-16...
| loeg wrote:
| Yes, exactly. I was using this for zero-copy serialization
| into a buffer. At the time, I don't believe that API had
| been stabilized yet.
| estebank wrote:
| That method has been around since 1.0 (as documented in
| the source code). Were you using Rust before 2015? If so,
| _a lot_ has changed :)
| loeg wrote:
| No, post-1.0. I don't remember exactly why I had to roll
| my own with unsafe, but it was essentially the same
| thing.
| MuffinFlavored wrote:
| Having to clone a String every time you send it around is
| "confusing" if you come from a C char* pointer background.
|
| You can dereference it to &str but I'm pretty sure that
| introduces weird "lifetime" &'a or whatever errors in most
| places (when you are first learning to write Rust that is)
|
| same for structs, I typically just derive Clone. Kind of gross
| but for hobbyist projects where I want to "move fast" (coming
| from node.js so it's hard to not treat Rust like a "scripting"
| language), it suffices.
| revskill wrote:
| Yes, i'm at awe when seeing .to_ref, to_owned,... and a bunch
| of alien methods, too.
| sidlls wrote:
| Well, the blog examples are quite trivial.
|
| Take a look at the standard hashmap implementation
| (https://doc.rust-
| lang.org/src/std/collections/hash/map.rs.ht...). Notice the
| lifetime annotations everywhere. This is a relatively basic
| data structure, but it has a ton of visual noise due to the
| constraints of the lifetime and borrow model, and programmers
| must know, understand _and be able to reason about_ these
| constraints when using this data structure.
|
| Now imagine a case where you need to operate on values with two
| (or more) different lifetimes (by definition, all must live _at
| least_ as long as the one with smallest lifetime, but in
| practice they all can and will have different lifetimes). Now
| you have ` 'a` _and_ ` 'b` (and perhaps more) everywhere *and*
| developers must now reason about that. (random example pulled
| from a popular networking crate: https://github.com/tokio-
| rs/tokio/blob/718d6ce8cac9f2e081c0a...)
|
| It isn't trivial to pick up from scratch, especially if one
| comes from a much higher level language (C#, Java, python,
| etc.). This is true even for people who are very experienced
| writing high-quality, durable, and safe code in other languages
| (e.g., C++) without the help of a compiler, because the
| ownership and lifetime model are both different and compiler-
| enforced.
| puffoflogic wrote:
| > Now you have `'a` and `'b` (and perhaps more) everywhere
|
| Only if you're a bad rust programmer. Lifetime variables can
| and should be a descriptive identifier, just like literally
| any other variable. Complaining that there's lots of 'a and
| 'b around is like complaining that your code has lots of x,
| y, z variables and you can't keep them all straight... It's
| not a language problem.
| howinteresting wrote:
| Lifetime variance often makes it so that more descriptive
| names are misleading.
| sidlls wrote:
| It's a "problem" in the sense that it's additional syntax
| with critically important meaning to the understanding of
| the code. The descriptiveness of the labels may help, but
| it won't eliminate the additional cognitive overhead
| required to mentally parse and reason about the code.
| cwzwarich wrote:
| To be fair to people using 'a/'b-type variables:
|
| 1) They are used pervasively in the standard library and
| its documentation.
|
| 2) Due to lifetime subtyping and implicit bounds,
| descriptive names may be inaccurate. For example, if I have
| an Ast that contains slices with a lifetime of the source
| code, I might decide to write Ast<'source>. However, what
| do I do if I then have a reference to such a thing? Do I
| add another lifetime parameter, e.g. &'ref Ast<'source>? If
| I am not going to be returning any of the 'source-lifetime
| slices, this additional parameter may be redundant. In such
| a case, do I write &'source Ast<'source> or &'ref
| Ast<'ref>? Both of those names are incorrect. Do I keep
| around an extra lifetime parameter to get the correct names
| (and be more future-proof), or do I just suck it up and use
| 'a?
| fbdab103 wrote:
| Nearly every Rust tutorial/blog/reference I have come
| across uses single letter names.
| puffoflogic wrote:
| This is a non-problem, or at least a non-unique problem.
| It is the exact same thing as using variables as function
| parameters. Sometimes what the variable means in one
| place is different from another place, so... you use
| different names. This surprises no one except maybe
| first-time programmers. Sometimes a variable means
| nothing and we can give it a single-character name, but
| then we shouldn't have a bunch of them to get confused
| by.
| [deleted]
| mtlmtlmtlmtl wrote:
| I think Rust is a lot easier when you already have decent
| experience with C. In C you have to reason about ownership and
| lifetimes too, the only difference is it's all implicit.
| Knowing C also helps you a great deal in the cases where unsafe
| is either neccessary or just the best solution. Programmers who
| haven't touched C might be very hesitant to even consider using
| unsafe.
|
| Other than that, it's been my experience that lifetimes come up
| very rarely or even never for a large range of programs. But
| someone coming from Java/C# where almost everything is a
| reference might struggle more than others because these
| languages lend themselves to constructing large object graphs
| that are annoying to do in Rust. You have to take a different
| approach, keeping object graphiness to a minimum where
| possible.
| marcosdumay wrote:
| That is pretty much it; it is way harder to learn to fit
| withing those constraints than you are assuming; and it has
| some very unintuitive consequences that won't appear on 99% of
| your code, but are very hard to deal with on the other 1%.
| pastaguy1 wrote:
| Would there be any value in a GC'd language where you had the
| option to explicitly call do_gc_now()? Is this functionality
| already out there and just not popular? I haven't spent a ton of
| time in these languages, so forgive the naivety. Again, naively,
| this seems like it would be a good compromise between what GC
| offers but near-determinism when you want it.
|
| I guess Rust and C++ also "pause the world", it's just
| predictable when it happens. It seems kind of arbitrary in some
| ways, like maybe I don't want the "world pause" at the end of
| this scope. There are ways around it obviously, but you start
| language-wrestling at that point.
| eloff wrote:
| You can often do this, although some runtimes treat it only as
| a hint and may ignore it (usually what you want). Go has some
| pretty strong guarantees on how long it will stop the world
| for, which makes it much less of an issue. But the best pause
| is still no pause, which means no GC.
| tsimionescu wrote:
| Virtually all GC languages have this option, but it is rarely
| better overall than the default algorithm for deciding when to
| do it.
|
| The biggest problem with GC is that it is often global, and a
| simple call to invoke the global GC doesn't usually help from a
| local scope. There are some arena-based allocators (I believe
| OCaml's GC uses this strategy) where this may be more
| beneficial.
|
| But the question always looms: if there is not enough memory to
| serve an allocation invoked from a hot loop, what should the
| program do?
|
| Note also that in advanced GCs, such as .NET or the JVM, a hot
| loop that doesn't allocate will often not need to be stopped by
| the GC at all. There are even GCs (all proprietary as far as I
| know) that guarantee a fixed pause time, so that they can be
| used in real-time workloads - Azul's JVM GC has this option for
| example.
| kapolos wrote:
| > I guess Rust and C++ also "pause the world"
|
| Rust does not ship a garbage collector with your binary, so
| there is nothing to pause your code.
|
| When the compiler adds those drop() statements, they just free
| the respective memory at runtime. There is no need to pause
| your application to do that.
|
| The garbage collector needs to pause the application because it
| takes time to calculate in runtime which parts of the
| application memory are safe to clean. If the application was
| running in the meantime, there's no guarantee that the blocks
| it marked as "safe" are actually still so.
| connicpu wrote:
| "pause the world" usually refers to garbage collectors having
| to stop all threads, whereas in Rust and C++ allocation/freeing
| of memory does not have to make any threads other than the
| current one wait (unless your memory allocator has global locks
| and multiple threads are trying to use it)
| nicoburns wrote:
| > Is this functionality already out there and just not popular?
|
| Yep. Node.js has this for instance (you have to enable it with
| a command line flag, but it's easy enough to do). I imagine
| most GC languages have a similar option.
| oconnor663 wrote:
| > Traditionally, you either have to manage the memory yourself (a
| la C), or pass the burden down to a run-time feature of the
| language - heroically called "the garbage collector".
|
| I think it's worth mentioning that C++ manages heap memory the
| same way Rust does, with destructors (Drop, in Rust). The story
| is a bit complicated with the new/delete operators only being
| deprecated recently and lots of legacy code sitting around, but
| vector and string work the same way, and those have been in
| common use for decades. The difference isn't the memory
| management strategy itself, but rather that Rust catches all our
| mistakes when we retain pointers to destroyed values. (Move
| semantics are also quite different, but that's a separate idea I
| think.)
| pjmlp wrote:
| Good luck telling to most enterprise developers that new and
| delete are deprecated, specially when ISO C++ makes zero
| reference to it.
___________________________________________________________________
(page generated 2022-11-27 23:01 UTC)