Advantages and Disadvantages of HugePages

Advantages and Disadvantages of HugePages

The translation of the article is prepared for the students of the course Linux Administrator.

Earlier, I explained how to check and enable the use of HugePages in Linux.
This article will be useful only if you actually have a use case for HugePages. I have encountered many people who are misled by the prospect that HugePages will magically boost performance. However, hugepaging is a complex topic, and if misused, it can actually degrade performance.

Part 1: Checking if HugePages are enabled in Linux (original here)

Issue:
It is necessary to check if HugePages are enabled on your system.

Solution:
It’s quite simple:

cat /sys/kernel/mm/transparent_hugepage/enabled

You will get something like this:

always [madvise] never

You will see a list of available options (always, madvise, never), with the currently active option enclosed in brackets (by default, madvise).

madvise means that transparent hugepages are enabled only for memory areas that explicitly request hugepages using madvise(2).

always means that transparent hugepages is always enabled for all processes. Generally, this increases performance, but if you have a use case where many processes consume a small amount of memory, the overall memory load may spike significantly.

never means that transparent hugepages will not be enabled even when requested via madvise. For more information, refer to the the documentation Linux kernel.

How to change the default value

Option 1: Change directly sysfs (after a reboot, the parameter will revert to its default value):

echo always >/sys/kernel/mm/transparent_hugepage/enabled
echo madvise >/sys/kernel/mm/transparent_hugepage/enabled
echo never >/sys/kernel/mm/transparent_hugepage/enabled

Option 2: Change the system default value by recompiling the kernel with a modified configuration (this option is only recommended if you are using a custom kernel):

  • To set always as the default, use:
    CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
  • To set madvise as the default, use:
    CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y

Part 2: Advantages and Disadvantages of HugePages

We will try to selectively explain the advantages, disadvantages, and potential pitfalls of using Hugepages. Since it is a technologically complex and meticulous article, it may be challenging to understand for those who are misled into thinking Hugepages are a panacea. I will sacrifice precision for simplicity. It's worth noting that many topics are indeed complex and therefore heavily simplified.

Please note that we are talking about 64-bit x86 systems running on Linux, and I am simply assuming that the system supports transparent hugepages (as it is not a drawback that hugepages are not substituted), as is the case in almost any modern Linux environment.

In the links below, I will attach more technical descriptions.

Virtual Memory

If you are a C++ programmer, you know that objects in memory have specific addresses (pointer values).

However, these addresses do not necessarily reflect the physical addresses in memory (addresses in RAM). They represent addresses in virtual memory. The processor has a special module called the MMU (memory management unit), which assists the kernel in mapping virtual memory to physical locations.

This approach has many advantages, but the most fundamental ones are:

  • Performance (for various reasons);
  • Isolation of programs, meaning no program can read from the memory of another program.

What are pages?

Virtual memory is divided into pages. Each individual page points to a specific physical memory; it may point to a portion of RAM or to an address assigned to a physical device, such as a graphics card.

Most pages you deal with either point to RAM or are swapped, meaning they are stored on a hard drive or SSD. The kernel manages the physical location of each page. If access to a swapped page is requested, the kernel halts the thread attempting to access the memory, reads the page from the hard drive/SSD into RAM, and then resumes the execution of the thread.

This process is transparent to the thread, meaning it does not necessarily read directly from the hard drive/SSD. The size of normal pages is 4096 bytes. The size of Hugepages is 2 megabytes.

Translation Lookaside Buffer (TLB)

When a program accesses a certain page of memory, the central processor must know which physical page to read data from (that is, it must have a virtual address map).

In the kernel, there is a data structure (page table) that contains all information about the pages in use. This data structure allows you to map a virtual address to a physical address.

However, the page table is quite complex and operates slowly, so we can't analyze the entire data structure every time a process accesses memory.

Fortunately, our processor has a TLB that caches the mapping of virtual and physical addresses. This means that although we need to analyze the page table on the first attempt to access it, all subsequent accesses to the page can be handled in the TLB, ensuring fast operation.

Since it is implemented as a physical device (which makes it fast in the first place), its capacity is limited. Therefore, if you want to access more pages, the TLB won't be able to store mappings for all of them, causing your program to run much slower.

