最近做了一些系统和网络调优相关的测试,达到了期望的效果,有些感悟。同时,我也发现知乎上对Linux服务器低延迟技术的讨论比较欠缺(满嘴高并发现象);或者对现今cpu + 网卡的低延迟潜力认识不足(动辄FPGA现象),比如一篇知乎高赞的介绍FPGA的文章写到“从延迟上讲,网卡把数据包收到 CPU,CPU 再发给网卡,即使使用 DPDK 这样高性能的数据包处理框架,延迟也有 4~5 微秒。更严重的问题是,通用 CPU 的延迟不够稳定。例如当负载较高时,转发延迟可能升到几十微秒甚至更高”,刚好我前几天做过类似的性能测试,发现一个tcp或udp的echo server可以把网卡到网卡的延迟稳定在1微秒以内,不会比FPGA方案慢很多吧?

因此,我觉得有必要分享下自己的见解。总的来说,我打算分两篇文章讨论相关低延迟技术:

1)系统调优(本文):一些低延迟相关的Linux系统设置,和一些原则。

2)网络调优:使用solarflare网卡降低网络IO延迟

这里不打算介绍用户空间的延迟优化,因为太广泛了,另外我之前的文章也分享一些解决某类问题的低延迟类库。

说到低延迟,关键点不在低,而在稳定,稳定即可预期,可掌控,其对于诸如高频交易领域来说尤为重要。 而说到Linux的低延迟技术,一个不能不提的词是"kernel bypass",也就是绕过内核,为什么呢?因为内核处理不仅慢而且延迟不稳定。可以把操作系统想象成一个庞大的框架,它和其他软件框架并没有什么本质的不同,只不过更加底层更加复杂而已。既然是框架,就要考虑到通用性,需要满足各种对类型用户的需求,有时你只需要20%的功能,却只能take all。

因此我认为一个延迟要求很高(比如个位数微秒级延迟)的实时任务是不能触碰内核的,(当然在程序的启动初始化和停止阶段没有个要求,That's how linux works)。 这里的避免触碰是一个比bypass更高的要求:不能以任何方式进入内核,不能直接或间接的执行系统调用(trap),不能出现page fault(exception),不能被中断(interrupt)。trap和exception是主动进入内核的方式,可以在用户程序中避免,这里不深入讨论(比如在程序初始化阶段分配好所有需要的内存并keep的物理内存中;让其他非实时线程写日志文件等)。本文的关键点在于避免关键线程被中断,这是个比较难达到的要求,但是gain却不小,因为它是延迟稳定的关键点。即使中断发生时线程是空闲的,但重新回到用户态后cpu缓存被污染了,下一次处理请求的延迟也会变得不稳定。

不幸的是Linux并没有提供一个简单的选项让用户完全关闭中断,也不可能这么做(That's how linux works),我们只能想法设法避免让关键任务收到中断。我们知道,中断是cpu core收到的,我们可以让关键线程绑定在某个core上,然后避免各种中断源(IRQ)向这个core发送中断。绑定可以通过tasksetsched_setaffinity实现,这里不赘述。 避免IRQ向某个core发中断可以通过改写/proc/irq/*/smp_affinity来实现。例如整个系统有一块cpu共8个核,我们想对core 4~7屏蔽中断,只需把屏蔽中断的core(0 ~ 3)的mask "f"写入smp_affinity文件。这个操作对硬件中断(比如硬盘和网卡)都是有效的,但对软中断无效(比如local timer interrupt和work queue),对于work queue的屏蔽可以通过改写/sys/devices/virtual/workqueue/*/cpumask来实现,本例中还是写入"f"。

那么剩下的主要就是local timer interrupt(LOC in /proc/interrupts)了。Linux的scheduler time slice是通过LOC实现的,如果我们让线程独占一个core,就不需要scheduler在这个core上切换线程了,这是可以做到的:通过isolcpus系统启动选项隔离一些核,让它们只能被绑定的线程使用,同时,为了减少独占线程收到的LOC频率,我们还需要使用"adaptive-ticks"模式,这可以通过nohz_fullrcu_nocbs启动选项实现。本例中需要在系统启动选项加入isolcpus=4,5,6,7 nohz_full=4,5,6,7 rcu_nocbs=4,5,6,7 来使得4~7核变成adaptive-ticks。adaptive-ticks的效果是:如果core上的running task只有一个时,系统向其发送LOC的频率会降低成每秒一次,内核文档解释了不能完全屏蔽LOC的原因:"Some process-handling operations still require the occasional scheduling-clock tick. These operations include calculating CPU load, maintaining sched average, computing CFS entity vruntime, computing avenrun, and carrying out load balancing. They are currently accommodated by scheduling-clock tick every second or so. On-going work will eliminate the need even for these infrequent scheduling-clock ticks."。

至此,通过修改系统设置,我们能够把中断频率降低成每秒一次,这已经不错了。如果想做的更完美些,让关键线程长时间(比如几个小时)不收到任何中断,只能修改内核延长中断的发送周期。不同kernel版本相关代码有所差异,这里就不深入讨论。不过大家可能会顾虑:这样改变系统运行方式会不会导致什么问题呢?我的经验是,这有可能会影响某些功能的正常运转(如内核文档提到的那些),但我尚未发现程序和系统发生任何异常,说明这项内核修改至少不会影响我需要的功能,我会继续使用。

两个原则:

1)如果一件事情可以被delay一段时间,那它往往能够被delay的更久,因为它没那么重要。

2)不要为不使用的东西付费,对于性能优化来说尤为如此。

