Linux网络协议栈可以准确但仍进行说明,不用说,Netfilter。简单地说,TC够了,但有几个硬伤,本文不构成一个完整的记录,如果是随笔,不可当真。

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栈搜索算法优化随想的更多相关文章

  1. Linux内核socket优化项

    Linux内核socket优化项 vi /etc/sysctl.confnet.core.netdev_max_backlog = 30000  每个网络接口接收数据包的速率比内核处理这些包的速率快时 ...

  2. Linux实战教学笔记06:Linux系统基础优化

    第六节 Linux系统基础优化 标签(空格分隔):Linux实战教学笔记-陈思齐 第1章 基础环境 第2章 使用网易163镜像做yum源 默认国外的yum源速度很慢,所以换成国内的. 第一步:先备份 ...

  3. Linux文件系统性能优化 (转)

    http://blog.chinaunix.net/uid-7530389-id-2050116.html 由于各种的I/O负载情形各异,Linux系统中文件系统的缺省配置一般来说都比较中庸,强调普遍 ...

  4. Linux/Android 性能优化工具 perf

    /***************************************************************************** * Linux/Android 性能优化工 ...

  5. linux系统基础优化16条知识汇总

    优化的总结: 1.不用root管理,以普通用户的名义通过sudo授权管理. 2.更改默认的远程连接SSH服务端口,禁止root用户远程连接,甚至 要更改只监听内网IP. 3.定时自动更新服务区时间,使 ...

  6. Linux下启动时间优化专题

    1. 过往优化总结 陆陆续续在Linux进行启动时间优化,之前有两份文档,分别从内核和用户空间两个方向进行了优化. <Android/Linux boot time分析优化>和<Bu ...

  7. MongoDB在Linux下常用优化设置

    MongoDB在Linux下常用优化设置 以下是一些MongoDB推荐的常用优化设置.在生产环境下选取合适的参数值,例如预读值和默认文件描述符数目等,会对系统性能有很大的影响. 1.关闭数据库文件的 ...

  8. linux的性能优化

    转一位大神的笔记. linux的性能优化: 1.CPU,MEM 2.DISK--RAID 3.网络相关的外设,网卡 linux系统性能分析: top:linux系统的负载,CPU,MEM,SWAP,占 ...

  9. Linux文件系统性能优化

    本文绝大部分是转载自CSDN刘爱贵专栏: http://blog.csdn.net/liuben/archive/2010/04/13/5482167.aspx另外根据参考文档增补了一部分内容. 由于 ...

随机推荐

  1. Java的压缩、解压及压缩加密、解密解压 样例

    为了节约带宽.加快传送速度,http协议支持gzip的压缩,但假设我们的app与后台不是通过http协议通讯的.那么压缩.解压这个流程须要自己写.以下给出compress和decompress的代码: ...

  2. Longest Increasing Subsequences(最长递增子序列)的两种DP实现

    一.本文内容 最长递增子序列的两种动态规划算法实现,O(n^2)及O(nlogn).     二.问题描述 最长递增子序列:给定一个序列,从该序列找出最长的 升序/递增 子序列. 特点:1.子序列不要 ...

  3. Linux 如何查看一个进程的堆栈

    有两种方法: 第一种:pstack 进程ID 第二种,使用gdb 然后attach 进程ID,然后再使用命令 thread apply all bt 第三种:strace -f -p pid  该方法 ...

  4. ImageButton按压效果失效

    LinearLayout中ImageButton的按压效果不起作用,如图 布局如下: <LinearLayout android:id="@id/ll_add_reply_face&q ...

  5. AOP概述:

    AOP可以在不修改源代码的情况下,对程序进行增强. AOP面向切面进行编程,Spring将AOP引入到框架中,但是也需要遵守AOP联盟的规范. 通过预编译的方式和运行期动态代理实现程序功能的同意维护的 ...

  6. [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 ...

  7. Android JNI 自定义对象为参数和返回值

    ndroid JNI 提供了很强大的支持,不仅可以采用基本类型做为参数和返回值,同时也支持自定义对象做为参数和返回值,以下举例说明. 一.定义作为输入和返回的自定义类 (仅提供两个简单类型和一个打印函 ...

  8. MouseGestureL.ini shift up/down/left/right edge

    MouseGestureL.ini [ShiftPress]Icon=C:\Windows\System32\explorer.exe,6Custom=GetKeyState("Shift& ...

  9. ArcSDE中Compress与Compact的区别

    原文 ArcSDE中Compress与Compact的区别 附件一”为两种数据库需要的管理工作.      与所表示的含义与操作是不同的.     对于来说,Compressing与Smart Dat ...

  10. MySQL key分区(五)

    具体描写叙述总结请看MySQL分区(一) 样例:该样例为本人个人学习总结分享->具体说明-->有问题欢迎前来交流