Why does this Rust program leak memory?

  Рет қаралды 59,249

fasterthanlime

fasterthanlime

Күн бұрын

Пікірлер: 154
@khoda81
@khoda81 Жыл бұрын
Knowing about fragmentation is one thing, but seeing it happen in practice is so useful! Thanks a lot
@fasterthanlime
@fasterthanlime Жыл бұрын
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 Жыл бұрын
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 :)
@abdelhakimakodadi3073
@abdelhakimakodadi3073 Жыл бұрын
(5:44) Je malloce, tu mallocs, vous m'allocez lol
@faeancestor
@faeancestor Жыл бұрын
your content always plants a massive smile on my face ; you have such a kind soul ; thank you for this content !!!!! !!!!!!!!
@hikson7
@hikson7 Жыл бұрын
Great content! Loved seeing a light deep-dive into kernel at work (+bonus with Rust!) with satisfying explanation
@fasterthanlime
@fasterthanlime Жыл бұрын
Thanks so much!
@Jplaysterraria
@Jplaysterraria Жыл бұрын
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 Жыл бұрын
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 Жыл бұрын
@@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 Жыл бұрын
"I have no tools because I've destroyed my tools with my tools" - James Mickens, The Night Watch (recommended)
@jarrednicholls
@jarrednicholls Жыл бұрын
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!
@khuiification
@khuiification Жыл бұрын
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.
@p0lyglot
@p0lyglot Жыл бұрын
See this is why we build compacting garbage collectors ;) It's not just for the improvement in cache locality...
@fasterthanlime
@fasterthanlime Жыл бұрын
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 Жыл бұрын
Then your GC leaks even more memory 🤡
@pfeilspitze
@pfeilspitze Жыл бұрын
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 Жыл бұрын
@@pfeilspitze Moving garbage collectors specifically fix fragmentation too.
@MarcusBrito
@MarcusBrito Жыл бұрын
This was great; definitely something that will stay with me, and remember when designing solutions.
@dexterman6361
@dexterman6361 Жыл бұрын
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 Жыл бұрын
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 Жыл бұрын
Leaking memory wouldn't be unsafe though! There's even a method in the standard library for that: Box::leak
@Erhannis
@Erhannis Жыл бұрын
@@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 Жыл бұрын
@@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 Жыл бұрын
@@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
@zactron1997
@zactron1997 Жыл бұрын
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 Жыл бұрын
yeah the choice of leaking memory is always handy lmao
@zactron1997
@zactron1997 Жыл бұрын
@@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.
@HyperFocusMarshmallow
@HyperFocusMarshmallow Жыл бұрын
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.
@Erhannis
@Erhannis Жыл бұрын
"I didn't hide my email address well enough, and received a fascinating puzzle." ...Good end???
@Dygear
@Dygear Жыл бұрын
Excellent work as always Amos!
@desuburinga
@desuburinga Жыл бұрын
Really appreciate these technical deep dives! Thanks!
@shashanksharma21
@shashanksharma21 Жыл бұрын
this was enlightening! thank you!
@getoutofhereinternet
@getoutofhereinternet Жыл бұрын
A truly herculean effort
@altairbueno5637
@altairbueno5637 Жыл бұрын
Arena allocators such as Bumpalo in rust mitigate this issue
@fasterthanlime
@fasterthanlime Жыл бұрын
Please no spoilers, I'm still working on that one
@AlwaysStaringSkyward
@AlwaysStaringSkyward Жыл бұрын
I learned TONS from this. Thank you!!!
@mikhailmikheev8043
@mikhailmikheev8043 Жыл бұрын
Thank you very much for the vid!
@miketube208
@miketube208 Жыл бұрын
pmap -X gives nicer output than cat /proc//maps :)
@Verrisin
@Verrisin Жыл бұрын
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...
@TheBrazilRules
@TheBrazilRules Жыл бұрын
"It does not use very much memory at all" "1GB" Me:"WTF"?
@arrux4822
@arrux4822 Жыл бұрын
Awesome vid!
@Bvngee
@Bvngee Жыл бұрын
This was fascinating!!!
@oyewodayo
@oyewodayo Жыл бұрын
Write a book. Don't waste time on this. You're a good teacher with good mastery.
@monad_tcp
@monad_tcp Жыл бұрын
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)
@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.
@flippert0
@flippert0 11 ай бұрын
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.
@shershahdrimighdelih
@shershahdrimighdelih Жыл бұрын
loved it
@felipellrocha
@felipellrocha Жыл бұрын
Is the example code available somewhere? I would love to dive into it
@l-const
@l-const Ай бұрын
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 Ай бұрын
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.
@sysop073
@sysop073 Жыл бұрын
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 Жыл бұрын
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?
@fntr
@fntr Жыл бұрын
what vscode extensions are you using?
@alexkazimir3835
@alexkazimir3835 Ай бұрын
Very cool
@nometutentegiapreso
@nometutentegiapreso Ай бұрын
So it's more like unintentional memory overprovisioning, rather than a memory leak?
@fasterthanlime
@fasterthanlime Ай бұрын
More like fragmentation, yeah!
@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?
@Otakutaru
@Otakutaru Жыл бұрын
What I take away from all this: "Phew!... Thought for a moment it was Rust's fault". Also, don't litter, keep it solid
@severinheugabler
@severinheugabler Жыл бұрын
What is the name of that font in VSCode?
@9SMTM6
@9SMTM6 Жыл бұрын
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.
@andrewdunbar828
@andrewdunbar828 Жыл бұрын
I wonder if Alice knows about this co-Alicing.
@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!
@returnzero7492
@returnzero7492 Жыл бұрын
What font do you use? ;)
@fasterthanlime
@fasterthanlime Жыл бұрын
Iosevka
@kawsxj681
@kawsxj681 Жыл бұрын
is that a custom font for your vsc?
@fasterthanlime
@fasterthanlime Жыл бұрын
That's typeof.net/Iosevka !
@nathanoy_
@nathanoy_ Жыл бұрын
what VSCode theme are you using?
@fasterthanlime
@fasterthanlime Жыл бұрын
Usually GitHub light / GitHub dark
@nathanoy_
@nathanoy_ Жыл бұрын
@@fasterthanlime thank you for the reply!
@tacticalassaultanteater9678
@tacticalassaultanteater9678 Жыл бұрын
It's like glibc assumes a variable page size OS
@fasterthanlime
@fasterthanlime Жыл бұрын
?
@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.
@Morimea
@Morimea Жыл бұрын
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.
@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 👍
@baxiry.
@baxiry. Жыл бұрын
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
@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
@cheaterman49
@cheaterman49 Жыл бұрын
Tu malloques ! xD
@fasterthanlime
@fasterthanlime Жыл бұрын
Avec l'orthographe correcte et tout, c'est nickel
@error200http
@error200http Жыл бұрын
dhat-heap is a very good memory profiler.
@stevenhe3462
@stevenhe3462 Жыл бұрын
The point is not to allocate those little vecs.
@srgi
@srgi Жыл бұрын
Why the heck indeed
@begga9682
@begga9682 Жыл бұрын
Double it and give it to the next person
@actuallyasriel
@actuallyasriel Жыл бұрын
Wait, wouldn't the plural of Linux be "Linuces?"
@porky1118
@porky1118 Жыл бұрын
Are there really people who find inlay hints useful and not confusing?
@fasterthanlime
@fasterthanlime Жыл бұрын
Yes, me!
@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 Жыл бұрын
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 kzbin.info/www/bejne/mJiZXn-MeK2gfa8#t=58m23s
@EzequielRegaldo
@EzequielRegaldo Жыл бұрын
So we can go back to C++ ? Feels weird overcomplicated lang
@fasterthanlime
@fasterthanlime Жыл бұрын
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 Жыл бұрын
Sadly, you'd have the same problem in C++ too.
@EzequielRegaldo
@EzequielRegaldo Жыл бұрын
@@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 Жыл бұрын
@@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 Жыл бұрын
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 Жыл бұрын
​@@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 11 ай бұрын
What font do you use?
I built my own memory profiler (in Rust, on Linux)
22:58
fasterthanlime
Рет қаралды 62 М.
strace feels like magic - let’s fix that (with Rust)
16:21
fasterthanlime
Рет қаралды 50 М.
Mom Hack for Cooking Solo with a Little One! 🍳👶
00:15
5-Minute Crafts HOUSE
Рет қаралды 23 МЛН
REAL or FAKE? #beatbox #tiktok
01:03
BeatboxJCOP
Рет қаралды 18 МЛН
黑天使被操控了#short #angel #clown
00:40
Super Beauty team
Рет қаралды 61 МЛН
The Truth about Rust/WebAssembly Performance
29:47
Greg Johnston
Рет қаралды 188 М.
Self-referential structs (in Rust)
27:21
fasterthanlime
Рет қаралды 55 М.
Python fundamentals part 2 (coding)
56:16
AIgineer
Рет қаралды 49
Rust Functions Are Weird (But Be Glad)
19:52
Logan Smith
Рет қаралды 144 М.
GitHub Actions Feels Bad
26:27
fasterthanlime
Рет қаралды 99 М.
Let's make an htop-like in your browser (with Rust)
51:25
fasterthanlime
Рет қаралды 84 М.
Catching up with async Rust
17:55
fasterthanlime
Рет қаралды 24 М.
Use Arc Instead of Vec
15:21
Logan Smith
Рет қаралды 157 М.
POV: I'm on my third coffee and you just asked me how the internet works
21:20
Your Command Line, Oxidised
10:09
No Boilerplate
Рет қаралды 208 М.
Mom Hack for Cooking Solo with a Little One! 🍳👶
00:15
5-Minute Crafts HOUSE
Рет қаралды 23 МЛН