大页内存(HugePages)在通用程序优化中的应用

2023-10-27

今天给大家介绍一种比较新奇的程序性能优化方法—大页内存(HugePages),简单来说就是通过增大操作系统页的大小来减小页表,从而避免快表缺失。这方面的资料比较贫乏,而且网上绝大多数资料都是介绍它在Oracle数据库中的应用,这会让人产生一种错觉:这种技术只能在Oracle数据库中应用。但其实,大页内存可以算是一种非常通用的优化技术,应用范围很广,针对不同的应用程序,最多可能会带来50%的性能提升,优化效果还是非常明显的。在本博客中,将通过一个具体的例子来介绍大页内存的使用方法。

       在介绍之前需要强调一点,大页内存也有适用范围,程序耗费内存很小或者程序的访存局部性很好,大页内存很难获得性能提升。所以,如果你面临的程序优化问题有上述两个特点,请不要考虑大页内存。后面会详细解释为啥具有上述两个特点的程序大页内存无效。

1. 背景

       近期一直在公司从事听歌识曲项目的开发,详细内容可参考:基于指纹的音乐检索,目前已上线到搜狗语音云开放平台。在开发的过程中,遇到一个很严重的性能问题,单线程测试的时候性能还能达到要求,但是在多线程进行压力测试的时候,算法最耗时的部分突然变慢了好几倍!后来经过仔细调试,发现最影响性能的居然是一个编译选项-pg,去掉它之后性能会好很多,但是还是会比单线程的性能慢2倍左右,这就会导致系统的实时率达到1.0以上,响应能力严重下降。

       通过更加仔细的分析,我们发现系统最耗时的部分是访问指纹库的过程,但是这部分根本就没有优化余地,只能换用内存带宽更高的机器。换用内存带宽更高的机器确实带来了不少性能的提升,但是还是无法达到要求。就在山重水尽的情况下,无意中看到MSRA的洪春涛博士在微博中提到他们用大页内存对一个随机数组的访问问题进行优化获得了很好的性能提升。然后就向他求助,终于通过大页内存这种方法使系统性能进一步提升,实时率也降到了0.4左右。圆满达成目标!

2. 基于指纹的音乐检索简介

检索过程其实和搜索引擎一样,音乐指纹就和搜索引擎中的关键词等价,指纹库就等价于搜索引擎的后台网页库。指纹库的构造和搜索引擎的网页库也是一样,采用倒排索引形式。如下图:


图1 基于指纹的倒排索引表

只不过指纹都是一个int型的整数(图示只占用了24位),包含的信息太少,所以需要提取很多个指纹完成一次匹配,大约是每秒几千个的样子。每获得一个指纹都需要访问指纹库获得对应的倒排列表,然后再根据音乐id构造一个正排列表,用来分析哪首音乐匹配上,如下图:

图2 统计匹配的相似度

最终的结果就是排序结果最高的音乐。

目前指纹库大约60G,是对25w首歌提取指纹的结果。每一个指纹对应的倒排列表长度不固定,但是有上限7500。正排列表的音乐个数也是25w,每一首音乐对应的最长时间差个数为8192。单次检索的时候会生成大约1000个左右的指纹(甚至更多)。

通过上面的介绍,可以看出基于指纹的音乐检索(听歌识曲)共有三部分:1.提取指纹;2.访问指纹库;3.排序时间差。多线程情况下,这三部分的时间耗费比例大约是:1%、80%和19%,也即大部分时间都耗费在查找指纹库的操作上。更麻烦的一点是,指纹库的访问全部是乱序访问,没有一点局部性可言,所以cache一直在缺失,常规的优化方法都无效,只能换成内存带宽更高的服务器。

不过正是由于上述的特点—耗费内存巨大(100G左右)、乱序访存且访存是瓶颈,导致大页内存特别适合来优化上面遇到的性能瓶颈问题。

3. 原理

大页内存的原理涉及到操作系统的虚拟地址到物理地址的转换过程。操作系统为了能同时运行多个进程,会为每个进程提供一个虚拟的进程空间,在32位操作系统上,进程空间大小为4G,64位系统为2^64(实际可能小于这个值)。在很长一段时间内,我对此都非常疑惑,这样不就会导致多个进程访存的冲突吗,比如,两个进程都访问地址0x00000010的时候。事实上,每个进程的进程空间都是虚拟的,这和物理地址还不一样。两个进行访问相同的虚拟地址,但是转换到物理地址之后是不同的。这个转换就通过页表来实现,涉及的知识是操作系统的分页存储管理。

