
How JavaScript works: memory management and common memory leaks - zlatkov
https://blog.sessionstack.com/how-javascript-works-memory-management-how-to-handle-4-common-memory-leaks-3f28b94cfbec
======
pizlonator
> As of 2012, all modern browsers ship a mark-and-sweep garbage-collector. All
> improvements made in the field of JavaScript garbage collection
> (generational/incremental/concurrent/parallel garbage collection) over the
> last years are implementation improvements of this algorithm (mark-and-
> sweep), but not improvements over the garbage collection algorithm itself,
> nor its goal of deciding whether an object is reachable or not.

WebKit uses a constraint-based garbage collector that does not rely on
reachability alone. This is an improvement over the classical garbage
collection algorithm.

~~~
mbudde
For reference: [https://webkit.org/blog/7122/introducing-riptide-webkits-
ret...](https://webkit.org/blog/7122/introducing-riptide-webkits-retreating-
wavefront-concurrent-garbage-collector/)

------
randomguy1254
Nice article. Minor gripe about the static vs dynamic memory section. The
requirement that the data sizes be known at compile-time for static memory
(with the example of an array allocated to a user-inputted size), seems to be
based on a past restriction of the C language. C has since remove the
requirement that stack-based arrays are sized with a compile-time constant;
there is nothing at the hardware/assembly level which prevents such arrays. So
these stack-based non-compile-time-sized arrays don't fit into either the
static or dynamic memory categories presented here.

~~~
phyllostachys
I was bothered by saying that static memory is assigned on the stack (implied
that it is only on the stack). As an embedded guy, at least in bare metal
situations, local function statics, any const variables, and any globals are
either in the read-only data section[1] or in the general data section[2],
both before the heap and definitely not in the stack section.

[1] - .rodata section in gcc