如何检测中断屏蔽的效果呢?可以watch/proc/interrupts文件的变化 。更好的方法是用简单的测试程序来验证延迟的稳定性:

#include <iostream>

uint64_t now() {
return __builtin_ia32_rdtsc();
} int main() {
uint64_t last = now();
while (true) {
uint64_t cur = now();
uint64_t diff = cur - last;
if (diff > 300) {
std::cout << "latency: " << diff << " cycles" << std::endl;
cur = now();
}
last = cur;
}
return 0;
}

通过taskset绑定一个核运行程序,每进入一次内核会打印一条信息。

最后,除了进入内核以外,影响延迟稳定性的因素还有cache misstlb miss

对于减少cache miss,一方面需要优化程序,minimize memory footprint,或者说减少一个操作访问cache line的个数,一个缓存友好例子是一种能高速查找的自适应哈希表文章中的哈希表的实现方式。另一方面,可以通过分(lang)配(fei)硬件资源让关键线程占有更多的缓存,比如系统有两块CPU,每块8核,我们可以把第二块CPU的所有核都隔离掉,然后把关键线程绑定到其中的部分核上,可能系统只有一两个关键线程,但它们却能拥有整块CPU的L3 cache。

对于减少tlb miss,可以使用huge pages。

链接:https://pan.baidu.com/s/1v5gm7n0L7TGyejCmQrMh2g 提取码:x2p5

免费分享,但是X度限制严重,如若链接失效点击链接或搜索加群 群号744933466

 
 
 

