- 博客(68)
- 资源 (4)
- 收藏
- 关注
原创 K路归并(外排序)和败者树
一 K路归并排序及其优化-败者树 外部排序由两个相对独立的阶段组成。首先,按可用内存的大小,将外存的n个记录分成若干长度的子文件或段,并且读取每个子文件对其进行单独的内排序,然后再写回外存;然后,再对这些归并段进行足趟归并,使得归并段逐渐变大,直到每个归并段有序。 普通二路归并导致磁盘读写次数很大,合理使用k路归并可以合理减少磁盘读写次数。但是传统的k路归并又带来另外一个问题:每次
2017-04-17 11:06:06
1323
原创 Eular质数筛法
一 Eular质数筛法欧拉筛法是一种比Eratosthenes筛法更为高效的质数筛法,其时间复杂度是O(n),其算法思想很简单,描述如下:linear_prime_sieves1: set is_prime[] to true2: for i=2 to n3: if is_prime[i]=true then prime[pi++]=i4: for j=0 to p
2017-04-15 21:23:06
414
原创 关于IO复用函数select的FD_SETSIZE的正确定义
一 FD_SETSIZE定义 首先,FD_SETSIZE的值在linux下一般被定义为1024,意思是select管理的描述符的最大值不能大于1024(1024也不行),参考linux的man page对FD_SET函数的一些提醒:Executing FD_CLR() or FD_SET() with a value of fd that is negative or is equal
2017-03-24 16:38:18
3747
原创 Redis主从复制机制
Redis主从复制机制一主要结构图 二 主要原理在Slave启动并连接到Master之后,它将主动发送一个SYNC命令。此后Master将启动后台存盘进程,同时收集所有接收到的用于修改数据集的命令,在后台进程执行完毕后,Master将传送整个数据库文件到Slave,以完成一次完全同步。而Slave服务器在接收到数据库文件数据之后将其存盘并加载到内存中。此后,Master继续将所有已经收集到的修改命令
2017-03-10 23:54:23
305
原创 Redis的主从复制机制(Master-Slave)
一 主从复制的大体结构图http://www.linuxidc.com/upload/2015_03/15033110386643.jpg
2017-03-10 23:37:36
219
原创 redis源码分析(七)- 网络通讯协议(networking.c)
一 Redis网络通讯协议 上节分析了redis对C标准网络的一系列简单的封装,本节继续分析Redis网络通讯的具体实现,也就是networking.c源原件,主要包括如何建立和客户端的链接,并且接收其命令,返回数据给客户端。二 网络通讯协议的实现2.1 建立连接 server端回初始化一个socket端口来监听客户端的连接,当一个建立一个连接后,服务端会对
2017-02-11 15:07:20
1107
原创 redis源码分析(七)- 网络通讯协议(networking.c)
一 Redis网络通讯协议 上节分析了redis对C标准网络的一系列简单的封装,本节继续分析Redis网络通讯的具体实现,也就是networking.c源原件,主要包括如何建立和客户端的链接,并且接收其命令,返回数据给客户端。 上节分析server端回初始化一个socket端口来监听客户端的连接,二 网络通讯协议的实现
2017-02-11 14:28:49
297
原创 redis源码分析(六)- anet网络通讯的封装
一 anet网络通讯封装介绍 Redis对网络通讯的封装在代码anet.c里面,总的来说该封装是对标准的socket的TCP通讯模块的一个小小的封装,总代码量才600多行。二 代码实现分析 因为代码简单,先大致看一下它的APIint anetTcpConnect(char *err, char *addr, int port); /* TCP的默认连接 */ int
2017-02-11 10:26:56
564
原创 redis源码分析(五)- Redis 事件驱动
一 Redis 事件驱动 作为一个网络数据库服务器,不可置否redis也用到了事件驱动的编程模型来实现网络通讯,不像Memcached采用libevent实现网络通讯,redis拒绝了庞大的libevent,尽管libev已经比较轻量,但是仍然比不上只有不到几百行代码的ae事件驱动库。 通常,事件驱动库的组成部分包括以下几个部分:1)事件,一般由外在因素触发,比如有网络数据
2017-02-10 21:36:29
356
原创 redis源码分析(四)-双向链表的实现
一 双向链表 双向链表是redis的最基础的数据结构之一,看完这个源码可以快速复习一下链表的基础知识:)。二 源码实现 adlist.h/* adlist.h - A generic doubly linked list implementation * * Copyright (c) 2006-2012, Salvatore Sanfilippo * All rig
2017-02-10 10:23:19
238
原创 redis源码分析(三)-ziplist的实现
一 ziplist简介以及应用 ziplist称之为压缩链表,顾名思义,压缩链表有压缩节省空间的语义。回想redis另外一种链表:双向链表,每个节点都需要prev、next指针来指向前后节点,如何数据只占1字节,大量的此类数据会造成空间上的浪费。因此redis提出了另外一种更具有空间效率的链表:压缩链表,压缩链表则没有这两个指针,压缩链表含有两个数,一个代表前一个节点的长度,有一个表示
2017-02-09 21:19:08
418
原创 redis源码分析(二)-sds字符串的实现
一 sds字符串简介 sds是redis对字符串的底层实现。类似于C++和java的string,sds提供对字符串数组char []的一系列封装,使其使用起来更加的方便和安全。二 sds的数据结构/* * 类型别名,用于指向 sdshdr 的 buf 属性 */typedef char *sds;/* * 保存字符串对象的结构,sizeof(sdshdr)的结果是
2017-02-09 11:12:42
299
原创 redis源码分析(一)-字典(dict)的实现
一 字典的简介以及在Redis中的应用 字典(dictionary), 又名映射(map)或关联数组(associative array), 是一种抽象数据结构, 由一集键值对(key-value pairs)组成, 各个键值对的键各不相同, 程序可以添加新的键值对到字典中, 或者基于键进行查找、更新或删除等操作。字典在Redis应用很广泛,和SDS、双向链表一样使用频率很高。其中,
2017-02-08 21:19:59
460
原创 小笔记-区分TCP连接中半打开连接和半关闭连接
TCP的半开连接(half-open)是指TCP连接的一端崩溃,或者在未通知对端的情况下移除socket,不可以正常收发数据,否则会产生RST。 TCP的半关闭是指TCP连接的一端调用shutdown操作使数据只能往一个方向流动,只有一方发送了FIN,仍然可以正常收(或发)数据。
2017-02-02 22:51:22
561
转载 C++ STL容器迭代器失效-笔记
迭代器是封装了指针、重载了 -> 、* 、++等操作符的类模板,具有类似指针的行为。迭代器的设计是对数据结构的泛化,使不同容器具有相同的访问方式,让代码不必依赖于特定的数据结构。指针也可以狭义的理解为迭代器。在C++中经常使用迭代器对STL容器进行操作,但很多同学没怎么关注过迭代器失效的问题。迭代器失效,指迭代器指向错误的元素或无效的内存地址。要理解迭代器失效,首先要知道为什么会造成迭代器
2017-01-18 20:56:59
229
原创 Item 29:追求异常安全的代码
异常安全是指当异常发生时,1) 不会泄漏资源,2) 也不会使系统处于不一致的状态。 通常有三个异常安全级别:基本保证、强烈保证、不抛异常(nothrow)保证。基本保证。抛出异常后,对象仍然处于合法(valid)的状态。但不确定处于哪个状态。强烈保证。如果抛出了异常,程序的状态没有发生任何改变。就像没调用这个函数一样。不抛异常保证。这是最强的保证,函数总是能完成它所承诺的事情。
2017-01-04 16:21:22
340
原创 滑动窗口协议、拥塞窗口与拥塞避免算法
TCP协议作为一个可靠的面向流的传输协议,其可靠性和流量控制由滑动窗口协议保证,而拥塞控制则由控制窗口结合一系列的控制算法实现。一 滑动窗口协议 ”窗口“对应的是一段可以被发送者发送的字节序列,因为是连续范围内的一段消息,所以被称之为“窗口”;因为窗口会随着发送过程的不断进行,可发送的段也在不断地移动(向右移动),所以称之为“滑动窗口“。滑动窗口协议可描述为下图: (1)
2016-12-20 22:15:34
991
原创 TCP滑动窗口协议、拥塞窗口控制与快速重传和快速恢复算法
TCP协议作为一个可靠的面向流的传输协议,其可靠性和流量控制由滑动窗口协议保证,而拥塞控制则由控制窗口结合一系列的控制算法实现。一 滑动窗口协议 ”窗口“对应的是一段可以被发送者发送的字节序列,因为是连续的范围内de一段消息,所以被称之为“窗口”
2016-12-20 21:24:26
382
原创 关于流式socket(TCP) read和recv的一些区别
1、read 与 recv 区别read 原则: 数据在不超过指定的长度的时候有多少读多少,没有数据则会一直等待。所以一般情况下:我们读取数据都需要采用循环读的方式读取数据,因为一次read 完毕不能保证读到我们需要长度的数据,read 完一次需要判断读到的数据长度再决定是否还需要再次读取。recv 原则: recv 中有一个MSG_WAITALL
2016-12-13 16:59:38
1383
原创 利用位图(Bit Map)和二分查找实现快速查找算法
一:应用背景 快速查找海量字符串数组中查找是否包含某个字符串(密文),应用于实验室的分布式破译系统中。二:实现主要思路 2.1 构造位图(bitMap),位图的每个bit对应一条密文,即密文映射到位图某个bit上,采用特定的hash函数计算映射地址,位图的大小根据碰撞系数可变化。位图过小,那么越多的明文字符串就会映射到同一个bit上,从而导致查找性能下降。位图查找的时间复杂
2016-12-03 21:27:28
1209
转载 高性能、高并发网络通信系统的架构设计
来自"祁峰"的优快云博客:http://blog.youkuaiyun.com/qifengzou/article/details/239122671 引言 随着互联网和物联网的高速发展,使用网络的人数和电子设备的数量急剧增长,其也对互联网后台服务程序提出了更高的性能和并发要求。本文的主要目的是阐述在单机上如何进行高并发、高性能消息传输系统的框架设计,以及该系统的常用技术,但不对其技
2016-10-20 15:12:01
1777
原创 小笔记-TIME_WAIT状态
一 TIME_WAIT状态的发生 在TCP连接中主动关闭连接的一方将进入到TIME_WAIT状态。该端点停留在这个状态的持续时间是最长分节生命期(MSL,maximum segment lifetime)的两倍,也就是2MSL。二 TIME_WAIT状态存在的理由 (1)可靠地实现TCP全双工连接的终止。 (2)允许老的重复分节在网络中消逝。
2016-10-11 16:14:51
326
原创 小笔记-setsockopt中SO_REUSEADDR选项
一 应用背景 我们知道,对于面向连接的TCP协议,先调用close函数的一方会进入TIME_WAIT状态,在linux下这个状态大概会保留2分钟,如果这两分钟之内(可以看作是服务进程终止了)监听服务器重启,也就是调用socket、bind、listen重新启动,那么将会出现“Address already in use”的错误。但是如果设置了SO_REUSEADDR选项,则不会出现
2016-10-11 14:59:18
582
原创 小笔记-pthread_cond_signal和pthread_cond_wait
一:应用背景UNIX网络编程第一卷30.12节用到了pthread_cond_signal和pthread_cond_wait来进行父子线程的通讯,在服务器端父线程accept来了一个新的连接,并通过pthread_cond_signal来通知线程池的一个子线程来处理该连接。二:关于pthread_cond_signal和pthread_cond_waitpthread_cond_wa
2016-10-10 16:37:32
251
原创 使用waitpid函数处理SIGCHLD信号-避免僵死进程
一:pid_t waitpid(pid_t pid, int *statloc, int options) 引用UNIX网络编程5.9-5.10节的内容,僵尸进程形成的原因大家都是很清楚了,这里不多解释,我们显然不能留存僵死进程,它们占用内核的空间,最终可能耗尽进程资源,所以我们得正确处理父进程以避免子进程变为僵尸进程。 我们一般使用函数waitpid来等待子进程,pid参数允
2016-09-11 15:40:07
510
原创 关于hashMap的一
一:应用背景 hashMap是一个好东西,之前没有太多关注,直到看了阿里的OceanBase源码,其块缓存和行缓存使用了LRU(最近最少使用算法),这个算法我的项目也简单实现过,有点不同的是它的访问缓存是通过hashmap来获取,我的是普通的map。二:hashMap特性 哈希表最大的优点,就是把数据的存储和查找消耗的时间大大降低,几乎可以看成是常数时间;而代价仅仅是消耗比
2016-09-08 11:08:57
287
原创 高效的大小写转换
一:背景在字符串处理时,我们会经常用到大小写转换,我们会经常用到if(tem_char ='a') tem_char-=0x20,其实是大规模的转换中,其效率并不高,判断和减法这样的操作也可以进一步优化。参考开源软件hashcat,里面有个非常高效的大小写转换方法。二:源代码代码只用了一些高效逻辑操作就完成了大小写的转换。static uint32 generate_cmask (
2016-07-29 11:07:35
486
原创 资源管理类
一:应用背景在一个系统中我们往往会用到很多全局的资源,比如缓存、监控器等资源,此时我们会需要一个类来管理这些类对象,使这些资源的生命周期内自动管理,不需要用户自动管理释放这些资源.二:代码样例/*! * \file scoped_ptr.h * \brief 资源管理类 * * * \author * * \version 1.0 * \date */#i
2016-07-19 13:07:43
498
原创 最近最少使用缓存算法LRU
一:应用背景分布式系统中的计算节点的输入参数是大量重复的文件,这些文件通常在10M-300M之间,如果每次从磁盘读取将会在读取数据上耗费大量的时间。解决这个问题解决方案的一个方法就是设计一个缓存机制,在内容中保存最近使用的文件,下次计算任务到来先检查缓存是否由此文件,有则直接读取缓存,而没必要读取磁盘文件!二:LRU最近最少使用缓存算法该算法的实现主要使用了双向链表和一个map容器,双
2016-07-13 21:57:19
1178
原创 容器存放指针的技巧-自动管理内存
一:前提我们知道,容器直接存放对象往往会降低性能,我们可以选择存放对象的指针,但是存放普通的指针将会带来内存管理的问题,即我们需要手动释放内存。下面介绍两种方法,详细介绍如何巧妙存放指针同时自动管理内存。二:方法2.1 使用智能指针shared_ptr,容器存放shared_ptr智能指针,让智能指针管理内存。2.2 使用代理类,代理类的应用很广泛,它可以使容器包含不同类型的对象(
2016-05-21 20:44:25
878
原创 setsockopt中参数SO_REUSEADDR的四个作功用
一:SO_REUSEADDR是让端口释放后立即就可以被再次使用,即使以前建立的绑定该端口的连接仍然存在。我们知道,tcp连接中主动执行关闭的那一端将处于TIME_WAIT状态,该端留在这个状态的持续时间叫做最长分节生命期(maximum segment lifetime,MSL)的两倍,一般MSL=30秒,即要等待一分钟之后该端口才能被重新使用。所有TCP服务器都应该指定本套接字选项,以允
2016-05-19 20:10:52
1712
原创 容器存放基础类型、对象、指针
一:容器存放基本原则 1.1 对于内建类型(int,long,float),容器只是单纯的位拷贝。 1.2 对于类对象,容器会调用对象的拷贝函数,最终放进容器的是对象的拷贝。 1.3 对于指针,容器放进去的是指针的拷贝,这种方式需要自己去释放指针指向的内存,容器并不会主动帮你释放。二:存放的选择2.1于普通的内建类型,直接存取数据本身。2.2对于复杂的对象,我
2016-05-18 19:41:55
590
原创 set_new_handler
函数原型: new_handler set_new_handler (new_handler new_p) throw();它的参数是一个指针,指向new无法分配足够空间时改被调用的函数,返回值也是个指针,指向set_new_handler被调用前正在执行的那个new-handler函数。 当perator无法申请到足够内存时,它会反复调用new_handler函数,知道找到足
2016-05-13 16:34:57
283
原创 读一个空指针的问题
项目遇到读空指针的问题,总结出来linux下读空指针的行为是未定义的,。以下是测试的代码void f(char *p[]){ p[1]="dd"; p[6]="cc";}int main(){ char *(p[10])={"aa","aa","aa","aa","aa"}; f(p); cout<<sizeof(p)<<endl; for(int i=0;i
2016-05-12 10:33:52
336
原创 pure virtual、impure virtual 、non-virtual函数-读书笔记
1:声明一个pure virtual函数的目的是为了让derived classes只继承函数接口。2:声明简朴的(非纯)impure virtual函数的目的,是让derived classes继承该函数的接口和缺省实现。3:声明non-virtual函数的目的是为了令derived classes继承函数的接口及一份强制性实现。 class Shape { pu
2016-05-09 09:34:17
660
原创 C++四种类型转换操作符:const_cast,static_cast, dynamic_cast 以及 reinterpret_cast
1:static_cast( expression ) 通常被用来将对象的常量性转除,它是唯一有此能力的C++转型操作符。2:dynamic_cast( expression ) 主要用来执行“安全向下转型”,也就是用来决定某对象是否归属继承体系中的某个类型。它是唯一可能耗费巨大运行成本的转型动作,所以要慎用!3:reinterpret_cast( expression )
2016-05-07 20:09:55
417
原创 野指针
野指针形成原因:1:未初始化 我们知道一个指针变量在创建的时候并不是NULL,它的缺省值是随机的,也就是说它可以乱指一通,所以在创建指针时应该初始化,要么将其设置为NULL,要么将其指向一块合法的内存!2:指针释放后未置空 指针指向的对象主动释放(free,delete)后未及时置空,指针释放只是释放该段内存,指针本身并没有释放,此时指针指向的内存就是垃圾内存,所以释放后应该马
2016-05-07 09:43:37
392
原创 提升笛卡尔乘积效率
最近项目的计算节点用的最多的是一个笛卡尔乘积算法,由于字典集合比较多,总高度有时会达到很高的一个量级,例如:1G。这样笛卡尔算法所 耗费的时间将很大,如何提交笛卡尔算法效率已经是当务之急。 笛卡尔乘积的算法很简单,复杂度就摆在这里O(high*n) :n指字典集合个数,high是所有集合的高度乘积。复杂度没法降低,所以我们从循环里面的运算下手,尽量降低循环内的计算,性能有所提升,下面是老版笛
2016-05-06 19:34:05
1340
原创 C++11尝鲜 之share_ptr
shared_ptr是C++11是boost库实用也很重要的一个组件.管理动态创建的对象的销毁,它的基本原理就是记录对象被引用的次数,当引用次数为 0 的时候,也就是最后一个指向某对象的共享指针析构的时候,共享指针的析构函数就把指向的内存区域释放掉。共享指针对象重载了 operator* 和 operator-> , 所以你可以像通常的指针一样使用它。 以上是网友这么说的,事实上我对这个
2016-05-05 16:26:21
371
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人