Memory Optimization for Web Applications

Alexander Parks
4 min readJan 11, 2024

--

As web applications become more and more complex and NodeJS is put into production environments on a large scale, many web applications will run for a long time, and JavaScript memory management becomes even more important.

JavaScript has an automatic garbage collection mechanism. The execution environment will be responsible for managing the memory used by the code during the execution of the environment and releasing the memory occupied by certain variables that are no longer used. Because of this, in most cases we use When developing, we don’t pay much attention to how much memory our page uses, whether it is reasonable, and whether optimization is needed.

There are many important knowledge points in the basics of JavaScript related to memory, such as deep copy and shallow copy, closure, prototype, reference data type and reference passing, etc.

Of course, there are many professional articles explaining the memory space and memory-related knowledge of JS in detail, so I won’t go into details here.

For knowledge about memory cycles and garbage collection, you can read and refer to MDN articles. Other articles are basically introduced based on this: Memory_Management

In web application development, we should pay attention to:

1. Avoid unnecessary use of global variables

Front-end developers all know that in the local scope, when the function is executed, there is no need for the local variable to exist. It is easily recycled by the garbage collector. When using global variables to define values, it is difficult for the garbage collector to Determine when the global variable needs to release the memory space, so it will not be recycled and destroyed. The variable will remain in the old generation heap memory until the page is closed.

function setName () {
name = "alloy";
}
// equals to
function setName () {
window.name = "alloy"
}

Another unexpected situation is;

function setName (name) {
this.name = name;
}
setName("alloy");

We can turn on strict parsing mode by adding “use strict” at the beginning of the JS file to avoid some accidental creation of global variables.

2. Dereference in time

If you must have a global variable to store a large amount of data, be sure to set it to null when you are done with it.

The delete operator is used to delete a property of an object; if there is no reference to the property, it will eventually be released.

But one thing to note is that try not to use delete in functions that require intensive operations. This is likely to cause the browser to GC at inappropriate times. Like other languages, JavaScript’s GC strategy cannot avoid stopping to respond to other functions during GC. Operation, and the GC of JavaScript is 50ms or more, which is fine for ordinary applications. If it is for web applications or games that operate frequently, it will be a hassle.

const Room = {
desks: 10,
chairs: 22
};
console.log(Room.desks); // 10;
delete Row.desks;
console.log(Room.desks); // undefined

Sometimes, although we use removeChild to remove the button, the reference to #button is still saved in the node object. The DOM element is still in the memory and needs to be dereferenced in time.

var node = {
button: document.getElementById('button');
};
document.body.removeChild(document.getElementById('button'));

3. Reduce object creation

Garbage collection runs periodically. If a lot of memory is allocated or a lot of new instances are created, the recycling work will be very hard.

Try to avoid recycling new objects in frequently called methods, and also spend time garbage collecting and processing these objects.

The flyweight pattern in design patterns is designed to reduce the multiple creation of objects. Reuse objects to the maximum extent within our control.

4. Memory is not cache

Caching plays an important role in demand development, but many times we cache a lot of big data in memory, causing our memory usage to always be at a high level. Memory is a precious resource for any program development. If it is not a very important resource, Please do not put it directly in the memory, or develop an expiration mechanism to automatically destroy the expired cache.

5. Avoid complex recursive calls

Normally, a simple recursive call will not cause the stack to overflow, but when it is complex and each call needs to store a large amount of information on the stack, thousands of such spaces accumulate and can easily exceed the stack. space.

6. Fair use of IndexedDB

In fact, this has little to do with JS, but it has a very important impact on Web applications. I once encountered a user case where due to long-term local data writing and some reported logs not being cleared in time, the user’s The IndexedDB storage under the corresponding domain name in the browser is up to 12GB. When the browser accesses the corresponding domain name, it can also initialize IndexedDB and read locally stored data. However, in the face of such a huge amount of data, the browser memory will skyrocket and eventually crash, avoiding Over-reliance on IndexedDB, mindless writing of data without regular cleaning.

7. Summary

This sharing mainly summarizes some situations we may encounter and things to pay attention to in web applications.

Many times, as long as we pay more attention when coding, we can avoid many problems.

--

--