自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(139)
  • 收藏
  • 关注

原创 linux库打桩

库打桩用于截获对共享库函数的调用,提供一个和库函数原型一致的桩函数,可以替换对原函数的调用,是性能分析工具使用的常见手段。打桩可以发生在编译时、链接时、运行时,这里以malloc为例展现桩函数的应用1、编译时打桩// main.c#include <stdlib.h>#include <stdio.h>#include <malloc.h>int main() { int *p = malloc(32); // 这里被打桩,调用mymall

2021-06-15 20:05:20 943

原创 c++17 string_view

c++最为c程序员诟病的一点是,c++会在程序员不知道的地方申请和释放内存。c++库如stl等提供了良好的抽象,但是屏蔽底层操作的代价就是如果程序员不了解库的底层实现,就可能造成误用导致的性能损失,这里以std::string这个最常见的容器为例,从c++17的string_view展开,最后带来一个string特定场景下的使用优化。1、std::string的内存申请对c程序员来说,字符串从char*开始位置到'\0'结束,需要从字符串中切词通过移动指针指向子串的头部并提供新长度,c程序需要传入字

2021-05-09 22:06:24 3322 2

原创 chubby总结

目录架构文件名空间分布式锁缓存一致性chubby master故障恢复client和chubby master交互master故障恢复master选举流程chubby服务端架构paxos算法实现chubby是一个面向松耦合分布式系统的锁服务,是paxos算法的工程实现。架构如图,chubby锁服务有中心化节点,这里以5个实例组成的chubby集群为例,根据paxos算法选举唯一master,client通过lib向chubby master发送rpc请

2021-04-25 16:37:22 1009

原创 google bigtable 浅析

