Magic behind the JavaScript engines Part-3 Orinoco Garbage collector
Hey Folks! welcome to third article of Magic behind JavaScript engine series in todays article we will see how Garbage collector works in V8 JavaScript engine.
If you have not gone though earlier articles of this series you can use the below links
If we go back to early 1950’s the size of main memory was too small considering todays standards. And in todays world the size of memory even on a small embedded device is many folds greater than what we had during early days. Even though the memory is getting cheaper day by day still we are far away to reach state of infinite memory. But the number of application and its size which residing on main memory has also grown exponentially. Hence the system can not simply add more and more process without removing the potential dead objects from memory, hence we need an application which can clean up the un-used object time to time so that it can make up space for new process to occupy. So here comes the concept of Garbage collection.
If we consider languages like C or C++ we don’t find any concept of Garbage collector in it. The complete memory management is in the hands of the programmer. But if we take languages like Java or JavaScript garbage collector are part of the compiler engine. Which makes the job of programmer easy and need not worry about OutOfMemoryError .
Orinoco is one of the game changing garbage collector in the history of V8. Even though garbage collector seems cool, it has its own issues. Garbage collector is also a process which needs to running most of the time. This may block the main thread for a while and would result in poor performance of the system.
The above image shows how main thread is blocked by garbage collector for 200ms. Let us assume a video been played at 60fps, if the main thread is blocked for more than 16.6ms then frame has to be dropped. So from the above image when GC blocks the main thread for 200ms then this results in a huge frame drop or might lead to buffering. So in order to solve these issue there are many way in which GC can run along with Main thread with out compromising the performance.
In order to prevent main thread from getting blocked for long time GC can create multiple threads and share the workload among them so that can windup quickly.
Instead of calling GC only when the heap is about to get filled completely, GC can be called at a smaller interval so that it can finish up its job quickly. But the major drawback of this model is that time spent on context switching will be more compared to other models.
With multi-core processor we can run main thread and GC parallelly on each core. This is one of the best solution but expensive on resource.
The first task of GC is to identify the dead objects. This is done by traversing the stack and global pointers. All those objects which are reachable starting from these pointers are flagged as live objects and the rest are considered as dead object.
Once the dead object are flagged now GC has to free up these location and this leads to external fragmentation of memory. Then compaction process is carried out to solve external fragmentation.
Generation Hypothesis: “Younger generation objects die faster”
Now what is this term generation doing in garbage collection? Developers of Orinoco has categorised objects into young and old generation. All those objects which survives at least one cycle of garbage collections are classified as Older generation objects. So based on this hypothesis Orinoco has two types of GC Minor GC ( also known as scavengers) and Major GC .
Minor GC: Uses thread model of garbage collection as mentioned in the above part. Multiple child threads identify the dead objects (only young generation) and evacuates the live objects to a new location. Where all those objects which escapes the GC are kept in a continuously location ( which avoids the external fragmentation) and the stack and global object pointers are updated to this new location.
Major GC: Here based on the object allocation rate and survival rate time slot for next GC is calculated. And just before the actual GC starts all dead objects are marked using multi process model. And using multi thread model the memory slots are freed. So Major GC is a hybrid version of multi treaded and multi process model.
Thank you guys for reading this article. In the next article of this series will cover dynamic datatypes in JS. Though we are done covering all the topics of V8 engine we will see how dynamic datatype works in JS which is one of the beautiful topic in JavaScript language. Till then happy reading…!
Manthan M Kulakarni