
Introduction to Memory Management (2018) - lrsjng
https://www.memorymanagement.org/mmref/index.html
======
mattnewport
From what I've skimmed so far this isn't a very good or accurate resource. In
particular it doesn't mention RAII in its discussion of C++, doesn't mention
Rust at all, neglects the role of stack allocation, glosses over the common
use of object pooling in GC languages as a workaround for performance issues,
has little on the extra issues introduced by multithreaded code and
understates the performance issues of GC.

~~~
pcwalton
It's actually a great resource. The glossary covers all these issues, except
for Rust, which the site content predates. It tends to use more academic
terminology instead of the current industry terminology, but the academic
terminology is often more precise anyway. Yes, it's opinionated in favor of
GC, but that's a perfectly defensible position (which may sound odd coming
from me as a Rust developer, but I actually like GC in many—just not
all—circumstances).

RAII is covered under "smart pointer":
[https://www.memorymanagement.org/glossary/s.html#term-
smart-...](https://www.memorymanagement.org/glossary/s.html#term-smart-
pointer)

Stack allocation is here:
[https://www.memorymanagement.org/glossary/s.html#term-
stack-...](https://www.memorymanagement.org/glossary/s.html#term-stack-
allocation)

Object pooling is covered under "segregated free list":
[https://www.memorymanagement.org/glossary/s.html#term-
segreg...](https://www.memorymanagement.org/glossary/s.html#term-segregated-
free-list)

Multithreaded GC is covered under "parallel garbage collection":
[https://www.memorymanagement.org/glossary/p.html#term-
parall...](https://www.memorymanagement.org/glossary/p.html#term-parallel-
garbage-collection)

~~~
clappski
That paragraph on smart pointers doesn’t have anything to do with RAII - it’s
not even accurate concerning C++ smart pointers, where the standard ‘has a
single owner’ smart pointer doesn’t use ref counting, it uses RAII.

~~~
adrianratnapala
Probably the resource is older than 2018, and is taking aim shared_ptr (or
maybe even auto_ptr?) rather than unique_ptr.

~~~
mattnewport
Both unique_ptr and shared_ptr have been standard since C++11 which is also
when auto_ptr was deprecated (auto_ptr is/was also not reference counted).

------
pcwalton
I don't think this is from 2018; the contents are mostly unchanged since 2014
[1].

Even though it's a bit dated, memorymanagement.org is one of my favorite
resources. It's opinionated, in a good way. The techniques that were developed
in the 2000s, which this site thoroughly covers, are still the state of the
art for garbage collection in my opinion.

[1]:
[http://web.archive.org/web/20140616011030/https://www.memory...](http://web.archive.org/web/20140616011030/https://www.memorymanagement.org/mmref/index.html)

------
keldaris
Even though many of the technical points are highly debatable, my biggest
issue is with the sentence "the programmer is freed to work on the actual
problem" listed among the "advantages" of automatic memory management, and
with how ubiquitous that mindset has become.

Insofar as computer programming is concerned, the "actual problem" is always
the transformation of specific data on a specific set of computing hardware.
Automating memory management doesn't imply working on the actual problem, it's
just outsourcing a part of the actual problem in the pursuit of other
objectives - decreasing development time, reducing the likelihood of specific
bugs, etc. I'm not arguing that people shouldn't use automatic memory
management, it often makes perfectly good technical and business sense to do
so - but pretending that memory management is not a crucial part of solving
any real problem in computer programming (even if you're not doing it
explicitly) does no good to anyone.

~~~
marvy
I think maybe your definition of "actual problem" is not the same as their
definition. Let me try to defend their definition with an analogy.

If I write in C, I don't have to worry about register allocation (which
variable goes in which register, when should I spill to the stack, etc.). I
can just write things like (a+b+c)/3 and it "just works". Perhaps the compiler
will do a bad job with allocating the registers, and a good assembly
programmer would have done far better, even to the extent that the program
goes from "way too slow" to "plenty fast". (Unlikely these days, but in the
past knowing when to use the "register" keyword was worth knowing.) But even
then register allocation is incidental complexity, in that they are an
artifact of the solution, not of the problem itself.

But even though C programmers don't have to worry which registers are callee-
save vs caller-save every time they call of function, they do have to worry
about who is supposed to free every allocated data structure. Java programmers
don't; they can just write

    
    
        ("1+2="+3).getBytes()
    

and it "just works". The garbage collector may be so inefficient that you wish
it weren't there, but even then, deciding exactly when to deallocate every
temporary string is incidental complexity, in that they are an artifact of the
solution, not of the problem itself.

Of course, just because the problem is incidental doesn't mean it need not be
solved! You really do need to free those strings or else you'll run out of
memory and crash. (but not too soon, or else you have a use-after-free
problem.) And likewise, at the end of the day, the values better end up in the
right registers. But whether you're writing a game or web app or an FPGA
simulator, memory management is not the "actual problem" you care about
solving. The proof is that you don't think about when you're writing the user
guide to your software.

~~~
keldaris
Well, that's exactly the point - I was arguing against the (by now ubiquitous)
definition of the "actual problem". Your analogy further illustrates exactly
that.

