一.Linux内存
1. Linux内存管理的硬件结构
图1
-
- CPU最开始访问虚拟地址:
访问数据前首先要获得数据的访问地址。物理地址
1.2.MMU (完成地址的转换)
1.2.1. TLB:存储页表转换的表项(TLB命中)
缓存了上一次虚拟地址访问物理地址的记录,便于加快访问速度。如果没有命中上次的记录则只能直接访问存储器的页表了(成为TLB Miss),
1.2.2. MMU访问一级缓存
当虚拟地址跟物理地址转换完成后则可以到缓存中查找是否存在访问的数据
物理索引和物理标签的方式(PIPT),上图访问缓存的方式是通过地址编码的方式来访问。
1.2.2.1. 访问地址的方式会分成三个部分:
- 偏移域
- 索引域
- 标记域
1.2.3.MMU访问二级缓存
A.如果一级缓存没有找到则继续查找二级缓存,当二级缓存也没有数据时最后访问主存储器。
B.当系统内存短缺时,Linux有个页面回收的机制,把常用的匿名页面放到Swap分区中,以便腾出物理内存。
2. 内存地址分类
内存的分页:按需分配
2.1. 物理地址
2.2. 虚拟地址
包含:线性地址,逻辑地址
2.2.1. 逻辑地址
和段相关的,是段的偏移地址
2.2.2. 线性地址
3. 虚拟地址和物理地址的转换
3.1.
即图1中MMU单元是如何访问页表的
图2(虚拟地址和物理地址转换)
3.2.缺页中断
即虚拟地址到物理地址的映射关系
3.2.1.匿名页面:
3.2.2. page cache :关联具体缓存的页面
3.2.3. 页面分配器/伙伴算法
3.2.3.slab机制
当内存短缺时会使用slab机制分配页面
3.2.4. 页面回收
A.当内存短缺时,通常是匿名页面和page cache ,系统有一个内核守护线程,当内存减少到一个阈值时就会被唤醒。
通常使用最近最少使用算法回收
LRU(List resontory used ,最近最少使用 )匿名页面和page cache 通常存放在该链表中。列表又分为:
B.匿名页面是不能被drop掉,是私有数据,要写到交换分区中:Swap ,当进程需要这些数据时,缺页中断会重新把Swap 中的数据读取到匿名页面中
3.2.5. 反向映射
老的内核版本:页面回收,页面所有的用户定义vma 的链接断开,
3.2.6. Huge Page (大页 2M—1G)
减少页面访问次数
3.2.7. 页迁移
3.2.8.内存规整
调整内存空间,管理碎片内存。
实现原理:room的扫描器,从头部向尾部扫描,有哪些页面可以迁移。可以迁移到空闲页面,以便腾出大的物理空间。
3.2.9. OOM
当以上所有内存回收策略全部失败后只能进行内存的回收。
二.Linux内存管理工具
1. JVM与Linux glibc
1.1. 虚拟内存占用
Linux glibc >= 2.10 (RHEL 6) malloc may show excessive virtual memory usage)
通过export MALLOC_ARENA_MAX=4可以解决VSZ占用过高的问题
1.2.pmap 查看进程的内存分配
pmap –d –x PID
1.3. gdb分析内存块:
gdb --batch --19774 75 -ex "dump memory map.dump 0x7f2bceda1000 0x7f2bcef2b000
1.4. perf开启监控栈函数调用
官方安装地址介绍:
https://www.fosslinux.com/7069/installing-and-using-perf-in-ubuntu-and-centos.htm
https://blog.csdn.net/zl1zl2zl3/article/details/82498125
Perf 主要是性能分析工具
1.4.1 分析命令
perf record -g -p 19774 ( 生成文件 )
perf report -I perf.data
perf mem report -i perf.data
1.4.1.1 内存分析结果
1.4.1.2 结果参数介绍
A.Samples:
B. Symbol:
C. Shared Object :
Data Symbol :
1.4.2. CPU 分析
1.4.2.1.命令
perf record -g -e cpu-clock ./perf_r
生成perf.data 由于我们程序是cpu是cpu密集型,所有我只关注了cpu始终(-e cpu-clock )
perf report -g 读取perf.data文件
1.4.2.2.
perf record -F 99 –p PID
1.5.nmon 性能检测工具
1.5.1. 下载
wget http://sourceforge.net/projects/nmon/files/download/nmon_x86_12a.zip/download
需要查看当前系统版本适合下载对应的nmon版本,参考官网
1.5.2.解压
unzip download #此处要留意,下载的包是存在 “download”目录下
1.5.3. 增加权限并修改位置
chmod +x nmon_x86_rhel52
mv nmon_x86_rhel52 /usr/bin/nmon
1.5.4. 启动nmon
直接执行[root@XXX]# nmon
1.5.5. 问题
注意** 有时会报 nmon: error while loading shared libraries: libncurses.so.5: cannot open shared object file: No such file or directory 的错误,是加载共享库时找不到文件,需要重新下载。
yum install ncurses-devel.i686 -y
下载完成就可以打开 nmon视图了
1.5.6. 显示命令
命令 |
说明 |
c |
提供关于物理CPU使用的详细信息 |
m |
提供内存使用的详细信息:系统(内核)和进程,活动虚拟内存 |
d |
提供关于磁盘,磁盘类型大小,可用空间,卷组,适配器等更详细的信息 |
t |
当前进程详细情 |
P |
Paging space 使用情况 |
k |
显示内核信息 |
+ |
Nmon 结果保存为文件 |
1.5.7. 各个命令结果集解释说明
1.5.7.1. CPU命令结果集
1.6.火焰图
工具地址:https://github.com/brendangregg/FlameGraph.git
2. Linux 系统内存管理
2.1. brk 函数 /sbrk 函数
Heap内存区的管理
Linux的运行时堆由malloc 创建。
在高并发请求的条件下容易产生内存碎片,
2.2.mmap/unmap
Glibc 会事先分配一段内存,eg:128K,减少对系统函数的调用
2.3. tcmalloc
3.内存池
3.1. ZMQ内存池
A.预读,预取
B.lock-free
C. 动态调整内存块
D.利用即将释放的内存块