读<<Redis设计与实现>>与redis(5.0)源码__对象

redisObject

1
2
3
4
5
6
7
8
9
10
11
typedef struct redisObject {
unsigned type:4; // 类型,4位
unsigned encoding:4; // 编码
// 上次访问时间
// #define LRU_BITS 24
unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
* LFU data (least significant 8 bits frequency
* and most significant 16 bits access time). */
int refcount; // 引用次数
void *ptr; // 底层地址
} robj;

阅读更多

读<<Redis设计与实现>>与redis(5.0)源码__ziplist

ziplist构成

zlbytes- ztail- zllen- entrys-…- zlend
uint32_t uint32_t uint16_t zlentry uint8_t

因为zlend使用固定值ZIP_END = 255作为结束标志(0xFF作为uint8的最大值,与prevlen单字节长度0xFE进行区别,同时是最后面的两个数作为标志(这个懂的吧)).

阅读更多

vimium

chrome扩展vimium

使用说明

  • 前缀 c=ctrl, m=meta, a=alt,大写+shift

  • 当前页的操作

    • 使用 ? 调出使用说明,快捷键列表
    • h,j,k,l 左下上右滚动
    • gg回到顶部
    • G到页面底部
    • d下滚半屏
    • u上滚半屏
    • f在当前tab打开链接
    • F在新tab打开链接
    • r刷新
    • gs查看源码
    • i 进入插入模式,其他键失效,知道ESC
    • yy复制当前url
    • yf复制链接url
    • gf进入下一个frame
    • gF回到上级frame

阅读更多

读<<Redis设计与实现>>与redis(5.0)源码__skiplist

结构差异

结构定义在server.h文件
方法实现在t_zset.c文件(ziplist是压缩)

  1. zskiplistNode

    1
    2
    3
    4
    5
    6
    7
    8
    9
    typedef struct zskiplistNode {
    sds ele; // 原本是 robj *obj,表示保存的成员对象
    double score; // 分值
    struct zskiplistNode *backward; // 后退指针
    struct zskiplistLevel {
    struct zskiplistNode *forward; // 前进指针
    unsigned long span; // 跨度
    } level[];
    } zskiplistNode;
  2. zskiplist

    1
    2
    3
    4
    5
    typedef struct zskiplist {
    struct zskiplistNode *header, *tail; // 表头和表尾
    unsigned long length; // 长度,即节点数()不含表头
    int level; // 跳跃表内层数最大的节点的层数
    } zskiplist;

阅读更多

读<<Redis设计与实现>>与redis(5.0)源码__dict

结构差异

  1. dictEntry,该结构中union里面多了double类型d
1
2
3
4
5
6
7
8
9
10
typedef struct dictEntry {
void *key;
union {
void *val;
uint64_t u64;
int64_t s64;
double d;
} v;
struct dictEntry *next;
} dictEntry;
  1. dict,多了一个迭代标志
1
2
3
4
5
6
7
typedef struct dict {
dictType *type;
void *privdata;
dictht ht[2];
long rehashidx; /* rehashing not in progress if rehashidx == -1 */
unsigned long iterators; /* number of iterators currently running */
} dict;
  1. 不知道是不是多出来的迭代器(adlist也有)

    迭代器,大多用在rdb,aof,cluster场景中
    有safe的差异

    1
    2
    3
    4
    5
    6
    7
    8
    typedef struct dictIterator {
    dict *d;
    long index;
    int table, safe;
    dictEntry *entry, *nextEntry;
    /* unsafe iterator fingerprint for misuse detection. */
    long long fingerprint; // 在非安全模式模式下,迭代的时候生成一个指纹,在后续再次处理相应键的时候,对比指纹是否一致,判断键值是否被修改
    } dictIterator;

阅读更多

读<<Redis设计与实现>>与redis(5.0)源码__sds

主要是区别

  1. sdshdr

    不是单一的sdshdr结构,而是分了sdshdr5,sdshdr8,sdshdr16,sdshdr32,sdshdr64几种.鉴于对__attribute__的浅陋理解,是对某种结构属性的定义,也就是说可以当作同一个结构,然后在不同的场景,赋予了不同的结构属性.然后主要用flags的前三位(5种类型)来判断使用的是那种属性结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 这个不存在使用场景,只是给出理论上的属性结构
struct __attribute__ ((__packed__)) sdshdr5 {
unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
char buf[];
};

// 其他几种字段相同,但是len和alloc的类型结构跟着名称变
struct __attribute__ ((__packed__)) sdshdr8 {
uint8_t len; /* used */
// 这里是总分配,书中是`free`,这里`free`用`sdsavail`计算得到
uint8_t alloc; /* excluding the header and null terminator */
// 多出来的类型标志
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};

阅读更多

一次go内存泄漏调试

go性能调试工具

虽然不一定都需要

  • gv,go自带的pprof命令,实际上是Graphviz,搜索安装就可以了
  • web,同gv,不过是在浏览器中显示
  • go-torch,火焰图

阅读更多

go-runtime之HACKING.md

HACKING.md

这是作者对runtime设计的一个阐述,翻译内容是这样的

这是一份原型文档,虽然在当下可能已经有点过时了.目的是讲述go程序运行原理,与我们写的go代码有什么不同.着重讲述一些大概的概念而不是详细的细节.

阅读更多

go-runtime之cpuprof.go

cpuProfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type cpuProfile struct {
lock mutex
on bool // profiling is on
log *profBuf // profile events written here

// extra holds extra stacks accumulated in addNonGo
// corresponding to profiling signals arriving on
// non-Go-created threads. Those stacks are written
// to log the next time a normal Go thread gets the
// signal handler.
// Assuming the stacks are 2 words each (we don't get
// a full traceback from those threads), plus one word
// size for framing, 100 Hz profiling would generate
// 300 words per second.
// Hopefully a normal Go thread will get the profiling
// signal at least once every few seconds.
// extra累积着非Go创建的线程调用addNonGo获取的摘要标记,一旦有Go线程获得这些标记句柄,extra栈就会被写入日志文件
extra [1000]uintptr
numExtra int
lostExtra uint64 // count of frames lost because extra is full
}

阅读更多

go-runtime之chan*.go

文件注释

1
2
3
4
5
6
7
8
9
10
// Invariants:
// At least one of c.sendq and c.recvq is empty,
// except for the case of an unbuffered channel with a single goroutine
// blocked on it for both sending and receiving using a select statement,
// in which case the length of c.sendq and c.recvq is limited only by the
// size of the select statement.
//
// For buffered channels, also:
// c.qcount > 0 implies that c.recvq is empty.
// c.qcount < c.dataqsiz implies that c.sendq is empty.

翻译一下:
定式:
在无缓冲通道,除非send和rece都在单线程下阻塞, c.sendq和c.recvq至少有一个是空的,而且c.sendq和c.recvq的长度只受select语法限制

阅读更多