The actual problem (as in, the thing you are actually solving whether you
realize it or not) of computer programming is not creating a product (that's
business) or even data transformation (that's applied math). All computer
programming is ultimately the transformation of data on real hardware (however
abstracted by everything from firmware to virtual machines). Obviously,
computer programmers don't exist in a vacuum and have to take into account
technical (including mathematical) and social (including business) concerns,
make tradeoffs, etc., but that doesn't change the basic facts. I'm just
arguing we should be more explicit about them, not write them off.

And to address your analogy directly, register allocation is as much part of
the actual problem as memory management. Even though most of us rarely resort
to actually doing it by hand, it's still there and examining it in the
resulting assembly is still often an important part of optimizing code. My
argument is that regardless of whether you directly encounter something like
register allocation every day, it is both conceptually important and useful to
recognize it as part of what computer programming actually is, the technical
and social properties that lead to the degree to which it is automated and the
associated tradeoffs. Pretending that the actual problem of getting computers
to do what we want is some annoying series of "incidental" problems is a
recipe for bad software.

~~~
marvy
So, I guess what you're saying (correct me if I'm wrong) is that even though
memory management (and register allocation, and other things) can be
classified as "incidental", this is a dangerous label, because people are
prone to then think "and therefore I can outsource these problems to a
GC/compiler/whatever and not need to think or worry about them anymore" and
then wonder why performance is so bad.

If that's your point then I agree, but I still think it's worth at least
making a vague mental note that the problem is still incidental (and then
carefully avoid the above conclusion).

~~~
mattnewport
Not the OP but I think you're still missing his point. The argument is that it
is fundamentally wrong headed to argue that the process of realizing software
on actual hardware is incidental or not part of the actual problem in the same
way that it would be wrong to argue that the laws of physics are not part of
the actual problem for engineering.

If you're building a road bridge you could say that the actual problem is
getting vehicles from one side of the river to the other and not the
engineering details required to realize a physical structure capable of doing
that. Things like the tensile strength of steel would be no more important to
the bridge builders than mere memory allocation is to the average programmer
in a GC'd language. You could also argue that taking that approach would lead
to bridges that fail as badly at their primary function as much modern
software does.

~~~
keldaris
That's exactly right, thank you. It's a fundamentally simple point often made
by embedded and game programmers (perhaps most famously in recent years in
Mike Acton's keynote at CppCon [1]), but most programmers seem to have
completely written off most of what computer programming actually is as
"incidental".

[1]
[https://www.youtube.com/watch?v=rX0ItVEVjHc](https://www.youtube.com/watch?v=rX0ItVEVjHc)

~~~
marvy
Hmm... maybe I better watch this talk at some point and try to get this
through my head better... When I saw the bridge example my reaction was
basically "why would that result in bad bridges?"

I feel slightly attacked when you say "written off". I don't mean to "write
off" memory management as something undeserving of attention. I think that if
performance matters at all, then even if you program in a GC'd language you
better know roughly how your GC works and what it's good and bad at, and
preferably have a plan for switching to a different GC if need be.

More generally, "incidental" stuff deserves attention. It may very well
deserve the MAJORITY of your attention. I don't want to "write it off". I just
want to classify it properly. Am I increasing my own risk of creating bad
software by thinking this way?

~~~
keldaris
Well, there are two at least partly orthogonal points here - the teleological
discussion over what computer programming actually is and the practical point
regarding which mindset is more likely to lead to better software. I don't
know that I can express my position on the former issue better than I already
have in the form of a short comment suitable for this format (though I do
recommend the talk I linked), so I'll leave that aside for now.

On the latter point, however - and to answer your question regarding bad
software - all other factors being equal, I think the answer is "probably,
yes". The fundamental reason is that someone who is used to regarding memory
management (which is really just one example among many) as incidental
complexity to be outsourced away by default is less likely to reason carefully
and intelligently about the actual implications of that decision. Just to pick
a trivial example, someone who has internalized the RAII pattern in C++
without really understanding its implications may find it difficult to solve
(or even find) memory fragmentation issues leading to bad performance - not
something easily found in current profilers if you don't know what you're
looking for already. There's a lot of issues like that which may seem either
obvious or subtle depending on whether your mindset is to properly understand
how the solution you've chosen actually works or regard it as incidental until
proven otherwise.

In the modern computer programming industry you can go a long way without
really dealing with any of the issues I've mentioned. However, the fact that
much of modern software is unbelievably bloated and slow for no good technical
reason is indicative that perhaps it would be better if more programmers took
direct responsibility not just for the code they actually write, but for the
code they outsource to others, often without truly grappling with the
implications of those decisions.

~~~
marvy
> perhaps it would be better if more programmers took direct responsibility
> not just for the code they actually write, but for the code they outsource
> to others, often without truly grappling with the implications of those
> decisions.

Now THERE I agree completely! (Will watch the talk next weekend I hope.)

------
pizlonator
I get that it’s well intentioned but I wish folks stopped talking about the
buddy allocator. It’s so obsolete. It’s not the fastest and it sure has some
of the worst fragmentation due to very imprecise sizing.

~~~
twtw
Can something be obsolete if it is still extremely widely used?

IIRC, Linux and FreeBSD both use a buddy allocator for physical memory, and
I'm pretty sure it is used (in addition to other allocators) in jemalloc as
well.

~~~
pcwalton
I don't think jemalloc uses any buddy allocators. It's a segregated free list
allocator, like most C mallocs and tenured generation allocators.

------
anitil
When reading the language section [0] I was surprised to see that COBOL had no
heap allocation until 2002. Searching around, the only comments I could find
amounted to "We just didn't need it.". Can anyone fill me in?

[0]:
[https://www.memorymanagement.org/mmref/lang.html](https://www.memorymanagement.org/mmref/lang.html)

~~~
vajrabum
Historically, there weren't recursive procedures in Cobol and no concept of
new(). Instead all the data was statically initialized at application start.
The compiler did the storage allocation.

------
dataking
Expected to see Rust's approach mentioned since it occupies an interesting
point in the design space, i.e., automatic memory management where lifetimes
are (mostly) determined at compile-time vs. at run-time (RC and/or GC).

