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另外根据参考文档增补了一部分内容. 由于 ...
随机推荐
- Java的压缩、解压及压缩加密、解密解压 样例
为了节约带宽.加快传送速度,http协议支持gzip的压缩,但假设我们的app与后台不是通过http协议通讯的.那么压缩.解压这个流程须要自己写.以下给出compress和decompress的代码: ...
- Longest Increasing Subsequences(最长递增子序列)的两种DP实现
一.本文内容 最长递增子序列的两种动态规划算法实现,O(n^2)及O(nlogn). 二.问题描述 最长递增子序列:给定一个序列,从该序列找出最长的 升序/递增 子序列. 特点:1.子序列不要 ...
- Linux 如何查看一个进程的堆栈
有两种方法: 第一种:pstack 进程ID 第二种,使用gdb 然后attach 进程ID,然后再使用命令 thread apply all bt 第三种:strace -f -p pid 该方法 ...
- ImageButton按压效果失效
LinearLayout中ImageButton的按压效果不起作用,如图 布局如下: <LinearLayout android:id="@id/ll_add_reply_face&q ...
- AOP概述:
AOP可以在不修改源代码的情况下,对程序进行增强. AOP面向切面进行编程,Spring将AOP引入到框架中,但是也需要遵守AOP联盟的规范. 通过预编译的方式和运行期动态代理实现程序功能的同意维护的 ...
- [TypeScript] Find the repeated item in an array using TypeScript
Say you have an array that has at least one item repeated. How would you find the repeated item. Thi ...
- Android JNI 自定义对象为参数和返回值
ndroid JNI 提供了很强大的支持,不仅可以采用基本类型做为参数和返回值,同时也支持自定义对象做为参数和返回值,以下举例说明. 一.定义作为输入和返回的自定义类 (仅提供两个简单类型和一个打印函 ...
- MouseGestureL.ini shift up/down/left/right edge
MouseGestureL.ini [ShiftPress]Icon=C:\Windows\System32\explorer.exe,6Custom=GetKeyState("Shift& ...
- ArcSDE中Compress与Compact的区别
原文 ArcSDE中Compress与Compact的区别 附件一”为两种数据库需要的管理工作. 与所表示的含义与操作是不同的. 对于来说,Compressing与Smart Dat ...
- MySQL key分区(五)
具体描写叙述总结请看MySQL分区(一) 样例:该样例为本人个人学习总结分享->具体说明-->有问题欢迎前来交流