一、madvise函数
madvise函数是Linux系统提供的一个操作系统调用(system call),用于控制系统内存管理。调用madvise函数可以对指定的内存区域设置适当的使用策略,从而优化系统整体性能和内存利用率。
使用方法如下:
int madvise(void *addr, size_t len, int advice);
其中addr参数指向欲改变的内存区域的首地址;len参数代表欲改变内存区域的大小(以字节为单位);advice参数可选,表示这段内存的用途,例如准备随后写入数据,可以选择MADV_WILLNEED等。
二、madvise是什么意思
madvise函数的主要作用是告诉内核,此区域的使用情况。它告诉内核在下一次内存缺页异常(Page Fault)发生时如何处理这个区域的页面。在没有使用madvise函数的情况下,当进程访问不存在于内存中的虚拟地址时,内核将会生成一个Page Fault异常,并进入到中断处理程序进行处理。在处理结束后,内核会重载页面到内存或者把页面标识为无效。这个过程需要花费一定的时间。madvise的目标是为了减少这个时间。
下面是几种advice参数的作用:
- MADV_NORMAL:默认参数,没有特殊含义。
- MADV_RANDOM:告诉内核此区域的访问方式是随机的。
- MADV_SEQUENTIAL:告诉内核此区域的访问方式是顺序访问。
- MADV_WILLNEED:告诉内核此区域需要预加载。常用于进程即将使用的数据,可以减少Page Fault的产生。
- MADV_DONTNEED:告诉内核此区域的数据即将不再使用,一旦内存紧张,可以把这块内存立即释放。
三、madvise变向缺页检测怎么过
madvise变向缺页检测,是madvise优化内存利用率的一种技术。在使用大型内存区域时,很容易遇到内存限制的问题。如果采用传统的缺页处理方案,系统可能会把程序整个挂起来等待内存分配完成,这种情况下,程序的性能会受到很大的影响。
madvise变向缺页检测的原理是先将内存区域设为内存映射区(或暂时存储提供页面的密集数组)。当访问内存区域时,操作系统会发现它并没有分配实际内存,此时,系统并不立即分配内存,而是等待其他内存释放后再分配。这样可以避免程序阻塞,提高程序性能,减少Page Fault数。
mmap+hugepage优化实例1
#include #include #include #include #include #include #include #include int main (void) { int fd; void* p = mmap(NULL, 2*1024*1024, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_HUGETLB, -1, 0); if (p == MAP_FAILED) { printf("errno=%d\n",errno); return -1; } printf("virtual space is allocated\n"); while (getchar()); munmap(p, 2*1024*1024); return 0; }
mmap+hugepage优化实例2
void* alloc_hugepage(size_t size) { void* p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_HUGETLB, -1, 0); if (p == MAP_FAILED) { return NULL; } return p; } int main() { void* p = alloc_hugepage(2*1024*1024); if (p == NULL) { printf("alloc hugepage failed!\n"); return -1; } printf("virtual space is allocated.\n"); while (getchar()); munmap(p, 2*1024*1024); printf("virtual space is freed.\n"); return 0; }
四、madvise hugepage是什么
madvise hugepage是Linux内核提供的一种优化内存利用率的技术。由于一些特殊的应用程序需要使用大量内存,但一般的系统进程只会使用小块内存,所以Linux内核提供了HugePage技术。HugePage允许一个进程使用大块的内存页,这些页的大小都是2MB或者1GB。这些大页(或超级页面)虽然没有能很好地减少缺页异常,但它们极大地减少了TLB缺失率,从而使程序的性能得到提升。
使用HugePage的步骤是:
- 检查系统是否支持HugePage(内核版本大于2.6.32)。
- 检查系统是否配置了HugePage,如果没有,需要手动修改内核参数。
- 按照HugePage的方式编写程序。
HugePage可以通过标准的mmap调用获得。在系统启动时,机器统计了可以用于映射的物理内存数,然后自动创建一定数量的超级页面。
madvise+hugepage优化实例
#include #include #include #define LENGTH (2*1024*1024) #define HUGE_SIZE (2*1024*1024) #define HUGE_MASK (HUGE_SIZE - 1) int main(int argc, char** argv) { void* ptr; int pagemap_fd; char pagemap_file[BUFSIZ]; int page_frame_number, pageshift; if (argc == 2) { ptr = mmap(NULL, LENGTH, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if(ptr == MAP_FAILED) { perror("Memory map failed"); return EXIT_FAILURE; } page_frame_number = ((unsigned long)ptr & ~(HUGE_MASK)) >> pageshift; pageshift = getpagesize(); sprintf(pagemap_file, "/proc/self/pagemap"); pagemap_fd = open(pagemap_file, O_RDONLY); if(pagemap_fd > pageshift; pageshift = getpagesize(); sprintf(pagemap_file, "/proc/self/pagemap"); pagemap_fd = open(pagemap_file, O_RDONLY); if(pagemap_fd < 0) { perror("Unable to open /proc/self/pagemap"); return EXIT_FAILURE; } if (pread(pagemap_fd, &page_frame_number, sizeof(int), page_frame_number*sizeof(int)) != sizeof(int)) { fprintf(stderr, "Failed to read pagemap\n"); close(pagemap_fd); munmap(ptr, LENGTH); return EXIT_FAILURE; } close(pagemap_fd); printf("page frame number: %d, HugePage\n", page_frame_number); } while (getchar()); munmap(ptr, LENGTH); return EXIT_SUCCESS; }
原创文章,作者:ZKTZ,如若转载,请注明出处:https://www.506064.com/n/134673.html