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另外根据参考文档增补了一部分内容. 由于 ...
随机推荐
- NoSql中的B-tree、B+tree和LSM-tree 分类: B7_HBASE 2015-03-15 18:27 85人阅读 评论(0) 收藏
总结: 1.B+树将数据完全排序,读数据时很快,但当要修改数据时,就需要将新入数据下面的数据重新排位,特别是当写入的数据排在较高的位置时,需要大量的移位操作才能完成写入. 2.SLM牺牲部分的读性能, ...
- js进阶 12-4 jquery键盘事件如何使用
js进阶 12-4 jquery键盘事件如何使用 一.总结 一句话总结:键盘和鼠标都是外设输入设备,所以函数很像,所以使用就像鼠标事件click一样 1.jquery键盘事件有哪三个? 1(up和do ...
- CSS文本阴影实例
原文 简书原文:https://www.jianshu.com/p/5abf2fa2f1b9 前言 以下的实例是我从<CSS实战>中看到的实例,当我看到这些实例的时候,发现平时不是很在意的 ...
- php计算两个坐标直线距离
function rad($d) { return $d * 3.1415926535898 / 180.0; } function GetDistance($lat1, $lng1, $lat2, ...
- SRA解密报错:Data must start with zero
项目背景:要对打印地址进行加密,用公钥加密后会乱码需要base64 decode一下,但是在解密时报错:javax.crypto.BadPaddingException: Data must star ...
- href="javascript:;" href="javascript:void(0);" href="#"区别
一.href="javascript:;" 这种用法不正确,这么用的话会出现浏览器访问"javascript:;"这个地址的现象: 二.href="j ...
- Google VR技术大揭秘
VR 虚拟现实(Virtual Reality)技术是一种能够创建和体验虚拟世界的计算机仿真系统.它利用计算机生成一种模拟环境.是一种多源信息融合的.交互式的三维动态视景和实体行为的系统仿真, 使用户 ...
- 微信管理系统基于Flask+Vue+Celery+SQLAlchemy+Redis等实现
https://zhuanlan.zhihu.com/p/28102858 现在绝大多数同学都在使用微信,不过微信有很多限制,比如: 微信聊天记录只保存在本地,换个手机那些内容就找不到了 微信扫码加群 ...
- Quartz2D常见图形的绘制:线条、多边形、圆
UI高级 Quartz2D http://ios.itcast.cn iOS学院 掌握 drawRect:方法的使用 常见图形的绘制:线条.多边形.圆 绘图状态的设置:文字颜色.线宽等 图形上下文状 ...
- JSP的C标签遍历Map数据
JSP的C标签遍历Map数据 Map可以实现较为丰富的数据封装. 第一种: 控制器传递到页面的map格式如下: Map<String, User> dataMap = new HashMa ...