1. Introduction

Device memory, or RAM, is a temporary but fast storage option where processes are loaded so that we can quickly access and run them. However, devices have limited memory, which can lead to various performance issues, such as sluggish performance, application crashes, or even system freeze.

Thankfully, Linux is extremely modifiable, allowing us to address these limitations by configuring memory usage in various ways. In this tutorial, we’ll explore a range of techniques to optimize memory usage for the overall system, from limiting resource usage to fine-tuning system configurations.

2. Viewing Current Memory Usage

Before optimizing the total memory of our Linux systems, it’s important to view the current state of memory usage. Fortunately, Linux provides us with a simple yet powerful command to monitor memory usage in real-time called free.

Let’s see an example of its usage:

$ free -h
               total        used        free      shared  buff/cache   available
Mem:           7.4Gi       280Mi       6.5Gi       0.0Ki       691Mi       6.9Gi
Swap:          2.0Gi          0B       2.0Gi

The free command displays as a table the combined amount of free and used physical and swap memory, as well as the buffers and caches used by the system. Here, we’ve used the -h or –human option to display the values in the table in human-readable format.

Let’s explain the rows and columns of the table in detail:

  • Rows:
    • Mem: The physical memory, which is also referred to as RAM (Random Access Memory). This is high-speed storage where processes are loaded while in execution.
    • Swap: The swap memory, which is a designated space on the hard drive used as virtual memory when physical RAM is fully utilized. It acts as an extension of RAM, allowing the system to move less frequently accessed data from RAM to disk to free up physical memory for more active processes.
  • Columns:
    • total: Total memory available
    • used: Amount of memory currently in use
    • free: Amount of unused memory available for use
    • shared: Memory used by shared memory segments that can be simultaneously accessed by multiple processes; it allows processes to communicate and share data efficiently
    • buff/cache: Memory used by buffers and caches; buffers temporarily hold data being transferred, while caches hold frequently accessed data to speed up access times
    • available: Estimated amount of memory available for starting new applications

From the above output of the free command, we can see that our system has almost 8 gibibytes of physical memory and 2 gibibytes of swap space, most of which is unused. This is a good scenario for optimal device performance.

3. Clearing Cache Memory

Clearing the cache can sometimes lead to improved system performance. Since loaded cache memory can decrease the available memory for resource-intensive tasks, one simple way to drop cached data is to write the value 3 to a particular system file:

$ sudo echo 3 > /proc/sys/vm/drop_caches

We use echo to write the value 3 to the /proc/sys/vm/drop_caches file, which instructs the kernel to drop all cached data, cached dentries, and inodes together. We can use this in situations where memory usage needs optimization or performance issues need troubleshooting. We’ll need to run it with the sudo command to enable permission to write to this system file.

However, directly dropping caches without prior preparation may hamper important tasks like data transfer, memory access, and many more. So, it’s essential to ensure that the cache doesn’t contain any useful contents before flushing it. For this particular task, the sync command is useful. Let’s use it in conjunction with the above command:

$ sudo sync && echo 3 > /proc/sys/vm/drop_caches

We need to enable higher privileges to run this command properly using sudoThen we issue the sync command, which signals the operating system to flush all pending writes in the system’s buffers to the disk. By this, we ensure that all data is written to the disk and that any changes are safely persisted before freeing the cache.

However, we should note that dropping caches can temporarily slow down system performance because accessing previously cached data again requires reloading it from disk.

4. Freeing Swap Space

When our system fully utilizes physical memory (RAM), Linux resorts to using swap memory as a fallback. Swap memory resides on the hard drive and acts as virtual memory, allowing the system to move less frequently accessed data from RAM to disk. However, excessive swapping can lead to performance degradation due to increased disk I/O operations. Clearing swap memory offers several benefits, like improving overall system responsiveness by reducing reliance on slower disk-based virtual memory.

To clear swap memory, we can utilize the swapoff and swapon commands:

$ sudo swapoff -a && swapon -a

The swapoff command disables swap devices on the system. It stops the swapping process, effectively removing data from swap space and returning it to RAM. On the contrary, the swapon command enables swap devices. It instructs the system to start using swap space again. However, since we’ve just cleared it, it’ll start with a clean slate. Using the -a option for both instructs the commands to clear swap memory for all devices.

5. Masking and Disabling Services

We might have certain unwanted services in our system that might autostart or run at startup. If they’re dependencies for other important services, uninstalling them directly is not a viable option. In that case, we can use systemctl to disable or mask these services.

5.1. Masking Services Using systemctl

The first option is to mask the service. Before masking the service, we should stop it first to avoid any misbehavior of the system. Let’s see the command sequences for masking a service using systemctl:

$ sudo systemctl stop xyz
$ sudo systemctl mask xyz
$ systemctl status xyz
● xyz.service
   Loaded: masked (/dev/null)
   Active: inactive (dead)

Here, we can see an example of masking a made-up service called xyz. The first command stops that service if it’s already running. By using the second command, we’re essentially preventing the xyz service from starting automatically during system boot. This action goes beyond merely stopping the service temporarily. Masking a service ensures that even if a process or command tries to enable or start the xyz service, it’ll fail. Effectively, it makes the xyz service invisible to the other services.

5.2. Disabling Services Using systemctl

Sometimes, we may want to stop a particular service from autostarting at startup, but we might still want other services to activate it if needed. In that case, we can disable that service:

$ sudo systemctl stop xyz
$ sudo systemctl disable xyz

This allows us to stop the xyz service from starting automatically during system boot and removes any existing symlinks that point to the service unit file.

While similar to masking, disabling the service provides a more reversible approach. It allows us to easily re-enable the service in the future by explicitly calling the service directly or as a dependency.

6. Conclusion

When we optimize memory resources, the system can operate smoothly, ensuring responsive application performance and minimizing the risk of slowdowns or crashes. By freeing up memory, we enable active processes to run without excessive swapping or resource contention hindering their performance.

In this article, we explored various techniques for optimizing memory usage in Linux. We learned how to monitor current memory usage, clear cached data, and manage swap space. Furthermore, we looked into how to disable and mask services using systemctl. By implementing these memory optimization techniques, we can ensure that our Linux systems run efficiently and effectively for our usage needs.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.