Why does this Rust program leak memory?

แชร์
ฝัง

ความคิดเห็น • 153

  • @khoda81
    @khoda81 ปีที่แล้ว +252

    Knowing about fragmentation is one thing, but seeing it happen in practice is so useful! Thanks a lot

    • @fasterthanlime
      @fasterthanlime  ปีที่แล้ว +51

      That's why I was so excited when it landed in my inbox! I often struggle to find good real-world examples of concepts and this was a gift ☺️

    • @monad_tcp
      @monad_tcp ปีที่แล้ว +3

      I'm impressed programming language runtimes are still letting the OS manage the buckets of memory allocation instead of always over-commiting pages and doing the correct thread-off that saves kernel invocations for malloc buckets.

    • @blinking_dodo
      @blinking_dodo ปีที่แล้ว

      @@fasterthanlime would this fragmentation be exploitable?

    • @94Quang
      @94Quang ปีที่แล้ว

      @@blinking_dodoyes, if there would be any kind of remote code execution exploitation and my goal would be to slow the system down, this would be a funny thing to do :)

  • @faeancestor
    @faeancestor ปีที่แล้ว +47

    your content always plants a massive smile on my face ; you have such a kind soul ; thank you for this content !!!!!
    !!!!!!!!

  • @abdelhakimakodadi3073
    @abdelhakimakodadi3073 ปีที่แล้ว +21

    (5:44) Je malloce, tu mallocs, vous m'allocez lol

  • @jarrednicholls
    @jarrednicholls ปีที่แล้ว +27

    An allocator backed by a memory arena/slab (if one knows the amount of memory they will need) is a good “have your cake and eat it too” solution to avoid fragmentation and maintain low latency.
    Your deep dive here was very very well done! Super valuable and approachable by all experience levels. Keep up the great work!

  • @Jplaysterraria
    @Jplaysterraria ปีที่แล้ว +99

    I've had to implement malloc/free for a Uni course, all the ways you can do things is very interesting!
    It is also interesting to debug... I was using rust at first, but even `printf` allocates memory, which is great if your `malloc` is crashing :)

    • @edgeeffect
      @edgeeffect ปีที่แล้ว +2

      Sounds like a Jacob Sorber video. ;)

    • @emmavdev
      @emmavdev ปีที่แล้ว

      Thats unfortunate yea

    • @shambhav9534
      @shambhav9534 ปีที่แล้ว

      Well, you could've easily worked around using Rust's printf.

    • @Jplaysterraria
      @Jplaysterraria ปีที่แล้ว +12

      @@shambhav9534 C's printf has the same problem, you have to use fprintf(stderr, msg).
      The problem isn't that you can work around it, is that you have a crash, so you use printf to see where it crashes, but it seems to crash before any printf (because allocating memory is what crashes the system)

    • @ccgarciab
      @ccgarciab ปีที่แล้ว +14

      "I have no tools because I've destroyed my tools with my tools"
      - James Mickens, The Night Watch (recommended)

  • @MarcusBrito
    @MarcusBrito ปีที่แล้ว +5

    This was great; definitely something that will stay with me, and remember when designing solutions.

  • @zactron1997
    @zactron1997 ปีที่แล้ว +31

    Another great example of why I love Rust: the control to choose whether to care about problems like this or not. For the type of work I do, I'll have RAM to spare, so I can afford to be a little more implicit with my management. But for some stuff, I can also go the complete opposite direction and maximize every last byte of memory.

    • @nickwilson3499
      @nickwilson3499 ปีที่แล้ว +6

      yeah the choice of leaking memory is always handy lmao

    • @zactron1997
      @zactron1997 ปีที่แล้ว +17

      @@nickwilson3499 as the video explains tho, it's not a memory leak, it's a worst-case fragmentation.in a more practical program, all those gaps in memory would be filled with smaller data structures anyway.

    • @0LoneTech
      @0LoneTech ปีที่แล้ว

      You mean like the Allocator template argument in C++ std::unordered_map? Looks kind of like Rust only does it at a global level. The example here also shows it making thousands of little allocations when populating a hashmap of known size, which would have been possible to preallocate unboxed. I'm also not seeing the strategic options of e.g. Gregory Collins' hashtables package. This is the sort of tuning I'd expect to see in Chapel, but its associative maps appear fairly limited too.

  • @p0lyglot
    @p0lyglot ปีที่แล้ว +29

    See this is why we build compacting garbage collectors ;) It's not just for the improvement in cache locality...

    • @fasterthanlime
      @fasterthanlime  ปีที่แล้ว +20

      Someone in chat rightfully pointed out we probably could've gotten out of this one with an arena, but I agree compacting GCs are the generic solution to this.

    • @mxbc_ebk5086
      @mxbc_ebk5086 ปีที่แล้ว +8

      Then your GC leaks even more memory 🤡

    • @pfeilspitze
      @pfeilspitze ปีที่แล้ว +10

      Well, GCs don't solve memory leaks either. And whether they actually provide *useful* cache locality is kinda a crapshoot.
      GCs are great sometimes, but they're not magical either. They solve use-after-free, but memory-use-after-free is arguably the easiest thing to solve. (After all, I need features to not use-after-close my file descriptors and use-after-FIN my socket handles, and use-after-unlock my mutexed data and ...)

    • @vanjazed7021
      @vanjazed7021 ปีที่แล้ว +1

      @@pfeilspitze Moving garbage collectors specifically fix fragmentation too.

  • @khuiification
    @khuiification ปีที่แล้ว +6

    I fucking love your videos. Especially rust ones. Amazing! I feel like i've always had a hunch about this as my mental model, but seeing it concretely explained is so good.

  • @HyperFocusMarshmallow
    @HyperFocusMarshmallow ปีที่แล้ว +3

    This was very interesting. I followed it roughly but I probably wouldn’t ace test questions about this from just watching the video.
    It’s all about trade offs. The thing is, it quickly becomes more complicated than what I would want to reason about when writing most programs.
    Since this is on top of libc-malloc all these issues would be there in c as well. But there are so many levels of indirection. Operating system, allocator, maybe garbage collector and then language abstractions.
    The levels of indirection most often saves you from having to deal with really stupid stuff like implementing your own paging in your little app that has a bunch of data in it.
    Sometimes it seems like you want to talk directly to the hardware but the second you want to run anything on multiple different systems all the levels of abstraction softens the rough edges.
    It’s just not clear at what point you would want to make choices about these kinds of issues. And it’s very hard to make general automatic defaults.
    I guess the reasoning should be, the defaults are very good and if you really run into trouble, profile and pick the lowest hanging fruit.

  • @hikson7
    @hikson7 ปีที่แล้ว +1

    Great content! Loved seeing a light deep-dive into kernel at work (+bonus with Rust!) with satisfying explanation

  • @dexterman6361
    @dexterman6361 ปีที่แล้ว +1

    Thank you. This was a really detailed, and highly interesting walkthrough. I really would like to thank you for sharing this.
    Saved to my library
    you have a good day smart kind human

  • @Erhannis
    @Erhannis ปีที่แล้ว +30

    Ahh, ok - so not a leak like, "memory is mysteriously disappearing and only the OS knows where", but rather, "memory inefficiently allocated". I was a little worried going into this that the promises I'd been told about Rust's memory safety would turn out to be disappointing lies, haha. Glad that's not the problem.

    • @fasterthanlime
      @fasterthanlime  ปีที่แล้ว +15

      Leaking memory wouldn't be unsafe though! There's even a method in the standard library for that: Box::leak

    • @Erhannis
      @Erhannis ปีที่แล้ว +6

      @@fasterthanlime I mean, if your apparently-correctly-written program, in normal usage, gradually grows in memory size until it (or the system) is forced to quit, that sounds fairly unsafe to me. Not as bad as leaking sensitive info or corrupting data, granted.

    • @jcdyer3
      @jcdyer3 ปีที่แล้ว +6

      @@Erhannis Rust's memory safety promises makes no guarantee that that won't happen.

    • @Erhannis
      @Erhannis ปีที่แล้ว

      @@jcdyer3 How so? My understanding was that things have one owner at any given time, and once execution leaves the scope containing the object, or the owner is collected, the thing is collected, too. Without invoking explicitly unsafe behavior, how would you permanently leak memory?

    • @aedieal
      @aedieal ปีที่แล้ว +3

      @@Erhannis You never permanently leak memory, as it would be reclaimed at program exit, but you can lose track of your objects and keep allocating more without letting the old ones go our of scope

  • @altairbueno5637
    @altairbueno5637 ปีที่แล้ว +4

    Arena allocators such as Bumpalo in rust mitigate this issue

    • @fasterthanlime
      @fasterthanlime  ปีที่แล้ว +10

      Please no spoilers, I'm still working on that one

  • @Erhannis
    @Erhannis ปีที่แล้ว +7

    "I didn't hide my email address well enough, and received a fascinating puzzle." ...Good end???

  • @desuburinga
    @desuburinga ปีที่แล้ว

    Really appreciate these technical deep dives! Thanks!

  • @Verrisin
    @Verrisin ปีที่แล้ว +1

    well ... all I can say it: Another reason I'm glad I can use compacting GC at work, instead worrying about stuff like this. It's INTERSTING, yes. But I don't have time for puzzles, when a client expects results...

  • @AlwaysStaringSkyward
    @AlwaysStaringSkyward ปีที่แล้ว

    I learned TONS from this. Thank you!!!

  • @TheBrazilRules
    @TheBrazilRules ปีที่แล้ว +1

    "It does not use very much memory at all" "1GB"
    Me:"WTF"?

  • @miketube208
    @miketube208 ปีที่แล้ว +5

    pmap -X gives nicer output than cat /proc//maps :)

  • @Dygear
    @Dygear ปีที่แล้ว

    Excellent work as always Amos!

  • @getoutofhereinternet
    @getoutofhereinternet ปีที่แล้ว +1

    A truly herculean effort

  • @shashanksharma21
    @shashanksharma21 ปีที่แล้ว

    this was enlightening! thank you!

  • @oyewodayo
    @oyewodayo ปีที่แล้ว

    Write a book. Don't waste time on this. You're a good teacher with good mastery.

  • @mikhailmikheev8043
    @mikhailmikheev8043 ปีที่แล้ว

    Thank you very much for the vid!

  • @flippert0
    @flippert0 10 หลายเดือนก่อน

    Should be worthwhile to note that Rust's memory safety guarantees are about dangling pointers, double free and such, but not about memory leakage. Structures with mutual pointers between instances cannot be freed easily, must use "Weak" references.

  • @l-const
    @l-const 17 วันที่ผ่านมา

    hey @fasterthanlime is there a way to know if it is a real memory leak? did you try valgrind or heaptrack and what did they report? I am having a similar issue that is reported as a leak by these tools and I am not sure if it is. Thanks for this video, learned a lot.

    • @fasterthanlime
      @fasterthanlime  11 ชั่วโมงที่ผ่านมา

      It's really hard to say without taking a look at the codebase itself! Most people's definition of "is it a leak" is "is it a problem in practice / does it keep growing". Otherwise it's just.. memory usage.

  • @AJMansfield1
    @AJMansfield1 ปีที่แล้ว

    How would this fare using the MESH allocator? That one that was going around a few years back that used some virtual memory tricks to let it merge together partially-empty memory pages if each page's holes overlapped with the other's data.

    • @fasterthanlime
      @fasterthanlime  ปีที่แล้ว

      I'm planning on doing a video about arenas & the MESH allocator :) Excited for that.

  • @Otakutaru
    @Otakutaru ปีที่แล้ว +10

    What I take away from all this: "Phew!... Thought for a moment it was Rust's fault". Also, don't litter, keep it solid

  • @9SMTM6
    @9SMTM6 ปีที่แล้ว +1

    Yessss, gonna feel nice for guessing fragmentation, even if I had no idea why and had to watch the explanation parts a few times:).
    Regarding what to do about it, I'm not certain that's generally applicable - tho it seems so - , but in this case you had "interlacing lifetimes" of memory allocations as root cause, no? Method 2 doesn't interlace them and because of that that free memory isn't used.
    Another solution should be separate allocators for the separate uses of course.

  • @felipellrocha
    @felipellrocha ปีที่แล้ว

    Is the example code available somewhere? I would love to dive into it

  • @Bvngee
    @Bvngee ปีที่แล้ว

    This was fascinating!!!

  • @sysop073
    @sysop073 ปีที่แล้ว +1

    I thought Rust had the ability to rearrange memory, and that's what Pin prevented. Have I totally misunderstood the purpose of pinning?

    • @fasterthanlime
      @fasterthanlime  ปีที่แล้ว +2

      Rust doesn't have a compacting GC that will move memory by itself. However, Rust code can move values, which would break async code. Async functions are self-referential state machines, and Pin makes it impossible to move them.

    • @Verrisin
      @Verrisin ปีที่แล้ว

      @@fasterthanlime I'm still confused what is "move values" if it doesn't rewrite pointers into it... or also, disallow moving values if there exist references into it, Pin being kind of implicit by that?

  • @arrux4822
    @arrux4822 ปีที่แล้ว

    Awesome vid!

  • @nometutentegiapreso
    @nometutentegiapreso 17 วันที่ผ่านมา

    So it's more like unintentional memory overprovisioning, rather than a memory leak?

    • @fasterthanlime
      @fasterthanlime  11 ชั่วโมงที่ผ่านมา

      More like fragmentation, yeah!

  • @fntr
    @fntr ปีที่แล้ว

    what vscode extensions are you using?

  • @andrewdunbar828
    @andrewdunbar828 ปีที่แล้ว

    I wonder if Alice knows about this co-Alicing.

  • @shershahdrimighdelih
    @shershahdrimighdelih ปีที่แล้ว +1

    loved it

  • @bsm117532
    @bsm117532 ปีที่แล้ว

    Seems to me there should be a way to do this this uses 3 orders of magnitude less memory. Why or why not?

  • @monad_tcp
    @monad_tcp ปีที่แล้ว +2

    26:04 paying for drops to the operating system ? that's insane, we don't pay that with garbage collectors, there's a thread to do that so our current thread will run smoothly

    • @tesfabpel
      @tesfabpel ปีที่แล้ว

      It won't make a syscall every time a value is dropped... glibc's malloc and free only do so when the memory they have at disposal isn't enough, otherwise it's just simple bookkeeping... Also, having destructors run in a separate thread is a very BAD idea when having native resources... I had to fight C#'s GC because it didn't have to run the finalizer of a OpenGL-related object in a different thread than the one it was created.

    • @monad_tcp
      @monad_tcp ปีที่แล้ว

      @@tesfabpel oh yes "simple" book keeping.
      It's not that simple either way.
      It's usually a sparse linked list or some red/black tree. I'm some cases it's much more complex than that with buckets and lots of things because they try really hard to avoid fragmentation.
      Meanwhile GCs take a much larger heap block from the OS and manage it themselves. And they can (usually) just do heap compaction and hardly suffer from fragmentation.
      They also pay much less in syscalls.
      As committing pages is basically free, there's no reason why you wouldn't prealloc a huge amount of heap, unless you're worried about fragmentation of the heap of the process.
      The real difference between GC and alloc/dealloc inline is where you pay the cost, on allocating or when deallocating.
      With manual memory management you pay nothing when deallocating, but allocation isn't cheap or even that predictable.
      GCs are ridiculously fast on allocation, it's not even a joke. It's as cheap as a barrier and a pointer increment.
      And they have a good side effect, no memory crashes.
      I find it funny that people think GCs made things slow when it fact it's always double dispatching and excessive use of objects. (which causes allocations that have to be paid either way).
      But GCs make it very evident the cost as they have their thread spinning and doing things. Meanwhile in C++ you happily pay constructor calls and never notice. But deallocating is "free", pun intended, just let it leak...

    • @monad_tcp
      @monad_tcp ปีที่แล้ว

      @@tesfabpel also what you were doing to C#, I never had that problem of having to free things in the same thread.
      Well, don't use destructors for that, they're meant to managed objects, not unmanaged system resources.
      The fact that you can use memory management to manage other kinds of resources is a impedence mismatch on programming languages.
      GCs don't replace RAII on system resources, ironically. You just have to implement Disposing(false) properly and sprinkle "using (opengl) {}" everywhere.
      And I think that the fact C++ uses RAII for everything is a mistake that complicates the runtime.
      C# IDisposable isn't great, it's one of the few things the Java/JVM has better.
      But I bet they didn't had to deal with COM compatibility, so there's a reason for the IDisposable design.
      Or even simpler, use a Object Pool class and reference count objects, like the COM does.
      You're not required to use the GC for everything. Sometimes doing things manually is fine. Just do a proper ".Dispose()" and suppress collection. Do it from the thread you want to dispose, don't fight the GC. It's simple as that.
      You probably were using the IDisposable wrong. I think you have to use a mashall reference and run your Thread render in the STA apartment if you really want the GC to fire destructors there.
      What you're doing is highly unusual on that environment. That's not a fault of the GC but of OpenGL being stupid. (as usual)

  • @tacticalassaultanteater9678
    @tacticalassaultanteater9678 ปีที่แล้ว

    It's like glibc assumes a variable page size OS

  • @severinheugabler
    @severinheugabler ปีที่แล้ว

    What is the name of that font in VSCode?

  • @Zooiest
    @Zooiest ปีที่แล้ว

    How differently would it behave on Windows?

    • @fasterthanlime
      @fasterthanlime  ปีที่แล้ว

      Hard to tell since it has s completely different allocator, but the basic idea is the same. Wouldn't be too hard to find out, if you're curious!

  • @baxiry.
    @baxiry. ปีที่แล้ว +1

    I have used a lot of C and C++ applications. I haven't had a memory leak.
    I used two Rust apps. One of them was leaking memory

  • @returnzero7492
    @returnzero7492 ปีที่แล้ว

    What font do you use? ;)

  • @nathanoy_
    @nathanoy_ ปีที่แล้ว

    what VSCode theme are you using?

    • @fasterthanlime
      @fasterthanlime  ปีที่แล้ว

      Usually GitHub light / GitHub dark

    • @nathanoy_
      @nathanoy_ ปีที่แล้ว

      @@fasterthanlime thank you for the reply!

  • @stevenhe3462
    @stevenhe3462 ปีที่แล้ว

    The point is not to allocate those little vecs.

  • @kawsxj681
    @kawsxj681 ปีที่แล้ว

    is that a custom font for your vsc?

  • @begga9682
    @begga9682 ปีที่แล้ว

    Double it and give it to the next person

  • @actuallyasriel
    @actuallyasriel ปีที่แล้ว

    Wait, wouldn't the plural of Linux be "Linuces?"

  • @srgi
    @srgi ปีที่แล้ว

    Why the heck indeed

  • @Morimea
    @Morimea ปีที่แล้ว +1

    Cool low level stuff.
    Lack of actually useful tools - everyone on "big" tasks playing with ML/AI/Clouds...
    And there is just no reward for making small "tools" that actually doing something useful now.

  • @Whatthetrash
    @Whatthetrash ปีที่แล้ว

    As someone who's now learning Rust, a title like this is NOT encouraging. >_< LOL I thought Rust was supposed to save you from yourself in regards to memory safety.

    • @tomtravis858
      @tomtravis858 ปีที่แล้ว

      Memory leaks are actually memory safe.

  • @error200http
    @error200http ปีที่แล้ว

    dhat-heap is a very good memory profiler.

  • @cheaterman49
    @cheaterman49 ปีที่แล้ว +2

    Tu malloques ! xD

    • @fasterthanlime
      @fasterthanlime  ปีที่แล้ว +3

      Avec l'orthographe correcte et tout, c'est nickel

  • @punpck
    @punpck ปีที่แล้ว

    glad it's clickbait and not a real memory leak^^ if it was a real memory leak, memory still would be gone after clear or reset^^ so it doesn't leak memory but how 3rd method was implemented is not good. Nonetheless, great video 👍

  • @porky1118
    @porky1118 ปีที่แล้ว

    Are there really people who find inlay hints useful and not confusing?

  • @monad_tcp
    @monad_tcp ปีที่แล้ว

    30:42 garbage collectors and memory compression !
    check mate

    • @fasterthanlime
      @fasterthanlime  ปีที่แล้ว

      This is literally the next thing mentioned in the video

  • @phenanrithe
    @phenanrithe ปีที่แล้ว

    To be frank, it's a bit confusing to watch. What's the trim code, what's the reset code? I see short glimpses of code that jump from left to two columns, then back to left, then split to show the graph... gah! Then it goes straight to the measurements without knowing what any of those actually does... that's where you lost me. 😅

    • @fasterthanlime
      @fasterthanlime  ปีที่แล้ว +1

      The description has a link to the repository! That might help :)

  • @isaac_shelton
    @isaac_shelton ปีที่แล้ว

    ...so it doesn't leak memory at all, it just allocates inefficiently. Misleading title

    • @fasterthanlime
      @fasterthanlime  ปีที่แล้ว

      The title is the question I was asked - the video elucidates it. If every commenter being salty about titles whilst still learning something useful in the video spent that energy elsewhere, we would have solved the climate crisis already.

  • @IanMaayrkas
    @IanMaayrkas ปีที่แล้ว

    Ohno, it's MADV_DONTNEED :O
    th-cam.com/video/bg6-LVCHmGM/w-d-xo.html#t=58m23s

  • @EzequielRegaldo
    @EzequielRegaldo ปีที่แล้ว +2

    So we can go back to C++ ? Feels weird overcomplicated lang

    • @fasterthanlime
      @fasterthanlime  ปีที่แล้ว +11

      The video emphasizes at the end that this is something common to all memory allocators - only moving/compacting garbage collectors solve that problem generally.

    • @shambhav9534
      @shambhav9534 ปีที่แล้ว +5

      Sadly, you'd have the same problem in C++ too.

    • @EzequielRegaldo
      @EzequielRegaldo ปีที่แล้ว +1

      @@shambhav9534 thats why i preffer stay with C++, i dont see a real benefit changing

    • @error200http
      @error200http ปีที่แล้ว

      @@EzequielRegaldo It might be harder to debug in C++ since you'd have to write 10x more lines on code to get a grasp on what's going on.
      In Rust you just use dhat heap profiler. In C++ you frequently need to create tools yourself (from my experience)

    • @shambhav9534
      @shambhav9534 ปีที่แล้ว +4

      @@EzequielRegaldo For every problem that Rust doesn't solve, it solves a thousand others.

  • @gaurangshukla8235
    @gaurangshukla8235 ปีที่แล้ว

    Isn't this just a mediocre programmer writing stupid code? Do people really think you can completely ignore how memory works and still write efficient software?

    • @fasterthanlime
      @fasterthanlime  ปีที่แล้ว +6

      It's not - the example was golfed down from a real-world codebase to something small enough to study in isolation. A lot of people were stumped by exactly what was going on. Calling people mediocre and their code stupid doesn't make you look cool and isn't welcome on this comment section.

    • @gaurangshukla8235
      @gaurangshukla8235 ปีที่แล้ว +2

      ​@@fasterthanlime If the code was not critical in the first place then why are we talking about it? If it was indeed critical then whoever wrote this didn't know what they were doing. Also just because a code excerpt comes from a real-world codebase doesn't magically make it perfect. The code was a textbook example of memory fragmentation, it really is dumb.
      EDIT: After reading the code myself, I think mediocre was an understatement. It was super obvious from reading the code itself. Even the real-world code was awful. They were collecting an entire database to create the inverse_map, which is obviously a memory fragmentation issue. A commit fixes it *accidentally*, by trying to save memory by streaming instead of collecting the entire db.

  • @1111757
    @1111757 ปีที่แล้ว

    I'd really like to see you on @Computerphile! I think it would fit perfectly.

  • @stintaa
    @stintaa 10 หลายเดือนก่อน

    What font do you use?