Linux栈搜索算法优化随想
0.发现物种
Linux堆栈作为一个纯软件实现,保留的硬件接口,但文章并不涉及硬件。
在Linux的协议栈实现中,由于没有硬件电路的固化,查找算法是难免的。比方路由查找,邻居查找。conntrack查找,socket查找,不一而足。其实。协议栈作为一个公共组织,为全部的数据包服务,假设一个数据包到达协议栈。处理逻辑必须帮它找到和它相关的数据结构,因此查找是必定的。即使在硬件中,也是这样。可是查找分为两种类型,这两种类型的查找对性能的影响是不一致的。
0.1.查不到不创建
像路由查找这类,假设查找不到路由项。那么就直接返回失败,数据包就此丢弃。对于这类查找。表项的创建和删除是特定事件(比方人为配置,网卡up/down等)触发的。不是自己主动的。查找结果的成功与失败所消耗的性能是一致的,所不同的协议栈对待成功与失败的方式不同,因此本文不关注这类查找。
0.2.查不到即创建
像conntrack查找。邻居查找这类,假设查找失败,将会建立一个新的表项,因此查找结果的成功与失败对性能的影响是全然不正确称的。
假设查找失败,性能损耗是巨大的,即使对于高效的hash算法,起码你要遍历完特定hash值指定的冲突链表才干发现失败,这在平均看来已经是一笔非常大的开销了,然后发现失败。这才是一个開始,接下来要分配内存,创建表项。这又是一笔非常大的花费,既消耗了时间又消耗了空间。尽管空间损耗不可避免。可是我希望在必须分配内存创建表项之前,用最快的速度发现查找失败。
0.3.介于0.1与0.2的查找
TCP socket查找介于0.1和0.2之间,对于Listen状态socket的查找。它的目标是创建一个客户socket,可是首先它要确保特定的TCP四元组不在ESTABLISHED状态或者TW状态的socket中被找到,假设存在大量的TW套接字,将会消耗大量的时间来证明“这么多TW socket中没有一个匹配它”。假设能高速说明这一点该多好啊。
而对于连Listen套接字都不匹配的元组,将会直接报告查找失败。
接下来我将不那么具体分析几种Linux内核协议栈中的查找方法。
2.nf_conntrack查找
Linux nf_conntrack优化的空间非常大非常大,測试表明,加入conntrack的内核协议栈在满载情况下PPS(Packet Per Second)会下降一半。长连接最大连接数下降一半。对于短连接。即使将各个timeout时间设置非常短,性能下降也非常明显。
新建conntrack表项的速度限制了新建连接的速度。而conntrack所能占用的内存大小以及一个conntrack表项持续的时间限制了最大的连接数量。在同一时候保持大量conntrack表项的情况下。假设HASHSIZE不够大,那么hash冲突链表将会非常长。新建连接,即NEW conntrack的创建将会极其损耗资源,由于它必须在经过极大消耗后才会发现查找失败,接下来才是干正事。假设在创建之前,高速发现查找失败,将是一件好事。
3.路由cache查找
对于相似cache的查找,也是相同的。比方路由cache的查找,我们知道,路由cache有一个过期时间,假设一台路由器的过境流量过多,将会有大量的路由项被cache,查找cache本身就是一笔非常大的开销,hash冲突的可能性非常大。费了这么大的劲还没有查到。不得不进入slow路径,简直气死人!
其实。在存在大量过境流量时,路由cache的查找开销将远远大于正规路由表查找的slow路径开销,或许正是由于这样,Linux最终还是取消了路由cache。
4.ipset查找
对于ipset中的表项查找也相似,今天在医院给小小看病的间隙。突然发现6.23版本号的ipset拥有了timeout參数,支持了超时时间本身能做非常多事,逻辑处理自己主动化了不少,可是协议栈并不知道一个表项是否已经由于过期而被删除,个人认为,像ipset查找这类,即使不携带timeout參数。假设能高速确定“不在set”中也是非常好的,当然不能明白确定“不在set中”的时候。再进行特定数据结构的查找,比方hash。tree查找。
5.Bloom过滤器
在上文中。我最终都表达了一种渴望,那就是尽快发现查找失败,这样就能够直接去干正事,而不必将时间花在一件必定失败的事上,这代价或许对于OpenWRT这种烟囱垃圾能付得起,可是对于登上大雅之堂的Linux而言,绝对付不起。
当然。差点儿全部的操作系统实现的协议栈,都和Linux一样。
怎样能高速发现查找失败。这是一个根本问题,可是再抽象一点,那就是怎样确定“一个元素一定不在一个集合中”。这件事有一个专门的理论去处理。那就是Bloom过滤器,它其实在时间复杂度和空间复杂度上的效率都非常高,可是天下没有免费的午餐,代价是什么?代价就是可能误判!尽管可能误判。可是这个算法还是能够确定一些事实的,假设它对每个推断的回答都是”可能“,那么它就是不可用的,我们总是希望确定一些事实。100%地确定一些事实!为了更好的说明,我将其写成一个函数r=B(x),假设返回0,那么就说明x不在集合中,假设返回1。那么就说明一个”可能“的事实。即x有y%的可能性不在集合中。具体y是多少,背后的数学其实也不复杂,但并非本文的重点。
正规的hash表是用一个hash算法将搜索范围缩小,然后在冲突链表中进行精确匹配,因此结果无疑是确定的。然而Bloom过滤算法并不维护冲突链表,它仅仅是逐步用多个不同的hash算法将搜索范围一步步缩小。即使这个范围再小,也还是有冲突的可能,而这种可能就是误判。
Bloom过滤算法在数据结构上设计地十分静止,假设使用N个hash算法,那么仅仅需维护一个N位的位图。为集合加入一个元素的时候,为该元素应用每个hash算法计算N个范围从0到N-1的hash值Si,并在位图中置位Si为1。如今推断元素x是否在集合中,为x计算N个hash值Xi,将位图上位于Xi上的全部值做与运算,结果为0的话。说明元素x一定不在集合中。假设它在的话,一定在加入的时候会将全部相关位设置为1。
6.应用Bloom过滤器
我在上述2-5小节所描写叙述的查找算法開始之前部署一个Bloom过滤器,是不是更好呢?假设这个Bloom算法设计地足够好,对于大多数情况,假设返回0,我就能够直接跳到创建操作的逻辑,省去了大量的遍历时间。假设返回1,那么仍然须要进行精确匹配。这相当于在我本来就认为不好的算法基础上又平添了一个Bloom过滤。情形恶化了。
可是这就是代价!这就是冒险!我能够将责任推到”这个Bloom算法设计地不够好“!还有一方面。须要权衡计算N个hash的开销和计算1个hash加上遍历的开销哪个大。此时不应该简单分析时间复杂度,由于对于Bloom。假设N确定了,那么时间复杂度无疑是O(1)。难道一定比hash表的效率更好吗?其实我们应该取加权统计值,而这个值依赖于严格的性能压力測试。
还是那句话,没有免费的午餐,要么使用硬件加速。此时你花费的是钱,要么设计一个良好的算法。此时你付出的冒险以及算法失败后的补偿。
7.分级hash查找
像MMU中的页表查找思想一样。也和BSD中的路由查找算法的思想一样。採用多层hash查找而不是单一hash加冲突链表遍历。
我以conntrack查找为例,我能够将conntrack简化为一个{IP1,IP2}对,第一个元素为键,第二个为值,这样就能够将conntrack的查找做成BSD系统的路由查找的样子,当中IP2能够被看成下一跳。
或者别的......
我并非说多级的hash算法比单独hash算法是更有效的,但多级hash表可以在超过CPU核心的计算。多级hash每个表都可以hash计算作为一个维度,每CPU多核计算维度hash值。位置维度的坐标,相比之下单hash我们不能利用多台CPU核心优势。你必须计算hash人才本地化的价值hash斗列表,以便通过冲突,。在更CPU多核时代,传统的方式来分析基于时间复杂度计算的性能可能已过时。
Linux栈搜索算法优化随想的更多相关文章
- Linux内核socket优化项
Linux内核socket优化项 vi /etc/sysctl.confnet.core.netdev_max_backlog = 30000 每个网络接口接收数据包的速率比内核处理这些包的速率快时 ...
- Linux实战教学笔记06:Linux系统基础优化
第六节 Linux系统基础优化 标签(空格分隔):Linux实战教学笔记-陈思齐 第1章 基础环境 第2章 使用网易163镜像做yum源 默认国外的yum源速度很慢,所以换成国内的. 第一步:先备份 ...
- Linux文件系统性能优化 (转)
http://blog.chinaunix.net/uid-7530389-id-2050116.html 由于各种的I/O负载情形各异,Linux系统中文件系统的缺省配置一般来说都比较中庸,强调普遍 ...
- Linux/Android 性能优化工具 perf
/***************************************************************************** * Linux/Android 性能优化工 ...
- linux系统基础优化16条知识汇总
优化的总结: 1.不用root管理,以普通用户的名义通过sudo授权管理. 2.更改默认的远程连接SSH服务端口,禁止root用户远程连接,甚至 要更改只监听内网IP. 3.定时自动更新服务区时间,使 ...
- Linux下启动时间优化专题
1. 过往优化总结 陆陆续续在Linux进行启动时间优化,之前有两份文档,分别从内核和用户空间两个方向进行了优化. <Android/Linux boot time分析优化>和<Bu ...
- MongoDB在Linux下常用优化设置
MongoDB在Linux下常用优化设置 以下是一些MongoDB推荐的常用优化设置.在生产环境下选取合适的参数值,例如预读值和默认文件描述符数目等,会对系统性能有很大的影响. 1.关闭数据库文件的 ...
- linux的性能优化
转一位大神的笔记. linux的性能优化: 1.CPU,MEM 2.DISK--RAID 3.网络相关的外设,网卡 linux系统性能分析: top:linux系统的负载,CPU,MEM,SWAP,占 ...
- Linux文件系统性能优化
本文绝大部分是转载自CSDN刘爱贵专栏: http://blog.csdn.net/liuben/archive/2010/04/13/5482167.aspx另外根据参考文档增补了一部分内容. 由于 ...
随机推荐
- crx 【 集合 】
Vimium dbepggeogbaibhgnhhndojpepiihcmeb-1.64-Crx4Chrome.com.crx https://www.crx4chrome.com/down/731/ ...
- [Docker] Run, Stop and Remove Docker Containers
In this lesson, we'll find out the basics of running Docker containers. We'll go over how to downloa ...
- 撸代码--类QQ聊天实现(基于linux 管道 信号 共享内存)
一:任务描写叙述 A,B两个进程通过管道通信,像曾经的互相聊天一样,然后A进程每次接收到的数据通过A1进程显示(一个新进程,用于显示A接收到的信息),A和A1间的数据传递採用共享内存,相应的有一个B1 ...
- .NET Framework基础知识(四)(转载)
.反射:是编程的读取与类型相关联的元数据的行为.通过读取元数据,可以了解它是什么类型以及类型的成员. 比如类中的属性,方法,事件等.所属命名空间System.Reflection. 例:using S ...
- php实现 删除字符串中出现次数最少的字符
php实现 删除字符串中出现次数最少的字符 一.总结 一句话总结:数组排序是改变数组的,而其它函数一般不改变原数据,比如str_replace(); 1.单案例测试通过而多案例测试不通过怎么办? 检 ...
- 【p091】多项式输出
一元 n 次多项式可用如下的表达式表示: 其中,aixi 称为i次项,ai称为i次项的系数.给出一个一元多项式各项的次数和系数,请按照如下规定的格式要求输出该多项式: 多项式中自变量为x,从左到右按照 ...
- 基于 MySQL 5.6 keepalived的双主搭建
环境介绍: 说明 IP 节点1 192.168.56.56 节点2 192.168.56.57 w_ip 192.168.56.6 安装keepalived tar -zxvf keepalived- ...
- RESET MASTER 和RESET SLAVE 命令的使用方法 注意事项
RESET MASTER 删除所有index file 中记录的所有binlog 文件,将日志索引文件清空,创建一个新的日志文件,这个命令通常仅仅用于第一次用于搭建主从关系的时的主库,注意 rese ...
- 【t062】最厉害的机器人
Time Limit: 1 second Memory Limit: 128 MB [问题描述] [背景] Wind设计了很多机器人.但是它们都认为自己是最强的,于是,一场比赛开始了~ [问题描述] ...
- $.ajax 请求 拦截器 重定向 无效 解决办法
在ajax 异步请求下 拦截器过滤器中使用 重定向 页面响应无效 我这里用的是springboot框架,用拦截器实现 对请求的拦截 ,session超时直接跳转到login.html页面. 后台代码: ...