[2] - I think this is in the .data and .bss sections, where .data is copied
from the file and .bss is zero initialized before calling main by the crt. If
you peak into a linker script, or dump one by passing --verbose to ld, you can
even see where it puts all the C++ bits and pieces. A dump I did on Debian
with g++ is here:
[https://gist.github.com/Phyllostachys/0682a3bda13ef9c6b49d04...](https://gist.github.com/Phyllostachys/0682a3bda13ef9c6b49d0445052ec955)

~~~
phyllostachys
After looking at that default linker script dump, I noticed it didn't have the
stuff I saw in the ARM linker script that I'm used to. So I attached one for a
Silicon Labs EFM32 part. It's below the x86-64 linker script and is a little
easier to read.

~~~
phyllostachys
After a little investigation[1][2], it seems things get weird with an OS, as
would be expected with virtual memory, et al.

[1] - [https://stackoverflow.com/questions/16360620/find-out-
whethe...](https://stackoverflow.com/questions/16360620/find-out-whether-a-
pointer-is-pointing-at-the-stack-heap-or-program-text)

[2] - [http://duartes.org/gustavo/blog/post/anatomy-of-a-program-
in...](http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory/)

------
vvanders
Wait, is #3 for real? If that's the case it seems like a huge oversight.

~~~
IgorPartola
Yeah, of the four things listed, I think it's the one that would trip me up
the most. I think the safety net here would be dead code elimination:
`unused()` should be detected as never called and removed during
compilation/transpilation so that this wouldn't be an issue.

I am sort of surprised that `unused` is not picked up by the garbage collector
in the first place though. Since JS functions are objects, shouldn't it detect
an object that's not referenced during the mark and sweep?

In general, I really hate having to debug memory leaks in JS or Python. The
interpreter for both will randomly allocate additional memory as it runs, so
using tools like Valgrind is next to impossible. The only reliable method I've
found is to pepper my code with logging statements that show what the current
memory usage is, run the code like 1000-10,000 times, and see the points
between which the memory usage goes up without coming down on a consistent
basis. Python's built in `gc` module seems nearly useless for determining
what's actually stuck in memory, and having a billion libraries that can have
their own memory leaks is also not fun. These are the times I miss C: when you
leak memory in C you know it because it becomes painful fast and it's usually
easy to find, if your code is sane.

~~~
favorited
I haven't done JS in a while, but it sounds to me like it _is_ referenced,
just not in source code. `someMethod` references it implicitly.

Is my understanding correct?

~~~
gsnedders
Yes. The function's frame contains a reference to the object storing local
variables of the parent frame. To do better you need to store a list of
variables referenced (which you can only do if there's neither direct-eval nor
a with statement).

------
fenwick67
Who is this article written for? There's a whole section on "What is memory?".
If you are optimizing to remove memory leaks I really hope you already know
what memory is.

~~~
mhh__
In my experience there are (I don't know how many) some programmers who, given
how they were taught/learnt, can do productive work but generally don't know
computing/programming in the abstract e.g. Memory at the machine level, or
type systems.

~~~
userbinator
_can do productive work but generally don 't know computing/programming in the
abstract_

 _e.g. Memory at the machine level,_

I think it's the other way around --- their usual level of abstraction is too
high to understand such things...

 _or type systems_

...and slightly too low to understand others.

------
styfle
Jump straight to "The four types of common JavaScript leaks" section:

[https://blog.sessionstack.com/how-javascript-works-memory-
ma...](https://blog.sessionstack.com/how-javascript-works-memory-management-
how-to-handle-4-common-memory-leaks-3f28b94cfbec#82b7)

~~~
dualogy
Didn't jump for me, but this should: [https://blog.sessionstack.com/how-
javascript-works-memory-ma...](https://blog.sessionstack.com/how-javascript-
works-memory-management-how-to-handle-4-common-memory-leaks-3f28b94cfbec#82b7)

~~~
styfle
Oops, it looks like medium removes the hash on load so my copy/paste didn't
work. I fixed my link.

------
cel1ne
The main problem with JS being sluggish (in electron apps for example) is
memory and especially the GC.

I can optimize CPU usage all I want, but only after I optimized for minimum
allocations, the tiny, but noticeable lags now and then would disappear.

The average javascript-GC must be really simple/naive compared to seasoned
workhorses like the JVM's various GCs.

There I can happily create millions of short-lived objects before getting
problems in a single-user application.

~~~
chillacy
Well, you can run JS on the JVM through Oracle's Rhino (now Nashorn), but
apparently perf is still largely worse than Sunspider or V8. The language
doesn't lend itself to optimization as much as java does for JVM bytecode:
[https://blogs.oracle.com/nashorn/nashorn-architecture-and-
pe...](https://blogs.oracle.com/nashorn/nashorn-architecture-and-performance-
improvements-in-the-upcoming-jdk-8u40-release)

------
irtefa
Haven't read such an easy to read technical article in a while. Kudos!

------
dispo001
having stuff do stuff for you is useful until it doesnt

~~~
theprotocol
I agree. I strongly dislike "magic" in programming. I prefer to call it
"denial" because you need to know about the complexities anyway, and "magic"
often means sweeping them all under the rug.

~~~
abritinthebay
At some point every abstraction above Assemby meets that criteria though. The
lines are personal and mostly arbitrary.

~~~
taeric
Meh, if you try and split hairs, even assembly has magic in it nowdays. Not
all instructions take the same amount of time. Some flush caches, thus cause
unexpected memory behavior, etc.

However, I think it is fair that most people learn roughly what the side
effects are of each line at a local level.

Ironically, this is an argument against many functional languages. There are
not side effects of the logic, per se. However, there are massive
implementation side effects that are not necessarily easy to reason on.

The saving grace for the vast majority of people is that typically you can get
by without knowing all of this. The people that care, do care. But
statistically you are not one of them. :)

~~~
abritinthebay
Like I said - it's mostly arbitrary. ;)

That said I think the issues with assembly you mention aren't magic as such,
they're just consequences of the commands. They don't really hide much (if
anything) behind the scenes that you'd have access to anyhow.

It's just that CPUs do _so much more_ than they used to.

~~~
horsawlarway
It's not that simple though. Most modern CPUs that support the x86_64
instruction set don't actually run them as instructions on the hardware. They
do all sorts of magic to queue operations, increase pipeline throughput,
manage register access, make branch predictions, etc...

You can think of assembly on those cpus as a high level language. It has
little correlation with what's actually happening in hardware.

This is EXACTLY the same type of "magic" that is getting complained about
above. The real implementation details are hidden and unknown, but the
abstraction is useful.

~~~
abritinthebay
Ah interesting. Not familiar with x_64 really. Mostly 16 & 32 bit experience
here.

------
def0wt
> To prevent these mistakes from happening, add 'use strict'; at the beginning
> of your JavaScript files. This enables a stricter mode of parsing JavaScript
> that prevents accidental global variables.

I don't think using strict will prevent accidental global variables, such as
this.var in global scoped function calls. Strictness main goal is to prevent
inadvertently misspelled variables from going unnoticed.

~~~
ufo
Iirc, if you use strict the this gets set to null by default instead of the
global object

------
jnordwick
More extremely junior posts being rated to the front page. Y combinator is
changing and i don't like its new junior tutorial level.