分页存储管理将进程的虚拟地址空间,分成若干个页,并为各页加以编号。相应地,物理内存空间也分成若干个块,同样加以编号。页和块的大小相同。假设每一页的大小是4K,则32位系统中分页地址结构为:

为了保证进程能在内存中找到虚拟页对应的实际物理块,需要为每个进程维护一个映像表,即页表。页表记录了每一个虚拟页在内存中对应的物理块号,如图三。在配置好了页表后,进程执行时,通过查找该表,即可找到每页在内存中的物理块号。

在操作系统中设置有一个页表寄存器,其中存放了页表在内存的始址和页表的长度。进程未执行时,页表的始址和页表长度放在本进程的PCB中;当调度程序调度该进程时,才将这两个数据装入页表寄存器。

当进程要访问某个虚拟地址中的数据时,分页地址变换机构会自动地将有效地址(相对地址)分为页号和页内地址两部分,再以页号为索引去检索页表,查找操作由硬件执行。若给定的页号没有超出页表长度,则将页表始址与页号和页表项长度的乘积相加,得到该表项在页表中的位置,于是可以从中得到该页的物理块地址,将之装入物理地址寄存器中。与此同时,再将有效地址寄存器中的页内地址送入物理地址寄存器的块内地址字段中。这样便完成了从虚拟地址到物理地址的变换。

图3 页表的作用

由于页表是存放在内存中的,这使CPU在每存取一个数据时,都要两次访问内存。第一次时访问内存中的页表,从中找到指定页的物理块号,再将块号与页内偏移拼接,以形成物理地址。第二次访问内存时,才是从第一次所得地址中获得所需数据。因此,采用这种方式将使计算机的处理速度降低近1/2。

为了提高地址变换速度,可在地址变换机构中,增设一个具有并行查找能力的特殊高速缓存,也即快表(TLB),用以存放当前访问的那些页表项。具有快表的地址变换机构如图四所示。由于成本的关系,快表不可能做得很大,通常只存放16~512个页表项。

上述地址变换机构对中小程序来说运行非常好,快表的命中率非常高,所以不会带来多少性能损失,但是当程序耗费的内存很大,而且快表命中率不高时,那么问题来了。

图4 具有快表的地址变换机构

4. 小页的困境

       现代的计算机系统,都支持非常大的虚拟地址空间(2^32~2^64)。在这样的环境下,页表就变得非常庞大。例如,假设页大小为4K,对占用40G内存的程序来说,页表大小为10M,而且还要求空间是连续的。为了解决空间连续问题,可以引入二级或者三级页表。但是这更加影响性能,因为如果快表缺失,访问页表的次数由两次变为三次或者四次。由于程序可以访问的内存空间很大,如果程序的访存局部性不好,则会导致快表一直缺失,从而严重影响性能。

       此外,由于页表项有10M之多,而快表只能缓存几百页,即使程序的访存性能很好,在大内存耗费情况下,快表缺失的概率也很大。那么,有什么好的方法解决快表缺失吗?大页内存!假设我们将页大小变为1G,40G内存的页表项也只有40,快表完全不会缺失!即使缺失,由于表项很少,可以采用一级页表,缺失只会导致两次访存。这就是大页内存可以优化程序性能的根本原因—快表几乎不缺失!

       在前面我们提到如果要优化的程序耗费内存很少,或者访存局部性很好,大页内存的优化效果就会很不明显,现在我们应该明白其中缘由。如果程序耗费内存很少,比如只有几M,则页表项也很少,快表很有可能会完全缓存,即使缺失也可以通过一级页表替换。如果程序访存局部性也很好,那么在一段时间内,程序都访问相邻的内存,快表缺失的概率也很小。所以上述两种情况下,快表很难缺失所以大页内存就体现不出优势来。

5. 大页内存的配置和使用

       网上很多资料在介绍大页内存的时候都会伴随它在Oracle数据库中的使用,这会让人产生一种错觉:大页内存只能在Oracle数据库中使用。通过上面的分析,我们可以知道,其实大页内存是一种很通用的优化技术。它的优化方法就是避免快表缺失。那么怎么具体应用呢,下面详细介绍使用的步骤。

