Why many programmers don't like GC?
tsbockman
thomas.bockman at gmail.com
Wed Jan 13 20:36:05 UTC 2021
On Wednesday, 13 January 2021 at 18:58:56 UTC, Marcone wrote:
> I've always heard programmers complain about Garbage Collector
> GC. But I never understood why they complain. What's bad about
> GC?
SHORT VERSION: While garbage collection is great for many
applications, GC also has some significant disadvantages. As a
systems programming language, D attracts users who care about the
disadvantages of GC, but D's design prevents it from mitigating
the downsides of GC to the extent that less powerful languages
like Java can.
LONG VERSION: There are many different garbage collector designs,
so not all of these criticisms apply to all garbage collector
designs. Nevertheless, most every design suffers from at least
some of these problems:
1) Freezes/pauses: many garbage collectors have to pause all
other threads in the program for some significant time in order
to collect. This takes somewhere between a few ms and a few s,
depending on how much data needs to be scanned.
For interactive applications, these pauses can cripple the
program's performance. 60 FPS, or 16ms per frame, is a typical
target rate for modern user interfaces, video playback, and
games. When any given frame may be subject to a 5ms pause by the
GC, the processing for *every* frame must be limited to what can
be accomplished in 11ms, effectively wasting 30% of the available
CPU performance of *all cores* on most frames, when no collection
was necessary. But, 5ms is on the low end for GC pauses. Pauses
longer than 16ms are common with some GC designs, guaranteeing
dropped frames which are distracting and unpleasant to the user.
For real-time applications such as hardware control systems, a
pause that is too long could actually break something or injure
someone.
2) Much higher memory consumption: all practical heap memory
management schemes have some overhead - additional memory that is
consumed by the manager itself, rather than the rest of the
program's allocations. But, garbage collectors typically require
three to ten times the size of the data for good performance, as
opposed to two times or less for reference counting or manual
management.
3) RAII doesn't work properly because the GC usually doesn't
guarantee that destructors will be run for objects that it frees.
I don't know why this is such a common limitation, but my guess
is that it is due to one or both of:
a) Collection often happens on a different thread from an
object's allocation and construction. So, either all destructors
must be thread-safe, or they just can't be run.
b) A collection may occur at some awkward point where the
program invariants depended on by non thread-safe destructors are
violated, like inside of another destructor.
It is certainly possible to retrofit correct resource management
on top of a GC scheme, but the logic required to determine when
to close file handles (for example) is often the same as the
logic required to determine when memory can safely be freed, so
why not just combine the two and skip the GC?
GC has significant advantages, of course: simplicity (outside the
GC itself), safety, and, for better designs, high throughput.
But, the D users are more critical of GC than most for good
reason:
I) D is a systems programming language. While a good GC is the
best choice for many, many applications, the kinds of
applications for which GC is inappropriate usually require, or at
least greatly benefit from, the full power of a systems
programming language. So, the minority of programmers who have
good reason to avoid GC tend to leave other languages like Java,
C#, python, and JavaScript and come to us (or C, C++, Zig, or
Rust).
II) Historically, D's GC was embarrassingly bad compared to the
state-of-the-art designs used by the JVM and .NET platforms. D's
GC has improved quite a lot over the years, but it is not
expected to ever catch up to the really good ones, because it is
limited by other design decisions in the D language that
prioritize efficient, easy-to-understand interoperability with
C-style code over having the best possible GC.
In particular, D's GC is a stop-the-world design that must pause
*all* threads that may own any GC memory whenever it collects,
and thus it fully suffers from problem (1) which I described
earlier. Also, it used to have the additional problem that it
leaked memory by design (not a bug). This is mostly fixed now,
but for some reason the fix is not enabled by default?!
https://dlang.org/spec/garbage.html#precise_gc
(In before someone answers with, "Nothing. It works for me, so
people who say it's bad are just stupid and don't profile.")
More information about the Digitalmars-d-learn
mailing list