… the story of how I identified the bug …
I just skimmed it but this seems to be the practical lesson for coders:
As mentioned previously, adding a call to shrink_to_fit() prior to storing the edge lists in the final graph eliminated the memory leak issue. This is fine as a quick hack, but it is not the proper solution. The real fix is to call into_boxed_slice() instead.
The basic problem is that Vecs are optimized for the case of a mutable list where you’re planning to add and remove elements in the future. However, people also commonly use them for fixed-length list data, even though this is not what Vecs are designed for, simply because Vec is the easiest and most intuitive way to store list data in Rust. The proper data structure for fixed-length lists is Box<[T]> rather than Vec<T>, but it takes a lot of Rust experience to even know about that as an option, and the syntax looks weirder.
I actually came in here to post just that. It’s something that, while I’ve vaguely known, is not something I typically remember to do - I’m usually returning or collecting Vecs all over. I shall be now diligent & intentional from now on.
For shared, immutable lists, you can also use
Arc
/Rc
in place ofBox
! I guess what’s surprising is that[
(and ]str
/Path
/OsStr
/etc) are traditionally associated with shared borrows (like&[T]
), but they’re really just unsized types that can be used anywhere there’s a?Sized
bound.Also, overuse of lists (as opposed to other data structures) seems to be a common problem in all programming languages among less experienced devs since they’re simple enough to use in most places. Not saying that’s what happened to the author though - these types are way less obvious than something like a hash set or queue.
Does
Box<[T]>
have the relevant trait implementations to be used in all the places where people misuseVec
?