1. 安装libhugetlbfs库

       libhugetlbfs库实现了大页内存的访问。安装可以通过apt-get或者yum命令完成,如果系统没有该命令,还可以从官网下载。

2. 配置grub启动文件

      这一步很关键,决定着你分配的每个大页的大小和多少大页。具体操作是编辑/etc/grub.conf文件,如图五所示。


图5 grub.conf启动脚本

具体就是在kernel选项的最后添加几个启动参数:transparent_hugepage=never default_hugepagesz=1G hugepagesz=1Ghugepages=123。这四个参数中,最重要的是后两个,hugepagesz用来设置每页的大小,我们将其设置为1G,其他可选的配置有4K,2M(其中2M是默认)。如果操作系统版本太低的情况下,可能会导致1G的页设置失败,所以设置失败请查看自己操作系统的版本。hugepages用来设置多少页大页内存,我们的系统内存是128G,现在分配123G用来专门服务大页。这里需要注意,分配完的大页对常规程序来说是不可见的,例如我们的系统还剩余5G的普通内存,这时我如果按照常规方法启动一个耗费10G的程序就会失败。修改完grub.conf后,重启系统。然后运行命令cat /proc/meminfo|grep Huge命令查看大页设置是否生效,如果生效,将会显示如下内容:

图6 当前的大页耗费情况

我们需要关注其中的四个值,HugePages_Total表示目前总共有多少个大页,HugePages_Free表示程序运行起来之后还剩余多少个大页,HugePages_Rsvd表示系统当前总共保留的HugePages数目,更具体点就是指程序已经向系统申请,但是由于程序还没有实质的HugePages读写操作,因此系统尚未实际分配给程序的HugePages数目。Hugepagesize表示每个大页的大小,在此为1GB。

       我们在实验中发现一个问题,Free的值和Rsvd的值可能和字面意思不太一样。如果一开始我们申请的大页不足以启动程序,系统就会提示如下错误:

ibhugetlbfs:WARNING: New heap segment map at 0x40000000 failed: Cannot allocate memory

此时,再次查看上述四个值会发现这样的情况:HugePages_Free等于a,HugePages_Rsvd等于a。这让人感到很奇怪,明明还有剩余的大页,但是系统报错,提示大页分配失败。经过多次尝试,我们认为Free中应该是包括Rsvd的大页的,所以当Free等于Rsvd的时候其实已经没有可用的大页了。Free减Rsvd才是真正能够再次分配的大页。例如,在图六中还有16个大页可以被分配。

具体应该分配多少个大页合适,这个需要多次尝试,我们得到的一个经验是:子线程对大页的使用很浪费,最好是所有的空间都在主线程分配,然后再分配给各个子线程,这样会显著减少大页浪费。

3. mount

执行mount,将大页内存映像到一个空目录。可以执行下述命令:

if [ ! -d /search/music/libhugetlbfs ]; then
    mkdir /search/music/libhugetlbfs
fi
mount -t hugetlbfs hugetlbfs /search/music/libhugetlbfs

4. 运行应用程序

为了能启用大页,不能按照常规的方法启动应用程序,需要按照下面的格式启动:

HUGETLB_MORECORE=yesLD_PRELOAD=libhugetlbfs.so ./your_program

这种方法会加载libhugetlbfs库,用来替换标准库。具体的操作就是替换标准的malloc为大页的malloc。此时,程序申请内存就是大页内存了。

按照上述四个步骤即可启用大页内存,所以启用大页还是很容易的。

6. 大页内存的优化效果

如果你的应用程序乱序访存很严重,那么大页内存会带来比较大的收益,正好我们现在做的听歌识曲就是这样的应用,所以优化效果很明显,下面是曲库为25w时,启用大页和不启用大页的程序性能。

可以看出,启用大页内存之后,程序的访问时间显著下降,性能提升接近50%,达到了性能要求。

7. 大页内存的使用场景

任何优化手段都有它适用的范围,大页内存也不例外。前面我们一直强调,只有耗费的内存巨大、访存随机而且访存是瓶颈的程序大页内存才会带来很明显的性能提升。在我们的听歌识曲系统中,耗费的内存接近100G,而且内存访问都是乱序访问,所以才带来明显的性能提升。网上的例子一直在用Oracle数据库作为例子不是没有道理的,这是因为Oracle数据库耗费的内存也很巨大,而且数据库的增删查改也缺乏局部性。数据库背后的增删查改基本上是对B树进行操作,树的操作一般缺少局部性。