Hugepages come to the rescue.

So, what can we do to avoid TLB overflow? (We assume that the program still needs the same amount of memory).

This is where Hugepages come into play. Instead of 4096 bytes, requiring only one entry in the TLB, a single TLB entry can now point to a massive 2 megabytes. Let's assume the TLB has 512 entries; without Hugepages, we can map:

4096 b⋅512=2 MB

Whereas with them, we can map:

2 MB⋅512=1 GB

That is why Hugepages are great. They can enhance performance without significant efforts. But there are some substantial caveats.

Swapping Hugepages.

The kernel automatically tracks the usage frequency of each memory page. If there isn't enough physical memory (RAM), the kernel will move less important (infrequently used) pages to the hard disk to free up some RAM for more important pages.
Essentially, the same applies to Hugepages. However, the kernel can only swap entire pages, not individual bytes.

Suppose we have a program like this:

char* mymemory = malloc(2*1024*1024); // Let’s take this as one Hugepage!
// We will fill mymemory with some data
// We will do a lot of other things,
// that will lead to the page replacement of mymemory
// ...
// We will request access only to the first byte
putchar(mymemory[0]); 

In this case, the kernel will have to read a whole 2 megabytes of information from the hard drive/SSD just for you to read one byte. As for regular pages, only 4096 bytes need to be read from the hard drive/SSD.

Therefore, if hugepage is swapped out, its reading occurs faster only if you need to access the entire page. This means that if you are trying to access various parts of memory randomly and just read a couple of kilobytes, you should use regular pages and not worry about anything else.

On the other hand, if you need to access a large portion of memory sequentially, hugepages will improve your performance. However, you need to check this for yourself (rather than with an example of abstract software) and see what works faster.

Memory Allocation

If you're coding in C, you know that you can request almost any small (or almost any large) amount of memory from the heap using malloc(). Let's say you need 30 bytes of memory:

char* mymemory = malloc(30);

To the programmer, it may seem like you are 'requesting' 30 bytes of memory from the operating system and returning a pointer to some virtual memory. But in reality, malloc() is just a C function that internally calls the brk and sbrk functions to request or free memory from the operating system.

However, requesting more and more memory for each allocation is inefficient; it is likely that some segment of memory has already been freed (free()), and we can reuse it. malloc() implements quite complex algorithms for reusing freed memory.

Meanwhile, everything happens unnoticed for you, so why should this concern you? Because the call to free() does not mean that the memory is necessarily returned to the operating system immediately..

There is a concept known as memory fragmentation. In extreme cases, there are segments of the heap that use only a few bytes, while all the space in between has been freed. (free()).

Note that memory fragmentation is an incredibly complex topic, and even minor changes in the program can significantly impact it. In most cases, programs do not cause significant memory fragmentation, but you should keep in mind that if there is a problem with fragmentation in a certain area of the heap, hugepages may only worsen the situation.

Selective application of hugepages.

After reading the article, you have determined which parts of your program can benefit from using hugepages and which cannot. So, should you even enable hugepages?

Fortunately, you can use madvise(), to enable hugepaging only for those areas of memory where it will be beneficial.

To start, check that hugepages are working in madvise() mode, using the instructions at the beginning of the article.

Then, use madvise(), to indicate to the kernel exactly where to use hugepages.

#include <sys/mman.h>
// Аллоцируйте большое количество памяти, которую будете использовать
size_t size = 256*1024*1024;
char* mymemory = malloc(size);
// Просто включите hugepages…
madvise(mymemory, size, MADV_HUGEPAGE);
// … и задайте следующее
madvise(mymemory, size, MADV_HUGEPAGE | MADV_SEQUENTIAL)

Note that this method is simply a suggestion to the kernel for memory management. It does not mean that the kernel will automatically use hugepages for the specified memory.

Refer to the documentation (manpage) madvise, to learn more about memory management and madvise(), this topic has an incredibly steep learning curve. Therefore, if you intend to really understand it well, prepare for reading and testing for several weeks before expecting any positive outcomes.

What to read?

Have a question? Leave a comment!

Source: habr.com

Buy reliable website hosting with DDoS protection, VPS VDS servers 🔥 Buy reliable website hosting with DDoS protection, VPS VDS servers | ProHoster