zoukankan      html  css  js  c++  java
  • 【Debian百科】巨页

    巨页

    为什么使用巨页?

    当一个进程使用一些内存的时候,CPU就把那部分内存标记成已被该进程使用的。为了提高效率,CPU会按4K字节块(它在很多平台上是默认值)分配内存。这些块被称作页。这些页可以被交换到磁盘上,等等。

    因为进程地址空间是虚拟的,CPU和操作系统就得记住哪一页属于哪个进程,存储在什么地方。显然的,拥有的页面越多,就得花费越多的时间去寻找那些内存被映射的地方。如果一个进程使用了1GB的内存,就得查找262144(1GB/4K)个条目。如果一个页表条目占用8字节,那么就得查找2MB(262144*8)。

    当前大多数CPU体系结构支持更大的页(这样CPU/OS要查找的条目就少了),这些页在Linux上被称作巨页(Huge pages),在BSD上被称作超级页(Super Pages),在Windows上被称作大页(Large Pages),它们都是同样的东西。

    目录

    1. 启用HugeTlbPage
    2. limits.conf
    3. Multiple huge page size support
      1. arm64
      2. x86_64
    4. 获取信息
    5. 巨页大小
    6. 工具
    7. 支持巨页的应用
      1. MySQL
      2. Java(Sun, OpenJDK)
      3. Memcached
      4. PostgreSQL
    8. 虚拟化
    9. 参见

    想知道更多关于hugetlbpage的信息,请阅读这篇文档。

    启用HugeTlbPage

    目前,没有标准的方式来启用HugeTlbfs,主要因为FHS(文件系统构架标准)中没有这种虚拟文件系统的相关规定。参见572733。(Fedora把它挂载在/dev/hugepages上了,所以如果你在网上看到一些使用这个位置的例子,就不要惊讶了)

    Debian是从DebianLenny(实际上是从2.6.23)开始支持“巨页表”(HugeTlb)的。在ibm.com上可以找到详细的大页介绍。

    1. 创建一个巨页的用户组,并且获取它的GID(是这个例子,2021),然后把你自己添加到这个组里。
      注意:libvirt并不需要这样做。(参见/etc/libvirt/qemu.conf)
      % groupadd my-hugetlbfs
      
      % getent group my-hugetlbfs
      my-hugetlbfs:x:2021:
      
      % adduser franklin my-hugetlbfs
      Adding user `franklin' to group `my-hugetlbfs' ...
      Adding user franklin to group my-hugetlbfs
      Done. 
    2. 编辑/etc/sysctl.conf,添加这个文本来指定你想要预留的页数(参见pages-size)。
      # Allocate 256*2MiB for HugePageTables (YMMV)
      vm.nr_hugepages = 256
      
      # Members of group my-hugetlbfs(2021) can allocate "huge" Shared memory segment 
      vm.hugetlb_shm_group = 2021 
    3. 给这个文件系统创建一个挂载点。
      % mkdir /hugepages
    4. 添加这一行代码到/etc/fstab(mode=1770准许组内的任何人创建文件,但是不能给彼此之间的文件解除链接或者重命名)。
      hugetlbfs /hugepages hugetlbfs mode=1770,gid=2021 0 0
    5. 重启(这是再内存碎片化之前分配巨页的最可靠方法。并不是必须要重启,你可以尝试执行 sysctl -p 来应用变化。如果 grep "Huge" /proc/meminfo 没有显示所有页面,你可以尝试执行 sync ; echo 3 > /proc/sys/vm/drop_caches (3表示清除页面缓存,dentries和inodes)来释放缓存,然后再次尝试执行 sysctl -p)。

    limits.conf

    你应该配置一个用户可以锁定的内存数量,这样一个应用程序就不会通过锁定所有内存而导致操作系统崩溃。注意并不是只有巨页可以可以被锁定,内存中的任何页面都可以被锁定。你应该允许进程锁定多一点的内存(只是巨页空间)。

    ## Get huge-page size:
    % grep "Hugepagesize:" /proc/meminfo
    Hugepagesize:       4096 kB
    
    ## What's the current limit
    % ulimit -H -l
    64
    
    ## Just add them up... (how many pages do you want to allocate?)

    参见Limits(ulimit -l 和/etc/security/limits.conf中的memlock)。

    Multiple huge page size support

    某些架构(如ia64)可以有多倍的和(或)可配置的(巨)页尺寸。

    (TODO)

    参见:

    • 文件编制中的 hugetlbpage.txt 中的启动参数和挂载选项。

    arm64

    Debian arm64 内核(用4KB标准PAGE_SIZE运行)支持2MB和1GB的 HugeTLB 页大小。一种是在内核命令行上指定参数,从而使启动时预分配1GB的 HugeTLB 页面。下面的文本将预分配10*1GB的巨页。

    hugepagesz=1G hugepages=10

    如果某人决定用 CONFIG_ARM64_64K_PAGES=y 来构建他自己的 Debian arm64 内核,那么只可以使用512MB的 HugeTLB(和THP)页面。这些在运行时可用。

    x86_64

    依据处理器,在 x86_64 架构上至少有两种不同的巨页尺寸:2MB和1GB。如果CPU支持2MB页面,它会在cpuinfo中有 PSE 旗标;如果支持1GB页面,它就会有 PDPE1GB 旗标。/proc/cpuinfo 显示了是否设置了这两种旗标。

    如果下面这个命令返回非空字符串,就支持2MB页面。

    % grep pse /proc/cpuinfo | uniq
    flags           : [...] pse [...]

    如果下面这个命令返回非空字符串,就支持1GB页面。

    % grep pdpe1gb /proc/cpuinfo | uniq
    flags           : [...] pdpe1gb [...]

    如果想要二者都可用,那么可能需要在启动时激活它们。下面的内核启动参数启用1GB页面并且创建了一个1GB页面池。

    hugepagesz=1GB hugepages=1

    在启动后,巨页池看起来像下面这样:

    % hugeadm --pool-list
          Size  Minimum  Current  Maximum  Default
       2097152        0        0        0        *
    1073741824        1        1        1

    获取信息

    你可以用hugeadm获取到一张可用巨页尺寸列表:

    % hugeadm --page-sizes-all
    2097152
    1073741824

    hugeadm也显示每个可用尺寸的已分配数量:

    % hugeadm --pool-list
          Size  Minimum  Current  Maximum  Default
       2097152        0        0        0        *
    1073741824        1        1        1

    另一种获取默认巨页尺寸的当前可用/已用页的方法是查看/proc/meminfo:

    % grep Huge /proc/meminfo 
    HugePages_Total:     256
    HugePages_Free:      256
    HugePages_Rsvd:        0
    HugePages_Surp:        0
    Hugepagesize:       4096 kB

    (想了解关于巨页的更多信息,请阅读文献/vm/hugetlbpage.txt)

    标准Debian内核启用了HUGETLB(Lenny呢?Xen呢?):

    % grep HUGETLB /boot/config-$(uname -r)
    CONFIG_HUGETLBFS=y
    CONFIG_HUGETLB_PAGE=y

    各种运行时设置(参见文献资料)。

    % grep -R "" /sys/kernel/mm/hugepages/ /proc/sys/vm/*huge*
    /sys/kernel/mm/hugepages/hugepages-4096kB/nr_hugepages:256
    /sys/kernel/mm/hugepages/hugepages-4096kB/nr_overcommit_hugepages:0
    /sys/kernel/mm/hugepages/hugepages-4096kB/free_hugepages:256
    /sys/kernel/mm/hugepages/hugepages-4096kB/resv_hugepages:0
    /sys/kernel/mm/hugepages/hugepages-4096kB/surplus_hugepages:0
    /proc/sys/vm/hugepages_treat_as_movable:0
    /proc/sys/vm/hugetlb_shm_group:0
    /proc/sys/vm/nr_hugepages:256
    /proc/sys/vm/nr_overcommit_hugepages:0

    巨页尺寸

    体系架构

    巨页尺寸

    arm64 4K, 2M, 1G(或者64K和512M,如果用CONFIG_ARM64_64K_PAGES=y构建自己的内核的话)
    i386 4M, 4M(在PAE模式下是2M)
    ia64 4K, 8K, 64K, 256K, 1M, 4M, 16M, 256M
    ppc64 4K, 16M

    工具

     libhugetlbfs库提供了简单的访问巨页内存的方式。它还包含一些用户空间工具来提升巨页的易用性,进行环境设置和控制等。

    http://libhugetlbfs.ozlabs.org/
    533708 - ITP: libhugetlbfs -- Initial package request
    http://www.ibm.com/developerworks/wikis/display/LinuxP/libhuge+short+and+simple

    PostgreSQL的HugeTLB(和其他应用)非正式

    http://oss.linbit.com/hugetlb/

    启用巨页的应用程序

    一个应用程序可以通过两种不同的方式分配/使用HugeTlbPage:

    1. 拥有适当的权限下,挂载了hugetlbfs后,使用系统调用mmap;
    2. 共享内存段(在MAP_TLB环境下使用系统调用shmat/shmget或者mmap)必须是一个组成员,配置在/proc/sys/vm/hugetlb_shm_group。

    应用程序

    hugetlbfs

    共享内存

    QEMU/KVM
    MySQL
    Java

    MySQL

    (TODO),参见:

    Linux HugeTLBfs:提升MySQL数据库应用程序性能

    http://www.cyberciti.biz/tips/linux-hugetlbfs-and-mysql-performance.html (未测试)

    Java(Sun, OpenJDK)

    Sun和OpenJDK可以使用大页。

    (TODO)

    总的来说,要启用巨页,似乎得使用 -XX:+UseLargePages 选项运行java。Java堆(-Xmx)的上限尺寸应该可以容纳你预留的巨页;使用 ulimit -l 和/或 /etc/security/limits.conf 中的memlock。

    参见:

    1. 大内存页的Java支持 - Sun:http://java.sun.com/javase/technologies/hotspot/largememory.jsp
    2. 大页内存分配的配置 - Linux上的 Java v6 的 IBM 用户指南:http://publib.boulder.ibm.com/infocenter/javasdk/v6r0/index.jsp?topic=/com.ibm.java.doc.user.lnx.60/user/alloc_large_page.html

    可能的错误:

    • 功能不全的 /proc/sys/kernel/shmmax?
    • 不在组中却定义在 /proc/sys/vm/hugetlb_shm_group
    % java -XX:+UseLargePages 
    Java HotSpot(TM) Server VM warning: Failed to reserve shared memory (errno = 1).
    Java HotSpot(TM) Server VM warning: Failed to reserve shared memory (errno = 22).

     Memcached

    memcached能够使用巨页,请阅读手册页:

    memcached -L

    尝试使用大内存页(如果可用)。增加内存页尺寸可以减少TLB漏掉的数量,并提升性能。为了从操作系统里获取大页,memcached将会把所有的条目缓存分配到一个大页块中。只有你的操作系统支持大页的时候才可用。

    PostgreSQL

    PostgreSQL 从版本9.4开始支持巨页。关于之前的版本,参见上面的hugetlblib

    虚拟化

    巨页虚拟化的一些建议:

    1. 在虚拟机上启用巨页之前,你必须确保你的虚拟化工具可以处理它;
    2. 对于虚拟化工具来说,它的客户端是否支持巨页,和它本身是否支持巨页,可能是两个不同的方面。

    KVM

    (TODO),参见:

    Xen

    (TODO)

    Xen从哪个版本开始支持巨页,还有它如何使用,都不是很清楚。


    说明:本文译自https://wiki.debian.org/Hugepages。由于英语水平有限,语句不通顺处还请谅解。

  • 相关阅读:
    uva 10491 Cows and Cars
    uva 10910 Marks Distribution
    uva 11029 Leading and Trailing
    手算整数的平方根
    uva 10375 Choose and divide
    uva 10056 What is the Probability?
    uva 11027 Palindromic Permutation
    uva 10023 Square root
    Ural(Timus) 1081. Binary Lexicographic Sequence
    扩展欧几里得(求解线性方程)
  • 原文地址:https://www.cnblogs.com/alwu007/p/5609142.html
Copyright © 2011-2022 走看看