B+树

B+树
B+树

nginx源码分析

nginx源码分析 nginx源码分析(1)- 缘起 nginx是一个开源的高性能web服务器系统,事件驱动的请求处理方式和极其苛刻的资源使用方式,使得nginx成为名副其实的高性能服务器。 nginx的源码质量也相当高,作者“家酿”了许多代码,自造了不少轮子,诸如内存池、缓冲区、字符串、链表、红黑树等经典数据结构,事件驱动模型,http解析,各种子处理模块,甚至是自动编译脚本都是作者根据自己的理解写出来的,也正因为这样,才使得nginx比其他的web服务器更加高效。 nginx 的代码相当精巧和紧凑,虽然全部代码仅有10万行,但功能毫不逊色于几十万行的apache。不过各个部分之间耦合的比较厉害,很难把其中某个部分的实现拆出来使用。对于这样一个中大型的复杂系统源码进行分析,是有一定的难度的,刚开始也很难找到下手的入口,所以做这样的事情就必须首先明确目标和计划。 最初决定做这件事情是为了给自己一些挑战,让生活更有意思。但看了几天之后,觉得这件事情不该这么简单看待,这里面有太多吸引人的东西了,值得有计划的系统学习和分析。首先这个系统中几乎涵盖了实现高性能服务器的各种必杀技,epoll、kqueue、master-workers、pool、 buffer……,也涵盖了很多web服务开发方面的技术,ssi、ssl、proxy、gzip、regex、load balancing、reconfiguration、hot code swapping……,还有一些常用的精巧的数据结构实现,所有的东西很主流;其次是一流的代码组织结构和干净简洁的代码风格,尤其是整个系统的命名恰到好处,可读性相当高,很kiss,这种风格值得学习和模仿;第三是通过阅读源码可以感受到作者严谨的作风和卓越的能力,可以给自己增加动力,树立榜样的力量。 另一方面,要达到这些目标难度很高,必须要制定详细的计划和采取一定有效的方法。 对于这么大的一个系统,想一口气知晓全部的细节是不可能的,并且nginx 各个部分的实现之间关系紧密,不可能做到窥一斑而知全身,合适的做法似乎

C++中STL中的map用法详解