什么样的程序局部性较差呢?我个人认为采用哈希和树策略实现的程序往往具有较差的访存局部性,这时如果程序性能不好可以尝试大页内存。相反,单纯的数组遍历或者图的广度遍历等操作,具有很好的访存局部性,采用大页内存很难获得性能提升。本人曾经尝试在搜狗语音识别解码器上启用大页内存,希望可以获得性能提升,但是效果令人失望,没有提升反而导致性能降低。这是因为语音识别解码器从本质上来讲就是一个图的广搜,具有很好的访存局部性,而且访存不是性能瓶颈,这时采用大页内存可能会带来其他开销,导致性能下降。

8. 总结

本博客以听歌识曲的例子详细介绍了大页内存的原理和使用方法。由于大数据的兴盛,目前应用程序处理的数据量越来越大,而且数据的访问越来越不规整,这些条件给大页内存的使用带来了可能。所以,如果你的程序跑得慢,而且满足大页内存的使用条件,那就尝试一下吧,反正很简单又没损失,万一能带来不错的效果呢。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

大页内存(HugePages)在通用程序优化中的应用 的相关文章

  • (笔试前准备)字符串匹配算法总结

    我想说一句 我日 我讨厌KMP KMP虽然经典 但是理解起来极其复杂 好不容易理解好了 便起码来巨麻烦 老子就是今天图书馆在写了几个小时才勉强写了一个有bug的 效率不高的KMP 特别是计算next数组的部分 其实 比KMP算法速度快的算法
  • Qt——用于表格QTableView的模型

    如果想使用表格来呈现数据 Qt提供了一个方便的部件QTableWidget 但是直接用它实现一些功能可能比较困难 这里将介绍一种强大 灵活的方式来操作表格 一 模型 视图架构 在这个架构中 模型用于存储数据 视图用于呈现数据 除此之外 还有
  • Hash table and application in java

    查找的效率取决于在查找是比较的次数 次数越少效率越高 反之越低 最理想的情况是无需比较 一次存取便能找到所查找的记录 根据对应关系f找到给定值K的像f K hash function 应运而生 由此思想建的表称为hash table 集合h
  • JavaScript实现数据结构 -- 链表

    文章目录 链表 链表的特点 链表和数组的区别 JS模拟链表 遍历链表 插入节点 删除节点 链表应用 删除链表中的节点 leetcode 237 思路 代码 反转链表 leetcode 206 思路 代码 链表 链表和数组一样是有多个元素组成
  • 用 Java 实现的八种常用排序算法

    八种排序算法可以按照如图分类 前置知识 1 算法稳定性 在一个序列中 能保证两个相等的数 经过排序之后 其在序列的前后位置顺序不变 A1 A2 排序前 A1 在 A2 前面 排序后 A1 还在 A2 前面 2 时间复杂度 时间复杂度是用于衡
  • 逆波兰表达式求值(C语言实现)

    实验项目 从文本文件输入任意一个语法正确的 中缀 表达式 显示并保存该表达式 利用栈结构 把上述 中缀 表达式转换成后缀表达式 并显示栈的状态变化过程和所得到的后缀表达式 利用栈结构 对上述后缀表达式进行求值 并显示栈的状态变化过程和最终结
  • MYSQL篇——性能调优专题

    MYSQL是业界最常使用的数据库 本文以5 7为主 从数据结构到性能调优阐述 深入理解mysql 但是本文只是九牛一毛 若对MYSQL感兴趣建议阅读源码 官方文档 文章目录 MYSQL调优篇 深入理解Mysql索引底层数据结构与算法 Exp
  • 数据结构之图的两种遍历实现(C语言版)

    上一期文章分享完了图的两种遍历方式 也是两种很重要的算法 DFS和BFS 这两种算法的应用和重要性我就不多说了 内行的人懂的都懂 今天这文章重要就是来上机实现这两种算法 又由于这两种算法都可以由邻接矩阵和邻接表来表示 博主分享的代码都是上机
  • 链表面试题(一):反转链表的算法实现

    关于链表的考察 链表是面试里面经常涉及到的考点 因为链表的结构相比于Hashmap Hashtable Concurrenthashmap或者图等数据结构简单许多 对于后者更多面试的侧重点在于其底层实现 比如Hashmap中Entry
  • 15 个高级 Java 多线程面试题及回答

    在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分 如果你想获得任何股票投资银行的前台资讯职位 那么你应该准备很多关于多线程的问题 在投资银行业务中多线程和并发是一个非常受欢迎的话题 特别是电子交易发展方面相关的 他们会问面试
  • 数据结构——计算节点个数和二叉树高度(C语言版)

    摘自 数据结构 计算节点个数和二叉树高度 C语言版 作者 正弦定理 发布时间 2020 12 12 23 27 09 网址 https blog csdn net chinesekobe article details 111086664
  • 插入排序超详解释,一看就懂

    目录 一 插入排序的相关概念 1 基本思想 2 基本操作 有序插入 二 插入排序的种类 三 直接插入排序 1 直接插入排序的过程 顺序查找法查找插入位置 2 使用 哨兵 直接插入排序 四 直接插入排序算法描述 五 折半插入排序 1 查找插入
  • 索引优化之Explain 及慢查询日志

    索引 本质是数据结构 简单理解为 排好序的快速查找数据结构 以索引文件的形式存储在磁盘中 目的 提高数据查询的效率 优化查询性能 就像书的目录一样 优势 提高检索效率 降低IO成本 排好序的表 降低CPU的消耗劣势 索引实际也是一张表 该表
  • 用两个栈实现队列

    目录 一 栈的基本结构及其接口 二 我的队列结构定义 三 我的队列创建及其初始化 四 我的队列入队 五 我的队列出队 六 我的队列取队头元素 七 我的队列判空 八 我的队列销毁 一 栈的基本结构及其接口 栈的结构定义 typedef int
  • 音视频的功耗优化

    前言 在应用中 录制与音视频模块往往是高耗能的模块 设备容易发热 影响体验 什么是功耗优化 手机有多个耗电模块 SOC CPU GPU DDR Display Audio Video Camera WIFI 等 通过参数配置优化 代码优化等
  • 牛客剑指offer刷题其他算法篇

    文章目录 构建乘积数组 题目 思路 代码实现 第一个只出现一次的字符
  • 【数据结构入门精讲 | 第二篇】一文讲清算法复杂度

    上篇文章中我们引入了算法 数据结构 数据类型等概念 而要想衡量一个算法与数据结构是否为优质的 就需要一个衡量标准 这个衡量标准也是在我们实现一个好的算法时要遵循的原则 目录 基本概念 渐进性态 渐进性态数学表征 算法复杂度的运算 顺序搜索算
  • Golang拼接字符串性能对比

    g o l a n g golang g o l an g
  • 排序:计数排序

    一 概念 计数排序是非比较排序 是对哈希直接定址法的变形应用 二 思想 利用数组统计相同数据出现的次数 例如整型数据m出现n次 就在数组m位置记录数据为n 最后从头遍历数组打印数据即可 通俗来讲就是 数组下标即为数据 下标所指位置的值即为数
  • 最大流-Dinic算法,原理详解,四大优化,详细代码

    文章目录 零 前言 一 概念回顾 可略过 1 1流网络 1 2流 1 3最大流 1 4残留网络 1 5增广路

