潇湘夜雨移动版

主页 > 系统 >

内存、IO、网络优化

一、内存优化
1、内存区域划分:
32bits: ZONE_DMA, ZONE_NORMAL, ZONE_HIGHMEM
64bits: ZONE_DMA, ZONE_DMA32, ZONE_NORMAL
通常32位Linux内核地址空间划分0~3G为用户空间,3~4G为内核空间。注意这里是32位内核和64位内核地址空间划分是不同的。
 
2、MMU
MMU是Memory Management Unit的缩写,中文名是内存管理单元,它是
中央处理器(CPU)中用来管理虚拟存储器、物理存储器的控制线路,同
时也负责虚拟地址映射为物理地址,以及提供硬件机制的内存访问授权,多用户多进程操作系统。
10bit, 10bit, 12bit PTE
 
3、TLB
3.1 TLB介绍
TLB是一个内存管理单元用于改进虚拟地址到物理地址转换速度的缓存.
TLB是位于内存中的页表的cache,如果没有TLB,则每次取数据都需要两次访问内存,即查页表获得物理地址和取数据.
当处理 器要在主内存寻址时,不是直接在内存的物理地址里查找的,而是通
过一组虚拟地址转换到主内存的物理地址,TLB就是负责将虚拟内存地址翻译
成实际的物理内 存地址,而CPU寻址时会优先在TLB中进行寻址。处理器的性
能就和寻址的命中率有很大的关系。
 
3.2 TLB优化——hugepage
1>HugePage的大小
一般的内存页大小为4kB,可以通过命令:getconf PAGE_SIZE 来查看,一般是4096Byte
huge page 的大小取决于所使用的操作系统的内核版本以及不同的硬件平台
[root@hadoop1 ~]#  cat /proc/meminfo | grep -i huge #查看
AnonHugePages:     96256 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB #当前大页面大小
参数介绍:
HugePages_Total: Hugepage的页面数量
HugePages_Free: 剩余的页面数量
HugePages_Rsvd: 被分配预留但是还没有使用的page数目
HugePages_Surp:HugePages_Total减去/proc/sys/vm/nr_hugepages中的值(我对这个理解也不很清楚)。
Hugepagesize: 每单位数量大小
2>设置了多少的huge page,free内存就会被使用多少。
  比如:我使用sysctl vm.nr_hugepages=1024 之后,free命令可以看到free的内存会减少2048MB。(这也和Hugepagesize的大小有关)
3>使用Hugepages的内存页是不会被交换出去到磁盘的,永远常驻在内存中,所以也减少了内存页交换的额外开销。
使用hurgepage的内存不能被其他的进程使用,所以,一定要合理设置这个值,避免造成浪费。使用超过8G物理内存的系统,有人推荐使用HugePage。
HugePages_Free - HugePages_Rsvd部分的内存是浪费的,且不能被其他程序使用。在实际应用中,尽可能让HugePages_Free - HugePages_Rsvd=0
4>HugePage的好处:
  大大提高了CPU cache中存放的page table所覆盖的内存大小,从而提高了TLB命中率。进程的虚拟内存地址段先连接
  到page tables然后再连接到物理内存。所以在访问内存时需要先访问page tables得到虚拟内存和物理内存的映射关系,
  然后再访问物理内存。CPU cache中有一部分TLB(Translation Lookaside Buffer)用来存放部分page table以提高这种
  装换的速度。因为page size变大了,所以同样大小的TLB,所覆盖的内存大小也变大了。提高了TBL命中率,也就是提
  高了地址转换的速度。
  系统进程是通过虚拟地址访问内存,但是CPU必须把它转换程物理内存地址才能真正访问内存。为了提高这个转换效率,
  CPU会缓存最近的虚拟内存地址和物理内存地址的映射关系,并保存在一个由CPU维护的映射表中。为了尽量提高内存
  的访问速度,需要在映射表中保存尽量多的映射关系。
5>Linux kernel 2.6.X 通过hugetlbfs文件系统对Huge pages进行了支持。当然Windows也有相应的支持,此处暂不详述。
6>设置huge pages
  首先mount一个hugetlbfs文件系统: mount -t hugetlbfs hugetlbfs /dev/hugepages
  然后为huge pages保留一定数量的内存:sysctl vm.nr_hugepages=1024
  (另一个操作方法,在/etc/sysctl.conf加入如下配置就可以:vm.nr_hugepages=1024  修改后,用命令sysctl -p 使得设置生效)
  (或者,改动linux启动的grub参数也是可以的,加上 hugepages=1024 这样的参数)