STL中map用法详解 说明:如果你具备一定的C++ template知识,即使你没有接触过STL,这个文章你也应该可能较轻易的看懂。本人水平有限,不当之处,望大家辅正。 一.Map概述 Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。下面举例说明什么是一对一的数据映射。比如一个班级中,每个学生的学号跟他的姓名就存在着一一映射的关系,这个模型用map可能轻易描述,很明显学号用int描述,姓名用字符串描述(本篇文章中不用char *来描述字符串,而是采用STL中string来描述),下面给出map 描述代码: Map mapStudent; 1. map的构造函数 map共提供了6个构造函数,这块涉及到内存分配器这些东西,略过不表,在下面我们将接触到一些map的构造方法,这里要说下的就是,我们通常用如下方法构造一个map:Map mapStudent; 2. 数据的插入 在构造map容器后,我们就可以往里面插入数据了。这里讲三种插入数据的方法: 第一种:用insert函数插入pair数据,下面举例说明(以下代码虽然是随手写的,应该可以在VC和GCC下编译通过,大家可以运行下看什么效果,在VC下请加入这条语句,屏蔽4786警告#pragma warning (disable:4786) ) #include #include #include Using namespace std; Int main() { Map mapStudent; (pair(1, “student_one”)); (pair(2, “student_two”)); (pair(3, “student_three”)); map::iterator iter; for(iter = (); iter != (); iter++) { Cout<first<<” ”<second< #include #include Using namespace std;

Linux内存系统讲解

我们先来看下Linux内存布局,此图比我之前写的那篇文章写的布局更详细。 在linux中,每一个进程都被抽象为task_struct结构体,称为进程描述符,存储着进程。 各方面的信息;例如打开的文件,信号以及内存等等;然后task_struct 的一个属性mm_struct管理着进程的所有虚拟内存,称为内存描述符。在 mm_struct结构体中,存储着进程各个内存段的开始以及结尾,如上图所示;这个进程使用的物理内存,即常驻内存RSS页数,这个内存使用的虚拟地址空间VSZ页数,还有这个进程虚拟内存区域集合和页表。 从上面这个图可以看出,进程是有代码段Text segment,数据段(已初始化的全局,静态变量),BSS段(未初始化的全局,静态变量),堆,内存映射区以及栈。 Linux 内存是后台开发人员,需要深入了解的计算机资源。合理的使用内存,有助于提升机器的性能和稳定性。本文主要介绍Linux 内存组织结构和页面布局,内存碎片产生原因和优化算法,Linux 内核几种内存管理的方法,内存使用场景以及内存使用的那些坑。 从内存的原理和结构,到内存的算法优化,再到使用场景,去探寻内存管理的机制和奥秘。 每一块虚拟内存区(VMA)都是由一块连续的虚拟地址组成,这些地址从不覆盖。一个vm_area_struct实例描述了一块内存区域,包括这块内存区域的开始以及结尾地址;flags标志决定了这块内存的访问权限和行为;vm_file决定这块内存是由哪个文件映射的,如果没有文件映射,则这块内存为匿名的(anonymous)。上述图中提到的每个内存段,都对应于一个vm_area_struct结构。如下图所示

复合文档文件格式解析-修复照片,word文件必备知识

复合文档文件格式研究 复合文档(Compound Document)是一种不仅包含文本而且包括图形、电子表格数据、声音、视频图象以及其它信息的文档。可以把复合文档想象成一个所有者,它装着文本、图形以及多媒体信息如声音和图象。目前建立复合文档的趋势是使用面向对象技术,在这里,非标准信息如图像和声音可以作为独立的、自包含式对象包含在文档中。Microsoft Windows就是使用这种技术,叫做―OLE2 stora ge file format‖或―Microsoft Office compatible storage file format‖。 当然Excel、Word等都是用这种格式存储的。本文主要研究复合文档的二进制结构,本文的目的就是为另一篇文章《Excel文件格式研究》(创作中)做准备的。 本文是在英文资料的基础上完成的,文中某些术语的翻译可能不够标准,但都会给出英文原名。关于这方面的中文资料网上几乎找不到,如果您有的话,请发到我的邮箱,谢谢。由于本人水平有限,文中错误难免,欢迎大家批评指正。 目录 第一章仓库与流(Storages and Streams 第二章扇区与扇区链(Sectors and Sector Chains 第三章复合文档头(Compound Document Header 第四章扇区配置(Sector Allocation 第五章短流(Short-Streams 第六章目录(Directory 第七章文件实例剖析 第一章仓库与流 复合文档的原理就像一个文件系统(文件系统:如FAT与NTFS)。复合文档将数据分成许多流(Streams),这些流又存储在不同的仓库(Storages)里。将复合文档想象成你的D盘,D盘用的是NTFS(NT File System)格式,流就相当于D盘里的文件,仓库就相当于D盘里的文件夹。 流和仓库的命名规则与文件系统相似,同一个仓库下的流及仓库不能重名,不同仓库下可以有同名的流。每个复合文档都有一个根仓库(root storage) 第二章扇区与扇区链 2.1 扇区与扇区标识

常用java集合类详解

常用java集合类详解 在尽可能短的篇幅里,将所有集合与并发集合的特征,实现方式,性能捋一遍。适合所有”精通Java”其实还不那么自信的人阅读。 List ArrayList 以数组实现。节约空间,但数组有容量限制。超出限制时会增加50%容量,用System.arraycopy()复制到新的数组,因此最好能给出数组大小的预估值。默认第一次插入元素时创建大小为10的数组。 按数组下标访问元素–get(i)/set(i,e) 的性能很高,这是数组的基本优势。 直接在数组末尾加入元素–add(e)的性能也高,但如果按下标插入、删除元素 –add(i,e), remove(i), remove(e),则要用System.arraycopy()来移动部分受影响的元素,性能就变差了,这是基本劣势。 LinkedList 以双向链表实现。链表无容量限制,但双向链表本身使用了更多空间,也需要额外的链表指针操作。 按下标访问元素–get(i)/set(i,e) 要悲剧的遍历链表将指针移动到位(如果i>数组大小的一半,会从末尾移起)。 插入、删除元素时修改前后节点的指针即可,但还是要遍历部分链表的指针才能移动到下标所指的位置,只有在链表两头的操作–add(), addFirst(),removeLast()或用iterator()上的remove()能省掉指针的移动。 CopyOnWriteArrayList 并发优化的ArrayList。用CopyOnWrite策略,在修改时先复制一个快照来修改,改完再让内部指针指向新数组。 因为对快照的修改对读操作来说不可见,所以只有写锁没有读锁,加上复制的昂贵成本,典型的适合读多写少的场景。如果更新频率较高,或数组较大时,还是 Collections.synchronizedList(list),对所有操作用同一把锁来保证线程安全更好。 增加了addIfAbsent(e)方法,会遍历数组来检查元素是否已存在,性能可想像的不会太好。

红黑树原理详解

红黑树原理详解(上) 前言: 之所以要写这篇文章,第一个目的是为了各位朋友在查看我写的源代码之前有一个可以理解理论的文章因为红黑树还是有点难的, 如果不想搞懂理论,而直接看代码,那绝对是云里雾里,不知所云。第二个目的是我觉得网上虽然后不少我文章也在讲,但是我就是理解 不上有点困难,在我参考了很多文章之后,认真阅读才慢慢摸透了其中的原理,所以我想用自己的方式来表达,希望有助于各位的朋友理解。 你可以在这里获得配套源代码 红黑树由来: 他是在1972年由Rudolf Bayer发明的,他称之为“对称二叉B树”,它现代的名字是Leo J. Guibas和 Robert Sedgewick 于1978 年写的一篇论文中获得的。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找, 插入和删除,这里的n 是树中元素的数目。 红黑树性质: 1. 每个结点或红或黑。 2. 根结点为黑色。 3. 每个叶结点(实际上就是NULL指针)都是黑色的。 4. 如果一个结点是红色的,那么它的周边3个节点都是黑色的。 5. 对于每个结点,从该结点到其所有子孙叶结点的路径中所包含的黑色结点个数都一样。 讨论的前提: 1,我们只讨论往树的左边和从树的左边删除的情况,与之对称的情况一样。 2,假设我们要删除一个元素的方法都是采取删除后继节点,而非前驱节点。 3,NL或全黑表示黑空节点,也可以不用画出。 4,“=>”这个符号我们用来表示“变成”的意思。 一.插入 当红黑树中没有节点的时候,新节点直接涂黑就可以了。 当树中已有节点,我们就将新节点涂红,并且底下挂两个黑空节点。

英本Linux IO调度算法之CFQ详解

读者须知:此文档为英本网(https://www.360docs.net/doc/0515871420.html,/)有。谨以此奉献给linux 爱好者,研究者,英本学员等。技术讨论QQ 群:67962133 CFQ 调度是基于优先级调度的,系统中的每一个进程都有一个优先级类(这个优先级类分成了3种:real-time (RT), best-e ort (BE),idle ),RT 和 BE 分成了8种不同的优先级来说明服务的不同优先级别。BE 作为进程默认的优先级类,通过nice 命令来设置。 每一个进程都有有个cfq_queue 队列来服务同步的请求req ,对于异步请求req 分别对应了8种不同优先级的BE 队列,8种不同优先级的RT 队列,和一个空闲队列。这些队列信息进程间是共享的,大家都知道。 下图是CFQ 算法中结构体之间的关系图(vdisktime 最小的cfq_group 先服务): 理解CFQ 算法重点是要分析这个算法用到的结构体变量。 217 220 struct cfq_data { 221 struct request_queue *queue; 223 struct cfq_rb_root grp_service_tree ;//此红黑树服务于cfg_group 224 struct cfq_group root_group; 229 enum wl_prio_t serving_prio; 230 enum wl_type_t serving_type; 231 unsigned long workload_expires; 232 struct cfq_group *serving_group; 233 234 //有8种不同优先级的树,每一个树中的优先级是相同的,不同的树优先级不同。 239 struct rb_root prio_trees[CFQ_PRIO_LISTS]; 240//cfq 里面有多少个正在使用的队列 241 unsigned int busy_queues; 242 unsigned int busy_sync_queues;//多少个同步的队列 244 int rq_in_driver; w w w . i n g b e n .c o m

红黑树的插入与删除 详细整理资料

红黑树的插入、删除及旋转原则 Category: Uncategorized— wuxicn @ 12:29 AM 红黑树(Red-Black Tree)的插入和删除操作很繁琐,一不小心就容易弄错,不能靠强制记忆。因此,今天总结一下红黑树插入和删除操作的推导原则,包括旋转的推导原则。 本文所有内容来自三个网页 1.https://www.360docs.net/doc/0515871420.html,/c?m=9d78d513d9d446db4fece4690a62c067691f976 34d8b8d5068d4e20ace3f07070671e3ca617f0704a299213156b8492dacad21724 65377a09bb9db1b9bfcc17671c33034014ad11f45954ef9df01659f2fca1cafed0 ee6c9ed2fccfd8f8b840b009759127af7a0d50755448d2ee71446b2fbc6554b024 5fbf03161fb5b7122952957b630a3a66d30&p=8f36da5986cc46aa19be9b7a7f0a &user=baidu 2.http://icoder.me/2009/08/25/insert-delete-in-red-black-tree/ 3.https://www.360docs.net/doc/0515871420.html,/20065562/blog/item/93b2d17fd6f391320dd7da4 4.ht ml 如果大家能打开上面的链接,就不用再看了,我整理得不好。。 先是比较简单的插入操作的推导原则: 1. 红黑树的插入和普通搜索二叉树(Binary Search Tree)的插入一样,只是在插入完以后,将新插入的节点标记为红色,然后从该节点开始,向上进行调整颜色。 2. 向上调整颜色进行旋转时,旋转的原则是尽量用1次或者最多2次旋转完成,并且旋转操作不能影响该层以下层次的节点,只能影响其父节点,然后将其父节点(或者叔节点、兄弟节点)作为新的要调整颜色节点,继续向上递推调整。 3. 调整完后注意检查根的颜色是否还是黑色。 删除操作的推导原则:(比较麻烦!)

K M P 算 法 详 解

KMP算法详解(转) ? 此前一天,一位MS的朋友邀我一起去与他讨论快速排序,红黑树,字典树,B树、后缀树,包括KMP算法,唯独在讲解KMP算法的时候,言语磕磕碰碰,我想,原因有二:1、博客内的东西不常回顾,忘了不少;2、便是我对KMP算法的理解还不够彻底,自不用说讲解自如,运用自如了。所以,特再写本篇文章。由于此前,个人已经写过关于KMP算法的两篇文章,所以,本文名为:KMP算法之总结篇。 本文分为如下六个部分: 第一部分、再次回顾普通的BF算法与KMP算法各自的时间复杂度,并两相对照各自的匹配原理;第二部分、通过我此前第二篇文章的引用,用图从头到尾详细阐述KMP算法中的next数组求法,并运用求得的next数组写出KMP算法的源码;第三部分、KMP算法的两种实现,代码实现一是根据本人关于KMP算法的第二篇文章所写,代码实现二是根据本人的关于KMP算法的第一篇文章所写;第四部分、测试,分别对第三部分的两种实现中next数组的求法进行测试,挖掘其区别之所在;第五部分、KMP完整准确源码,给出KMP算法的准确的完整源码;第六步份、一眼看出字符串的next数组各值,通过几个例子,让读者能根据字符串本身一眼判断出其next数组各值。力求让此文彻底让读者洞穿此KMP算法,所有原理,来龙去脉,让读者搞个通通透透(注意,本文中第二部分及第三部分的代码实现一的字符串下标i 从0开始计算,其它部分如第三部分的代码实现二,第五部分,和第

六部分的字符串下标i 皆是从1开始的)。 第一部分、KMP算法初解 1、普通字符串匹配BF算法与KMP算法的时间复杂度比较 ? KMP算法是一种线性时间复杂的字符串匹配算法,它是对BF算法(Brute-Force,最基本的字符串匹配算法的)改进。对于给的原始串S 和模式串P,需要从字符串S中找到字符串P出现的位置的索引。 BF算法的时间复杂度O(strlen(S) * strlen(T)),空间复杂度O(1)。 KMP算法的时间复杂度O(strlen(S) + strlen(T)),空间复杂度O(strlen(T))。 2、BF算法与KMP算法的区别 ? 假设现在S串匹配到i位置,T串匹配到j位置。那么总的来说,两种算法的主要区别在于失配的情况下,对的值做的处理: ? BF算法中,如果当前字符匹配成功,即s[i+j] == T[j],令j++,继续匹配下一个字符;如果失配,即S[i + j] != T[j],需要让i++,并且j= 0,即每次匹配失败的情况下,模式串T相对于原始串S向右移动了一位。 ? 而KMP算法中,如果当前字符匹配成功,即S[i]==T[j],令i++,j++,继续匹配下一个字符;如果匹配失败,即S[i] != T[j],需要保持i不变,并且让j = next[j],这里next[j] =j -1,即模式串T相对于原始串S向右移动了至少1位(移动的实际位数j - next[j]? =1),

红黑树简介

红黑树简介 首先红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结点的颜色,可以是RED或者BLACK。通过对一条从根节点到NIL叶节点(指空结点或者下面说的哨兵)的简单路径上各个结点在颜色进行约束,红黑树确保没有一条路径会比其他路径长出2倍,因而是近似平衡的。 用途 红黑树和AVL树一样都对插入时间、删除时间和查找时间提供了最好可能的最坏情况担保。对于查找、插入、删除、最大、最小等动态操作的时间复杂度为 O(lgn).常见的用途有以下几种: ?STL(标准模板库)中在set map是基于红黑树实现的。 ?Java中在TreeMap使用的也是红黑树。 ?epoll在内核中的实现,用红黑树管理事件块。 ?linux进程调度Completely Fair Scheduler,用红黑树管理进程控制块 红黑树VS AVL树 常见的平衡树有红黑树和AVL平衡树,为什么STL和linux都使用红黑树作为平衡树的实现?大概有以下几个原因: 1.从实现细节上来讲,如果插入一个结点引起了树的不平衡,AVL树和红黑 树都最多需要2次旋转操作,即两者都是O(1);但是在删除node引起树的不平衡时,最坏情况下,AVL需要维护从被删node到root这条路径上所有node的平衡性,因此需要旋转的量级O(logN),而RB-Tree最多只需3次旋转,只需要O(1)的复杂度 2.从两种平衡树对平衡的要求来讲,AVL的结构相较RB-Tree来说更为平衡, 在插入和删除node更容易引起Tree的unbalance,因此在大量数据需要插入或者删除时,AVL需要rebalance的频率会更高。因此,RB-Tree在需要大量插入和删除node的场景下,效率更高。自然,由于AVL高度平衡,因此AVL的search效率更高。

相关主题
相关文档
最新文档