参考文献:
http://blog.csdn.net/iter_zc/article/details/44308729
https://www.ibm.com/developerworks/cn/linux/l-cn-hugetlb/
cacheline pagecache buffercache 对比
1. Cacheline:cpu中高速缓存(L1,L2)的每一行的大小。取决于cpu,x86的cacheline一般为64B,L1一般为32KB.
a) Pagecahe:主存中页缓存,linux默认的页大小是4KB。
2. Buffercache:块设备的块缓存,例如磁盘,光盘等,但是在程序开发中考虑的很少。
Cacheline深度分析
使公共管理数据的大小设为64B,这样就可以提高cache的命中率
Pagecache深度分析
可以提高页缓存命中率
a) 顺序读写磁盘
b) 每次访问的数据大小<4KB
总结
在 Linux 操作系统上运行内存需求量较大的应用程序时,由于其采用的默认页面大小为 4KB,因而将会产生较多TLB Miss 和缺页中断,从而大大影响应用程序的性能。当操作系统以2MB 甚至更大内存作为分页的单位时,将会大大减少TLB Miss 和缺页中断的数量,显著提高应用程序的性能。而linux的默认页面大小对于大部分程序的内存需求应该是够用了。
问题
如果每次需要加载到内存的数据超过了4KB,怎么提高页缓存的命中率???
有2种方法:
1.Linux的基于hugetlb特殊的文件系统,需要编译内核的时候设置内核参数hugetlb。。。。
2.简单的文件操作接口,如mmap
mmap简单介绍+虚拟存储器简单回顾
内存映射mmap是Linux内核的一个重要机制,它和虚拟内存管理以及文件IO都有直接的关系。
虚拟页(页表)的三种状态:
① 未分配虚拟页,没有对应到具体的页表项
② 已分配虚拟页,未映射到物理页
③ 已分配虚拟页,已映射到物理页
mmap要么映射到一个后备文件,要么映射到一个匿名文件。操作系统分配物理内存时实际用到了匿名文件的mmap。
c代码示例
// 后备文件的共享映射
fd = open("/home/xxx/a.txt", O_RDWR)
addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARD, fd, 0)
// 匿名文件的私有映射
fd = open("/dev/zero", O_RDWR)
addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)
mmap的4种类型
mmap分为有后备文件的映射和匿名文件(不需要关心文件)的映射,这两种映射又有私有映射和共享映射之分,所以mmap可以创建4种类型的映射
1. 后备文件的共享映射,多个进程的vm_area_struct指向同一个物理内存区域,一个进程对文件内容的修改,会被其他进程可见。对文件内容的修改会被写回到后备文件。(也是linux下共享内存区的一种实现)
2. 后备文件的私有映射,多个进程的vm_area_struct指向同一个物理内存区域,采用写时拷贝的方式,当一个进程对文件内容做修改,不会被其他进程看到。另外对文件内的修改也不会被写回到后备文件。当内存不够需要进行页回收时,私有映射的页被交换到交换区。一般用在加载共享代码库
3. 匿名文件的共享映射,内核创建一个初始都是0的物理内存区域,然后多个进程的vm_area_struct指向这个共享的物理内存区域,对该区域内容的修改对所有进程可见。匿名文件在页回收时被交换到交换区。(也是linux下共享内存区的一种实现)
4. 匿名文件的私有映射,内核创建一个初始都是0的物理内存区域,对该区域内容的修改只对创建者进程可见。匿名文件在页回收时被交换到交换区。
内存映射的用途很多,比如
1. 后备文件的共享映射可以用作内存映射IO来对大文件进行操作
1. 普通文件复制2次,内存映射mmap复制一次
2. 普通文件是堆内操作,内存映射是堆外操作
3. 需要注意的是内存映射IO涉及到内核的很多操作,比如vm_area_struct的创建,页表的修改等等,比普通IO的操作更复杂。小文件的读写使用普通IO更合适
2. 后备文件的私有映射可以用作共享库二进制文件代码段,数据段的加载
3. 匿名文件的共享映射可以用作fork时让父子进程共享匿名映射分配的内存
4. 匿名文件的私有映射可以用作进程的私有内存分配
Malloc :内存对堆的管理
malloc()底层是用了匿名文件的私有映射来分配大块内存。
内核对堆空间的分配主要是brk系统调用,brk系统调用本质上也是利用了匿名文件私有映射,分配初始化0的物理内存页,建立vm_area_struct,然后更新页表结构。brk系统调用分配的内存最小单位是页,需要按页对齐,从start_brk位置向上扩展,也就是说从内核的角度来说,每次对堆空间的分配最小就是一页,更细粒度的字节内存空间分配由C语言标准库实现的。