3.30一周拾遗

一些杂项的积累

PHP配置文件找不到怎么破

使用PHP的phpinfo();来进行查找

1
2
3
4
5
6
// PHP CLI

php -r "phpinfo()" | grep "Loaded Configuration File" && "Configuration FIle";
// 但是找不到Loaded怎么办 或者Loaded出来是 none
// 一般是新的PHP没有将PHP.ini放到指定位置
// 原始的PHPINI可以从源码包找到 php.ini.production cp过去就可以了

Segment Fault 段错误 怎么进行debug

首先Linux系统默认是不dump Core的 需要设置unlimit 让系统对Fault的Core进行Dump

1
ulimit -c unlimited

就可以将出错时的内核文件进行输出 .Core.XXXX文件

然后 yum install gdb 然后

1
gdb php core.XXXX 进行分析 可以找出出错的行数

[未解决问题] 对PHP扩展开发的时候 return_value_used变量不能用

提示未定义 而且在源码包内对PHP_FUNCTION的宏定义中找不到这个变量 难道是PHP7更新之后自动可以GC的缘故?

Redis 内存数据库数据结构整理

SDS (动态字符串)

1
2
3
4
5
6
7
8
struct sdshdr {
int len; // SDS遵循C字符串以 '\0'为结尾的规则 但是 末尾的空不计算在len内
// 这样获取的长度的速度就是O(1)
// 还可以杜绝缓冲区溢出 在操作之前可以先看一下是否有足够的空间 如果没有就malloc C语言本身不记录string的长度
// 减少修改字符串带来的内存重新分配次数
int free;
char buf[];
}

SDS使用空间预分配和惰性空间释放策略 提升性能

空间与分配:

如果小于1MB

预分配相同的size

如果大于1MB

预分配1MB的size

二进制安全

避免使用 \0 导致字符串截断

Redis在读取字符串的时候是依据 SDS结构之内的len进行读取 有多少读多少

对比C字符串的优点

  • O(1)获取长度复杂度

  • 杜绝缓冲区溢出

  • 减少修改字符串带来的内存重新分配次数

  • 二进制安全

链表

链表提供高效的结点重排能力

1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef struct listNode {
struct listNode *prev;
struct listNode *next;
void *value;
}listNode;

typedef struct list {
listNode *head;
listNode *tail;
unsigned long len;
void *(*dup)(void *ptr)
void *(*free)(void *ptr)
int (*match)(void *ptr)
}list;

API时间复杂度

  • 返回值所在的index O(N)

  • 返回index所在的值 O(N)

  • 删除指定结点O(N)

  • 复制一个副本O(N)

  • 释放链表 O(N)

字典—使用哈希表实现

又被称为符号表、关联数组、或者映射

字典使用哈希表实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef struct dictEntry{ // 哈希表结点
void *key;

union {
// 同样采用联合体来节约内存
void *val;
uint64 _tu64;
int64 _ts64;
}v;
struct dictEntry *next;
}

typedef struct dict{
dictType *type;
void *privdata;

dictht ht[2];

// 平时数据会存在第一个HashTable 当进行rehash的时候使用第二个HashTable

}

解决HashTable的方法

有链接法和开放寻址法

链接法就是当发生index冲突的时候,在index处形成链表,新插入的在前面

开放寻址法就是发生index冲突的时候,自动向下寻址

HashTable的API时间复杂度

  • 向HashTable加新的元素 O(1)

  • 释放HashTable O(N)

跳跃表-有序set的实现之一

跳跃表支持平均O(logN)、最坏O(N)的复杂度查找

。。。说实话跳跃表没咋看懂

跳跃表API时间复杂度

  • 寻找 删除 返回排位 平均O(logN) 最坏O(N)

  • 给定一个范围 如果有一个在范围之内 就可以 O(1)

整数集合 set的单纯整数实现

1
2
3
4
5
6
7
typedef struct intset{
uint32_t encoding;

uint32_t length;

int 8_t content[]; // 不仅会保存int8的数据 保存类型取决于encoding;
}intset;

整数集合API时间复杂度

  • 添加新元素复杂度为O(N) // 因为每次操作都可能引起升级 所以会大一点

  • 整数集合不会降级 保证性能

压缩列表 列表键和哈希键的实现之一

压缩列表是连续内存构成的顺序结构

[zlbytes, zltail, zllen, entry1, entry2, …, zlend];

zlbytes: 表示压缩列表总长度

zltail: 压缩列表尾部指针P

zllen: 压缩列表数据个数

通过以上三个参数 可以分别计算出每个数据点的指针 从尾部开始计算即可

压缩列表结点构成

[previous_entry_length, encoding, content]

pre记录了前一个结点的长度

可以根据当前结点的起始地址计算出前一个结点的起始地址指针

压缩列表API时间复杂度

  • 创建一个包含指定结点的压缩列表 O(N) 最坏O(N*N)

  • 插入结点 O(N) 最坏O(N*N)

  • 返回index的结点O(N)

  • 找到包含指定值的 O(N) 最坏O(N*N)

  • 删除指定结点 O(N) 最坏O(N*N)

  • 返回结点数量 结点数量小于65535 O(1) 最坏O(N*N)

REDIS对象以及实现

Redis_string

int raw embstr;

redis_list

ziplist hashtable intlist

redis_hash

ziplist hashtable

redis_set

intset hashtable

reids_zset

ziplist skiplist

猜你喜欢

转载自www.cnblogs.com/xiaoerli520/p/9624272.html