Gmail is one of the most popular web-based email products. It is no secret that Gmail puts a noticeable strain on your browser and subsequently the entire computer. It may seem pointless to analyze why Gmail is bloated, considering it is an integral part of many users' business and even personal life.
Well, it turns out that studying the breakdown of Gmail's memory consumption has led us to some interesting discoveries.
We used Firefox to profile Gmail's memory usage. Like many web applications, Gmail incrementally downloads scripts and resources. We have interacted with the application until the memory consumption reached a stable level.
At the first glance, we see that Gmail takes up more than 100 megabytes of RAM. The majority of the RAM is divided into three equal parts: objects, domNode (DOM Nodes) and scripts.
In a plain, static HTML document, elements on the page are described by HTML tags. Each pair of tags denote what's known as a "node". Nested tags illustrate a hierarchy of nodes, much like a tree structure. All these nodes, or "objects" are part of the DOM, or "document object model".
In addition to statically declared HTML tags, JavaScript can also dynamically insert, modify or remove nodes from the DOM. When a user interacts with a web page, or application, the browser will trigger an "event". For example, when a button is clicked, there is an onclick event. A JavaScript routine, or a "function", is then called to handle such event. If a web application allows many interaction points, there would be many functions. Also, not all JavaScript functions are DOM event handlers. They could be "helper functions" for internal data processing.
In addition to functions, there are also "objects" that are internal representations of logical objects in memory. Many JavaScript frameworks allow the programmer to work with these invisible objects. The actual DOM nodes are then generated automatically.
Knowing the concept of "objects", "DOM nodes" and "scripts", we now know that Gmail has a large number of JavaScript functions. These functions then create an overwhelming number of internal objects. Many of these objects are then "materialized" into actual DOM nodes. If every footprint of Gmail is pressed by a giant dinosaur, the entire trail cannot possibly be small.
Is script size the determining factor in web app's responsiveness? To answer this question, we looked at another heavy project - Jira, a web-based bug tracking software:
For comparison, we also included some products that are built with Antradar's coding practice (marked in blue).
Jira is not a single page application; it is a collection of a few functional modules. Within each module, or "view", there is a single page that acts like a mini Gmail. We have examined two common views in Jira - the Ticket view, and the Board view.
Jira's level of bloat is astounding, as if it's going for some Award of Inefficiency. The supposedly simple Ticket view dwarfs Gmail. The Board view is definitely reaching for the crown jewel.
Just to be fair, Jira is an engineering marvel in its own right. For those who are interested in Jira's front-end changes, here's an interesting video:
Given a development team that's approaching 400, Jira has no choice but to use many layers of abstraction. Unfortunately abstraction does not translate well to the front end. The memory chart shows that the Object size in Jira is not only large, but it surpasses its DOM Nodes.
Before we dive into the topic of DOM-to-Object ratio, let's also throw in some non-web app products for comparison:
The front-end of Shopify is just a collection of loose pages. Each page can be reached directly, and the user can jump from one page to another. There is no incentives of having a monolithic JavaScript run-time environment. Therefore, a typical website that's powered by Shopify uses less memory.
Efficiency is relative. Although Shopify is slimmer than Gmail, it is still heavier than most Gyroscope applications, which are often complex, feature-rich back office systems. Since a web page, in contrast to a single-page web app, requires less in-residence JavaScript overhead, our FFC shopping framework is even more efficient. At a screaming lightweight of 2MB, or 10% of a Shopify page, or 1.5% of Gmail's memory footprint, FFC powered shopping pages are impressively fast.
DOM-to-Object Ratio
Now let's turn our attention back to the sumo wrestlers. Earlier, we mentioned that in many JavaScript frameworks, the DOM nodes are strictly mapped from JavaScript objects. This means that for every elements you see on a web page, or web app for that matter, there is one, or multiple corresponding objects. We have measured the DOM-to-Object ratio for the following projects:
We can see that the lower the ratio is, the more the application relies on JavaScript. There is an observed correlation between low DOM-to-Object ratio and sluggish user experience.
An Architectural Advantage
We also see that Gyroscope applications have a rather high DOM-to-Object ratio. Furthermore, another Antradar product, FFC, exhibits an even higher ratio, as it is optimized for massive scale and performance:
Both Gyroscope and FFC use the LCHH architecture, which, by design, does not have the double representation issue that plagues nearly all JavaScript frameworks. In LCHH, DOM nodes are directly generated on the server side. JavaScript functions are mostly used to interact, rather than to define, DOM elements. This design drastically reduces the web app's memory footprint. In addition, the page rendering time is much shortened.
Unused Memory is NOT Wasted Memory
There is a saying "unused memory is wasted memory" that's commonly used to defend bloated software. However, this saying is used out of context and is therefore utter nonsense.
Originally the saying was to point out, that if a piece of software uses disk instead of the much faster RAM, it is under utilizing the hardware resource. A reasonably designed operating system should use as much "real" RAM as possible before resorting to virtual memory that's backed by disk files.
On Android devices, obsessively freeing up RAM might be counter productive because of context switching penalty.
As far as web application goes, using less memory is definitely more efficient.
To put things in perspective, imagine that a family is going on a trip to Mars. Everything they need to bring on this one way trip must be bought. There is no point of leaving some money behind. "Unused money is wasted money". Within this Mars-bound family, there is a big eater, which we'll call Gee-Mal. Gee-Mal is inconsiderate and eats everyone's food. "uneaten food is wasted food", proclaims Gee-Mal. The rest of the family, along with the space crew, starve to death. End of story.