随机推荐

  • Elasticsearch 5.4.x 版本的 scroll demo用法

    要使用 Java 实现 Elasticsearch 5 4 x 的滚动导出 您可以使用 Elasticsearch 的 Java 高级客户端进行操作 以下是一个简单的示例代码 首先 您需要确保已经添加了 Elasticsearch 的 Ja
  • 100g光模块厂家排名_交换机如何通过光模块实现100G与10G/25G/40G互连?

    QSFP28封装以更小的体积 功耗和价格优势 成为了100G主流光模块 在实际应用中 我们应该如何解决100G端口与40G 25G 10G端口互连的需求呢 下面易天光通信 ETU LINK 就给大家介绍几种常见的方案 深圳易天光通信有限公司
  • 科学认识手机充电问题

    目录 导语 关于手机充电 一 纠正几点认知 二 最常见的不良充电习惯 三 正确的充电方式 四 名词解释 导语 关于手机充电 手机电量越来越不耐用 坏的充电习惯会对手机电池产生诸多不良影响 生活中处处皆学问 记录一下 印象深刻 一 纠正几点认
  • pytorch1.7教程实验——分类器训练

    近来想大致总结一下自己知识学习的脉络 发现自己除了大量的工程经验外 对模型算法的研究还是不够深入 而且大多都是关于目标检测方向 锚框或非锚框以及transformer 其他的涉猎不足 认识不够清晰 而且目标检测网络现在要自己单独构建写一个出
  • VMware 安装 win7、win10、MAC 和网络模式VMnet0、VMnet1、VMnet8解释

    VMware 虚拟机安装ghost win7系统方法 http www xitongcheng com jiaocheng xtazjc article 15314 html VMWare 安装Mac OS系统 https blog csd
  • [TRPO] Trust Region Policy Optimization

    论文链接 http proceedings mlr press v37 schulman15 引用 Schulman J Levine S Abbeel P et al Trust region policy optimization C
  • git 保护分支

    问题描述 推送dev分支报错 该分支受保护 git push Enumerating objects 9 done Counting objects 100 9 9 done Delta compression using up to 8
  • 数字技术的优点

    数字技术之所以能够广泛应用 主要因为数字电路与模拟电路相比 有许多优点 抗干扰能力强 数字电路能够在相同的输入条件下精确地产生相同的结果 而模拟电路容易受到温度 电源电压 噪声 辐射和元器件老化等因素的影响 在相同的输入条件下输出结果可能会
  • google翻译的一个错误

    如图 音标标着yi朗读却是ai
  • 需要多表连接查询时该怎么弄(一对多的情况)

    第一步 一对多时应该在 一的类中 添加 多的类 的集合变量 例 通过部门号来查询特定的部门 以及该部门中所有的职工 这时需要在dept类中新增一个集合变量 第二步 开始写具体代码 方法一 通过连接查询 左外连接 一次到位 方法二 分步查询
  • ReactNative ListView + 上拉加载更多 + 下拉刷新

    ListView 上拉加载更多 下拉刷新 一 内容简介 ListView列表在添加了上拉加载更多功能之后再添加下拉刷新 二 代码实现 1 引入原生组件 RefreshControl import ListView View Text Act
  • mysql表的约束

    目录 一 表的约束分类 1 not null 非空 输入的数据内容不能为空 2 unique key 唯一键 输入的数据可以为null或者跳过赋予他的值 但是如果输入数据不能相同 3 primary key 主键 每个表中必须有唯一的主键
  • matlab编写dbscan聚类

    在Matlab中编写DBSCAN聚类的方法有很多种 一种常用的方法是手动编写代码 下面是一个简单的DBSCAN示例 function labels nClusters dbscan data eps MinPts data 数据点 eps
  • Qt 使用QInputDialog弹出输入框获取用户输入数据

    简要说明 在开发Qt程序的过程中 我们可能会需要在程序中弹出输入框 并且获取用户输入的数据 一种比较麻烦的做法就是新建一个对话框类 然后在主界面中调用对话框类 获取返回值 使用QInputDialog对话框类可以通过访问不同的接口函数 弹出
  • php导出数据xlsx

    lists 二维数组 public function xlsx lists 生成文件名 date date Y m d H i s time fileName XXXX date xlsx 头部标题 xlsx header array 序号
  • Java Springboot--swagger配置

    文章转载自 第一步 配置pom xml文件
  • 视线估计(Gaze Estimation)简介概述

    PaperWeekly 原创 作者 俞雨 单位 瑞士洛桑联邦理工学院博士 研究方向 视线估计 头部姿态估计 本文七个篇章总计涵盖 29 篇论文 总结了自深度学习以来 视线估计领域近五年的发展 概述 1 1 问题定义 广义的 Gaze Est
  • [Unity]Lua本地时间、倒计时和正计时。

    惯例 直接上代码 正计时开始时的时间戳 self begin time os time 倒计时时长 01 30 00 self countdown time 5400 是否开始计时 self is update local time tru
  • 一文搞定在Ubuntu安装tldr

    目录 第一步 执行安装命令 第二步 更新tldr数据库 第三步 测试tldr功能 补充 未成功返回的错误类型 在安装之前你得先在Ubuntu上登入你自己的账户 当然你肯定在刚安装好Ubuntu的时候就注册自己的账户并且登录了 第一步 执行安
  • 大页内存(HugePages)在通用程序优化中的应用

    今天给大家介绍一种比较新奇的程序性能优化方法 大页内存 HugePages 简单来说就是通过增大操作系统页的大小来减小页表 从而避免快表缺失 这方面的资料比较贫乏 而且网上绝大多数资料都是介绍它在Oracle数据库中的应用 这会让人产生一种