目录概述key-value模式详解构件组件tablet概念tablet组织结构tablet分配tablet变更tablet服务架构优化局部性群组缓存bloom filter概述bigtable是一个key-value模式的分布式结构化存储系统,不提供传统关系数据库的sql功能,设计目标是高适用性、高扩展性、高性能、高可用key-value模式详解bigtable的key-value模式如下:(row:string, column:str

2021-04-25 13:46:42 1372

原创 GFS(google file system)深度剖析

目录架构一致性模型系统交互快照master节点管理文件锁文件删除过期失效的副本检测高可用数据完整性架构gfs(google file system)包含一个master节点和若干个chunk server。master节点维护元数据,chunk server存储实际数据。访问gfs通过client进行,client通过lib的形式集成在用户程序中,先访问master节点获取要访问文件所在的chunk节点地址,然后访问chunk server操作数据。.

2021-04-24 23:47:24 1244

原创 bthread源码分析(十)进阶数据结构FileStatus

FileStatus在用户态维护一个文件描述符机制,设计这样一个数据结构有如下原因:epoll_ctl开销大,不宜多次调用 用户态butex同步机制,bthread可以基于butex的同步编程模式等待文件描述符源码地址:bthread/file_status_monitor.h bthread/file_status_monitor.cpp这里给出一个例子:如图,每个打开的fd在内存中维护一个对应的FileStatus对象,bthread1在fd3上butex_wait,bthread2

2021-04-20 17:27:06 184

原创 bthread源码分析(九)进阶数据结构 ExecutionQueue

ExecutionQueue是一个多生产者-单消费者模型的工作队列,特性:wait-free,基于butex同步 队列元素数量无边界 没有daemon thread存在,消费者线程自动启动、自动销毁。当有任务加入队列,启动一个bthread持续消费队列并执行任务,直到队列为空,销毁这个bthread 提供有序性和优先级管理,高优先级任务先于低优先级任务执行,相同优先级内部任务按照FIFO顺序执行。高优先级任务不是即时抢占的,即若当前正在执行低优先级任务,那么高优先级任务插入不会抢占低优先级任务立刻

2021-04-20 17:25:57 408

原创 bthread源码分析(八)进阶数据结构bthread_id:以id关联data的同步机制

bthread_id是一种同步机制,其思想是为需要同步的数据关联一个带版本管理的id,在这个id上做加锁、解锁等同步操作。bthread_id的同步操作在锁内进行,其效率比mutex低,也就是说bthread_id不能用做通用的同步机制,其适用于对一个对象进行一系列低冲突操作的场景,用于同步这些操作。源码位置 bthread_id.h bthread_id.cppid版本号管理 first_ver | * | * | ... | locked_ver -1| locked_ver | ..

2021-04-20 17:23:49 379 1

原创 bthread源码分析(七)bthread调度逻辑

TaskControl:全局一个,控制所有TaskGroup和工作线程,初始化时根据配置数量创建指定数量的工作线程。包含4个parkinglot供线程睡眠等待任务使用。非工作线程添加任务时通过TaskControl进行,在TaskControl中随机选择一个TaskGroup并将任务添加到该TaskGroup队列中TaskGroup:每个工作线程绑定一个TaskGroup,TaskGroup中包含工作队列等信息源码地址:bthread/task_control.h bthread/task_cont

2021-04-20 17:23:08 419

原创 bthread源码分析(六)bthread同步机制

Butexbutex是bthread使用的类futex的32bit同步原语,可用于bthreads或者pthreads的同步,不可用于同步多进程。源码地址:bthread/butex.h bthread/butex.cppButex数据结构如图,每个Butex内部包含一个32bit的用于同步的value和一个WaiterList。bthread进行同步操作时先判断Butex中的value是否和expect value相等,若是那么此bthread拿到了这个Butex,否则在栈上分配一个W

2021-04-20 17:21:45 642

原创 bthread源码分析(五)上下文和栈实现

Contextcontext是bthread的上下文,提供上下文初始化和上下文切换功能源码位置:bthread/context.h bthread/context.cpp接口api 1 2 3 4 5 6 7 8 9 10 11 12 13 // 上下文切换,从ofc切换到nfc intptr_t BTHREAD_CONTEXT_CALL_CONVENTION

2021-04-20 17:20:40 757

原创 bthread源码分析(四)定时器实现

bthread中启用一个pthread作为全局唯一的定时器处理线程,所有定时任务都通过这个pthread进行管理和调度。由于全局只有一个定时任务处理线程,因此定时任务中不能放耗时长的逻辑,否则会给后续任务造成延迟。源码位置:bthread/timer_thread.h bthread/timer_thread.cpp接口api 1 2 3 4 5 6 7 8 9 //调用者传入一个方法fn和方法的参数ar

2021-04-20 17:19:06 363

原创 bthread源码分析(三)基础数据结构和组件

1、WorkStealingQueueWorkStealingQueue是一种无锁队列,用做bthread中的任务队列。WorkStealingQueue提供三种操作:push,pop,steal。由于push和pop都是在本线程中完成的,因此push和pop操作不会并发,两个push和两个pop之间也不会并发,但是steal是从其他线程发起的,因此会和push或pop并发。源码位置:bthread/work_stealing_queue.h基本操作队列保存头尾指针_top和_bottom,

2021-04-20 17:18:22 470

原创 bthread源码分析(二)ObjectPool && ResourcePool

对象池存储固定大小的对象,针对多线程环境反复使用fixed size小对象的场景相比每次都new和delete有明显的性能提升。同时由于对象池不销毁对象的特性,极大简化了无锁编程中对象生命周期管理的问题。源码位置:base/resource_pool.h base/resource_pool_inl.h base/object_pool.h base/object_pool_inl.hbthread提供对象池ObjectPool和资源池ResourcePool,两者的差异仅仅在于ResourcePo

2021-04-20 17:16:33 363

原创 bthread源码分析(一)概述

bthread是一个M:N线程库,是brpc的核心组件。bthread实现了用户态上下文切换,主要有2个目标,一是降低编码难度,业务层可使用同步编程模式;二是在多核系统上取得更好的扩展性和局部性,提供更低的延时,更高的cpu利用率。bthread和协程谈到bthread,就不得不提协程。首先要强调的一点是,bthread不是协程。一般上我们说的协程的概念是M:1线程库,多个协程跑在一个底层pthread上,一个协程阻塞就会导致协程所在的pthread阻塞,进而该pthread上的其他协程都无法被调度

2021-04-20 17:15:01 1093 1

原创 leveldb源码分析(七)db操作流程详解

1、GetGet操作较简单,先查内存的两个memtable,查不到的话继续查磁盘文件,伪代码如下: Get(options, key, value) { mutex.lock() { sequence_num = options.has_snapshot() ? options.snapshot() : versions.last_sequence()// 获取seq num mem.Ref(), imm.R...

2021-04-19 15:58:31 402

原创 leveldb源码分析(六)Version

leveldb的db实现包含一组version,所有version在version_set中维护,最新的version为current。每个version记录一个db状态,包含每个level的文件、每个文件的key range等信息。version中维护一个ref计数以管理声明周期,保证old version在仍有迭代器访问时不会消失。所有version保存在一个version_set中。源码位置:db/version_set.h db/version_set.cc这里结合一个具体例子如图:

2021-04-19 15:57:38 318

原创 leveldb源码分析(五)Compaction

leveldb进行Compaction对文件进行合并和层级下沉,原因有如下几个:记录一经写入不会修改,对同一个key的多次操作会产生多条记录,占用了额外空间需要清理 合并倾向于把不活跃key沉降到下层level,上层level活跃度高,利用局部性原理减少IO开销leveldb会进行2种Compactionminor compaction将immutable memtable刷到磁盘。内存中的memtable有大小限制,一方面内存是有限的,另一方面过大的memtable会导致过大的LOG文件,

2021-04-19 15:56:32 309

原创 leveldb源码分析(四)cache

在前文的leveldb文件层次结构中,内存中只显示了memtable,然而内存中不只有memtable,实际上leveldb在内存中维持了sst文件内容的缓存。这里介绍leveldb的cache实现和两个使用场景。LRU实现leveldb提供了一个Least recently used的缓存实现,源码位置:include/leveldb/cache.h util/cache.cc如图,leveldb的LRU实现包含一个hash表和两个双链表,查找数据在hash表中进行,hash使用拉链法,n

2021-04-19 15:55:31 303

原创 leveldb源码分析(三)文件格式

levedb层级组织如图,leveldb由内存中的memtable和磁盘文件组成,memtable和ldb文件中均按key有序存储,level0的各文件管理的key空间可能有重合,从level1到level6,每个level内的文件key范围不会重合。下面分别介绍memtable和磁盘文件格式。memtable数据结构memtable使用skiplist维护插入的数据,不允许删除数据,插入数据按自定义的Comparator进行比较按序插入。memtable内部没有同步机制,由于不会删除.

2021-04-19 15:54:01 1032

原创 leveldb源码分析(二)leveldb数据结构

1、skiplist跳跃表是一种O(logN)插入和查找操作的数据结构,和红黑树类似,优点是实现简单,易于理解。levedb使用的跳跃表在一般跳跃表的基础上做了一些改造,特点如下:内部没有同步机制,写操作需要调用者同步,读操作可并发,写不阻塞读,读者可能丢失同时进行的写,但是不会读取不一致数据 相同的key只允许插入一次 不提供删除操作,数据插入后不允许修改内容 支持用户定制比较器用于key的比较skiplist内存管理skiplist使用arena管理内存,目的是缩减小内存的申请次数以

2021-04-19 15:48:49 796

原创 leveldb源码分析(一)概述

leveldb是key-value模式数据库,出自Jeff Dean和Sanjay Ghemawat之手,适用于顺序读写场景。各大厂均有以leveldb为积木搭建的成熟数据库产品,如google的bigtable,baidu的tera等,在工程实践上取得了广泛成功。leveldb以其良好的编程风格和设计理念为人称道,阅读leveldb源码对提升自己的编程能力大有裨益。leveldb源码地址https://github.com/google/leveldbleveldb源码目录结构 db

2021-04-19 15:46:19 908

原创 pure virtual method called 纯虚函数被调用原理分析

程序退出或者组件析构过程中常发生一类“pure virtual method called”导致的core,前几栈帧如下:这里对该问题发生的原理做一个剖析并给出一个可复现该问题的简单demo前置知识一、虚函数表虚函数表的概念在很多如《c++ primer plus》等权威书籍中有详细阐述,这里简单回顾下虚函数表的概念虚函数表用于支持运行时多态,在继承关系中,父类声明的函数在子类的中可以用同名函数重写,这类函数按照静态调用的规则,根据指针、引用、原始对象的类型决定调用父类函数还是子类函数。

2021-03-23 15:14:53 2469

原创 c++ 动态库虚表问题导致的不兼容问题 实例

c++动态库在abi兼容方面臭名昭著,这里结合一个线上模块使用动态库导致出core的问题总结下动态库、虚函数表等知识,这里将线上遇到的问题抽象出一个极简的例子,三个文件include.h, main.cpp, func.cpp ,先上源码include.h:class Base {public: void virtual func1() = 0;};class Wrapper {public: Base *b;};extern void jj(Wrapper *);

2020-10-29 14:51:38 612

原创 leveldb NoDestructor类解析

leveldb提供了byte级别的比较器,见util/comparator.cc,这个文件中提供的BytewiseComparator类对象通过无析构函数的单例提供,代码如下:const Comparator* BytewiseComparator() { static NoDestructor<BytewiseComparatorImpl> singleton; return singleton.get();}这里单例通过static语义实现,保证第一个到达此函数c

2020-09-08 17:05:03 760 2

原创 x86-64指令集128位乘法和除法实现

两个64位整数相乘得到的乘积需要128位来表示,x86-64指令集提供两个指令用于无符号乘法和有符号乘法,如下:imulq S :R[%rdx] : R[%rax] <-- S * R[%rax]mulq S :R[%rdx] : R[%rax] <-- S * R[%rax]imulq用于实现有符号乘法,mulq用于实现无符号乘法,其余操作相同,将rax寄存器中保存的64位整数和给定操作数S相乘,得到一个128位的结果,其中高64位放在rdx寄存器中,低64位放在rax寄存器中,一

2020-09-02 16:16:48 3348

原创 Amdahl’s Law

Amdahl’s Law 公式化描述了系统中某个部分性能提升对整个系统性能提升的影响程度,为系统性能优化提供了基本指导原则,公式如下:设某个系统执行某个操作的时间为系统中执行这个操作的一部分占百分比为这部分性能提升后,速度因子为k,即这部分操作快了k倍,原来需要的时间为,现在需要的时间为从而得到整理得到这就是某个部分性能提升对整个系统性能提升的影响程度,例如,某部分占比60%,性能提升3倍,那么整个系统性能提升为1.67倍。这个公式同样可以用于判断并发对系统性能的影响,这里k的含

2020-08-10 11:28:44 232

原创 goto语句在c++中的注意事项(C to C++移植)

健壮的程序要求,在一个函数内部,所有异常分支都要考虑回收资源,例如内存,若进入异常分支导致函数提前return,需要保证所有资源得到回收,否则会造成资源泄漏。C语言没有好的解决方案,需要程序员手动在所有异常分支增加释放机制,这样带来两个问题:一、增加了设计成本,既要保证所有分支兼顾,又要防止释放语句多次调用导致资源释放两次二、后续对该函数进行改造时,例如新增了一个异常分支,后来者很难注意到这个细节,程序的可维护性不好C中为了解决这个问题,常用两种方法,一种是封装一个资源清理函数,缺陷是针对每

2020-07-24 11:07:19 1166 1

原创 《c++并发编程实战解析》 无锁数据结构 doubly-buffered-data

多线程环境设计数据结构相比单线程,需要额外注意的是利用多线程提升并发度同时保持数据结构不变性,即满足如下两个原则:1、正确性,保证多线程并发访问没有 data race2、性能,保护最小的数据,提供最大的性能《c++并发编程实战》提供了一种【无锁数据结构】,注意这里无锁的含义不是真正无锁,而是利用数据结构特性保证运行时并发抢锁的线程数量最小,达到一种常态下访问数据结构不被锁阻塞的状态使用场景:1、读远多于写2、数据小,一般最大为几K字节的元数据3、数据可以应用到一致性状态机,即b

2020-05-22 17:57:32 1144

原创 缓存行和伪共享

cpu使用缓存以提升读取数据速度,缓存使用缓存行的形式,每次从主存load64字节到缓存。在多核架构中, 会发生一种伪共享的情况,原因是,每个cpu缓存自己的数据,cpu0对long i进行操作,缓存了i和i附近共计64字节数据;cpu1对long j进行操作,缓存了j和j附近共计64字节的数据。若i和j相邻,那么两个cpu缓存的就是主存中相同的一段64字节的内存数据。此时若cpu0对i的操作是写...

2019-11-07 14:58:26 477

原创 linux观察cpu常用命令

1、uptimecpu最近1、5、15分钟的负载,是百分比,如下2、vmstatvmstat显示内存、I/O、cpu等信息,通过每秒执行一个观察cpu利用率变化可以发现问题趋势,如下:us:用户态cpu时间sy:内核态cpu时间id:空闲时间wa:等待I/O时间st:虚拟机偷取cpu时间3、mpstat查看单个cpu时间,如下:mpstat ...

2019-11-05 15:23:40 490

原创 linux内存观察常用命令汇总

1、vmstat看系统总体内存情况,包括物理内存、虚拟内存、换页等情况vmstat 1 10:每1秒采样一次输出,持续10次vmstat -d:看磁盘情况vmstat -m:看内存详细情况,包括slab每个2的幂分配了多少个vmstat -S m:系统内存大的时候无法对齐, 按照MB显示可以对齐vmstat基本信息的解释:进程相关:r:当前在内核运行队列上的ta...

2019-11-05 14:28:13 499

原创 paxus made simple中文翻译

1、介绍paxos算法用于构建一个容错的分布式系统,它一直被认为是难以理解的,原因很可能是对于很多读者来说原始手稿是用希腊文实现的。实际上,这个算法基于最简单并且容易理解的分布式算法。它的核心是一个一致性算法:议会算法。下一章展示了这个一致性算法不可避免的遵循我们希望它满足的属性。最后一章展示了完整的paxos算法的实现,该算法从用于建立分布式系统的一个一致性状态机模型的直接应用中获得。这个一...

2019-10-31 10:44:23 248

原创 tcp几种常见异常出现情况总结

1.三次握手后连接成功建立,client发送RST到server,此时server阻塞在accept或者即将调用accept,accept会返回成功,得到一个sockfd,对此sockfd的read会导致一个connect reset by peer错误,注意此时tcp连接的终止不需要4次挥手,不会有TIME_WAIT状态。client端发送RST代码如下:struct linger s...

2019-10-25 11:01:35 2597

原创 pthread_cleanup_push注册清理函数中解锁导致的时间窗口问题

可以向其他线程发送pthread_cancel(threadid) ,让线程id为threadid的另一个线程取消,若threadid这个线程中使用了mutex,在lock和unlock期间收到了其他线程发来的取消要求,那么这个mutex没人解锁,造成死锁,解决这个问题的方案是注册线程清理函数,在清理函数中释放资源(解锁),但这样会造成一个时间窗口导致的额外加锁或者额外解锁,如下:pthre...

2019-10-16 18:23:55 204

原创 利用gdb调试线程验证多线程并发问题

一个经典问题,两个线程,都执行变量自增操作,由于实现是先将变量读到寄存器自增后再写回内存,不是一个汇编指令,导致存在窗口期,最后结果取决于执行顺序,变量的值可能多1或者多2,验证代码如下:int a;void func() {}void* thread_func1(void* arg) { func(); a++;}void* thread_func2(voi...

2019-10-12 18:53:46 1318

原创 linux 网络通信地址查询api

#include <netdb.h>struct hostent* gethostent(void);作用:返回本机主机信息。该函数读取/etc/hosts,逐行返回此文件中内容,即多次调用每次返回不同值,不可重入,示例:struct hostent* p;p = gethostent();while (p) { printf("%s\n", p->h_...

2019-10-10 20:13:37 191

原创 use of cast expressions as lvalues is deprecated

gcc编译warning:use of cast expressions as lvalues is deprecated,不建议将强转表达式作为左值,初衷是防止类型不一致导致解析非预期的类型,后续使用引发问题,如下void func() { void (*p)(void); void *j; (void*)p = j;}此时会报编译warning,此warn...

2019-09-27 15:34:45 234

原创 shell管道前后多个进程和进程组的关系

shell可以通过管道符将前一个进程的标准输出重定向到后一个进程的标准输入。用如下程序观察管道前后进程的父进程和进程组:void func() { printf("pid is %d\n", getpid()); printf("ppid is %d\n", getppid()); printf("group id is %d\n", getpgid(0));}...

2019-08-27 14:29:49 651 1

原创 linux常用命令词典

basename:获取文件名cat: -A:显示特殊字符 -n:行号,空白行也会带上cd: -:回到上一个目录 ~:回到自己的主文件夹chattr: -i:文件不可修改不可删除 -a:文件只能用append的方式追加内容,不能修改,也不能删除文件cp: -a:完全复制,包含文件上次修改时间也不会更新 -l:硬链接 -...

2019-08-19 19:30:07 441

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除