Linux低延迟服务器系统调优的更多相关文章

  1. 大数据集群Linux CentOS 7.6 系统调优篇

    大数据集群Linux CentOS 7.6 系统调优篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.设置主机hosts文件 1>.修改主机名 [root@node100 ...

  2. Linux中如何将系统调优

    Linux高可用服务器集群解决方案让IT系统管理员可以从容应对许多常见的硬件和软件故障,允许多台计算机一起工作,为关键服务正常运行提供保障,系统管理员可以不中断服务执行维护和升级.Linux服务器有各 ...

  3. Linux系统调优1

    Linux在进行系统调优的时候,首先要考虑整个操作系统的结构,然后针对各个部分进行优化,下面展示一个Linux系统的各个组成部分: 有上图可以看出,我们可以调整的有应用程序,库文件,内核,驱动,还有硬 ...

  4. Linux系统调优——CPU(一)

    (1).系统调优思路 性能优化就是找到系统处理中的瓶颈以及去除这些的过程,性能优化其实是对OS 各子系统达到一种平衡的定义.具体步骤如下: 1. 系统的运行状况:  CPU -> MEM  -& ...

  5. Linux系统调优相关工具

    一.系统调优概述 系统的运行状况: CPU -> MEM -> DISK*-> NETWORK -> 应用程序调优 分析是否有瓶颈(依据当前应用需求) 调优(把错误的调正确) ...

  6. linux系统调优工具

    系统调优思路 性能优化就是找到系统处理中的瓶颈以及去除这些的过程,性能优化其实是对 OS 各子系统达到一种平衡的定义.具体步骤如下: 1. 系统的运行状况: CPU -> MEM -> D ...

  7. 高性能linux服务器内核调优

    高性能linux服务器内核调优 首先,介绍一下两个命令1.dmesg 打印系统信息.有很多同学们服务器出现问题,看了程序日志,发现没啥有用信息,还是毫无解决头绪,这时候,你就需要查看系统内核抛出的异常 ...

  8. Sybase数据库应用系统调优的五大领域

    Sybase数据库应用系统调优的五大领域 2011/3/14/13:49来源:慧聪it网 本 文以“某大型商业银行的网上银行系统”这一很具有典型意义的企业级大型Sybase数据库应用系统为例,涉及了数 ...

  9. Oracle 系统调优

    一:前言 一:调整初始化参数 1: Oracle 初始化参数分类 2:主要系统调优参数介绍 二:系统全局区 sga 优化 1:调整内存分配 2:调整日志缓冲区 1:查询当前oracle 实例的日志缓冲 ...

随机推荐

  1. JavaScript面向对象①

    什么是对象 对象是一个整体,对外提供一些操作 什么是面向对象 使用对象时,只关注对象提供的功能,不关注其内部细节:比如jQuery 面向对象编程(OOP)的特点(自己理解的特点:把书本上多态放在类继承 ...

  2. SpringBoot学习笔记:http接口请求

    controller package com.example.demo.controller; import java.util.HashMap; import java.util.Map; impo ...

  3. Html引入百度富文本编辑器ueditor及自定义工具栏

    在日常工作用,肯定有用到富文本编辑器的时候,富文本编辑器功能强大使用方便,我用的是百度富文本编辑器,首先需要下载好百度编辑器的demo, 然后创建ueditor.html文件,引入百度编辑器,然后在h ...

  4. django rest_framework vue 实现用户登录

    django rest_framework vue 实现用户登录 后端代码就不介绍了,可以参考  django rest_framework 实现用户登录认证 这里介绍一下前端代码,和前后端的联调过程 ...

  5. nmap指令

    -sP  主机发现    -p  端口扫描(可区域)  -sV  端口(服务版本信息)-O  操作系统-iL  使用列表里的IP.(快捷方便)-iR  对公网上的随机n个IP.--excludeile ...

  6. QElapsedTimer定时器记录程序执行时间

    QElapedTimer类提供了一种快速计算运行时间的方法,从Qt4.7引入. QElapsedTimer类通常用于快速计算两个事件之间经过了多少时间.它的API与QTime相似,因此可以将正在使用的 ...

  7. [转]【EL表达式】11个内置对象(用的少) & EL执行表达式

    1.EL的内置对象 其他不用记,红色记一下 代码: 2.EL执行表达式

  8. docker更改默认存储路径

    systemctl stop docker mkdir /data/docker cp -r /var/lib/docker/* /data/docker mv /var/lib/docker /va ...

  9. Kibana 学习资料

    Kibana 学习资料 网址 Kibana 官方文档 https://s0www0elastic0co.icopy.site/guide/en/kibana/current/introduction. ...

  10. $.fn与$.fx什么意思; $.extend与$.fn.extend用法区别; $(function(){})和(function(){})(jQuery)

    $.fn是指jquery的命名空间,加上fn上的方法及属性,会对jquery实例每一个有效. 如扩展$.fn.abc() 那么你可以这样子:$("#div").abc(); 通常使 ...