7>KVM如何让guest使用huge pages ?
  首先,让host开启huge pages(像上面那样设置)
  在qemu启动时加上参数,示例:qemu-system-x86_64 -m 2048 -hda /mnt/rhel6.img -mem-path /dev/hugepages
  如果是用libvirt来启动KVM的,那么需要在启动guest的XML配置文件中添加如下的参数:
    <memoryBacking>
    <hugepages/>
    </memoryBacking>   (启动guest后,可以发现,在host中的cat /pro/meminfo看到的HugePages_Free数量有所减少)
8>很多Oracle DBA对hugepages比较关系的,他们也写了些关于huge pages的东西,可以看看后面的参考资料,有DBA建议将huge pages的大小设置为SGA的大小。
 
4 strace命令
strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。
strace COMMAND: 查看命令的syscall
strace -p PID: 查看已经启动进程的syscall
 
-c: 只输出其概括信息;
-o FILE: 将追踪结果保存至文件中,以供后续分析使用;
示例:
[root@node3 mycat]# strace  cat version.txt #追踪命令的执行过程
execve("/bin/cat", ["cat", "version.txt"], [/* 26 vars */]) = 0
brk(0)                                  = 0x971000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f27d9b6e000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=51699, ...}) = 0
mmap(NULL, 51699, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f27d9b61000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY)      = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\356\1s<\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1926480, ...}) = 0
mmap(0x3c73000000, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3c73000000
mprotect(0x3c7318a000, 2097152, PROT_NONE) = 0
mmap(0x3c7338a000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18a000) = 0x3c7338a000
mmap(0x3c7338f000, 18696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3c7338f000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f27d9b60000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f27d9b5f000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f27d9b5e000
arch_prctl(ARCH_SET_FS, 0x7f27d9b5f700) = 0
mprotect(0x3c7338a000, 16384, PROT_READ) = 0
mprotect(0x3c72a1f000, 4096, PROT_READ) = 0
munmap(0x7f27d9b61000, 51699)           = 0
brk(0)                                  = 0x971000
brk(0x992000)                           = 0x992000
open("/usr/lib/locale/locale-archive", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=99154480, ...}) = 0
mmap(NULL, 99154480, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f27d3cce000
close(3)                                = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
open("version.txt", O_RDONLY)           = 3
fstat(3, {st_mode=S_IFREG|0777, st_size=219, ...}) = 0
read(3, "BuildTime  2016-09-29 15:30:36\nG"..., 32768) = 219
write(1, "BuildTime  2016-09-29 15:30:36\nG"..., 219BuildTime  2016-09-29 15:30:36
GitVersion   66fe155cad660dc8ac7506331253afbb43540057
MavenVersion 1.5.1-RELEASE
GitUrl https://github.com/MyCATApache/Mycat-Server.git
MyCatSite http://www.mycat.org.cn
QQGroup 106088787
) = 219
read(3, "", 32768)                      = 0
close(3)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
[root@node3 mycat]# strace -c cat version.txt #追踪命令执行的统计信息
BuildTime  2016-09-29 15:30:36
GitVersion   66fe155cad660dc8ac7506331253afbb43540057
MavenVersion 1.5.1-RELEASE
GitUrl https://github.com/MyCATApache/Mycat-Server.git
MyCatSite http://www.mycat.org.cn
QQGroup 106088787
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 0.00    0.000000           0         3           read
 0.00    0.000000           0         1           write
 0.00    0.000000           0         4           open
 0.00    0.000000           0         6           close
 0.00    0.000000           0         5           fstat
 0.00    0.000000           0         9           mmap
 0.00    0.000000           0         3           mprotect
 0.00    0.000000           0         1           munmap
 0.00    0.000000           0         3           brk
 0.00    0.000000           0         1         1 access
 0.00    0.000000           0         1           execve
 0.00    0.000000           0         1           arch_prctl
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000                    38         1 total
 
5. slab分配器
5.1 slab介绍
 slab分配器是Linux内存管理中非常重要和复杂的一部分,其工作是针对一些经常分配并释放
 的对象,如进程描述符等,这些对象的大小一般比较小,如果直接采用伙伴系统来进行分配
 和释放,不仅会造成大量的内碎片,而且处理速度也太慢。而slab分配器是基于对象进行管
 理的,相同类型的对象归为一类(如进程描述符就是一类),每当要申请这样一个对象,slab
 分配器就从一个slab列表中分配一个这样大小的单元出去,而当要释放时,将其重新保存在
 该列表中,而不是直接返回给伙伴系统。slab分配对象时,会使用最近释放的对象内存块,
 因此其驻留在CPU高速缓存的概率较高。
5.2 slab的作用
1>降低微型内存对象的系统开销
slab(默认已使用)
2>缩减慢速子系统的服务时间 (责任编辑:liangzh)