关于redis:Redis中的内存分配和原子操作

内容

  • redis中的内存调配api
  • redis中的原子操作api

源代码

Redis中的内存调配和原子操作

代码构建

cp /home/vagrant/github/server_installer/servers/redis/redis-6.2/src/zmalloc.* .
cp /home/vagrant/github/server_installer/servers/redis/redis-6.2/src/atomicvar.h .

zmalloc.c中援用了config.h, 删除掉

新建server.c, 内容如下

#include "stdio.h"
#include "atomicvar.h"
#include "zmalloc.h"
int main(int argc, char **argv){
    redisAtomic long  long i = 10;
    atomicIncr(i, 3);
    printf("hello %lld\n",i);
    char *p;
    p = zmalloc(10);
    p = "hello";
    printf("hello %s\n",p);
    int accurate;
    accurate = 10;
#ifdef REDIS_TEST
    zmalloc_test( argc,argv,accurate );
#endif
    return 0;
}

新建Makefile

server : zmalloc.o server.o
        $(CC)   -o $@   $^

%.o: %.c 
        $(CC) -DREDIS_TEST=1 -MMD -o $@ -c $<


.PHONY: clean
clean:
        rm -rf *.o *.d server

再看一下zmalloc_test的内容

#ifdef REDIS_TEST
#define UNUSED(x) ((void)(x))
int zmalloc_test(int argc, char **argv, int accurate) {
    void *ptr;

    UNUSED(argc);
    UNUSED(argv);
    UNUSED(accurate);
    printf("Malloc prefix size: %d\n", (int) PREFIX_SIZE);
    printf("Initial used memory: %zu\n", zmalloc_used_memory());
    ptr = zmalloc(123);
    printf("Allocated 123 bytes; used: %zu\n", zmalloc_used_memory());
    ptr = zrealloc(ptr, 456);
    printf("Reallocated to 456 bytes; used: %zu\n", zmalloc_used_memory());
    zfree(ptr);
    printf("Freed pointer; used: %zu\n", zmalloc_used_memory());
    return 0;
}
#endif

输入

hello 13
hello hello
Malloc prefix size: 0
Initial used memory: 24
Allocated 123 bytes; used: 160
Reallocated to 456 bytes; used: 480
Freed pointer; used: 24

解释

对于zmalloc函数,能够间接对应到c规范库里的malloc, realoc, free函数,redis会依据不同的实现调用不同的内存调配库,以实现更好的性能以及更多的性能。因为redis中曾经写好测试了,咱们就间接调用了。这外面用到了预编译。失常的编译不会把测试函数编译进redis server中的。在编译多c文件中,没有制订如何生成*.o文件。当用上篇文章中的Makefile编译时会晋升找不到zmalloc_test的实现。通过查看redis的Makefile, 发现了

%.o: %.c
        $(CC) -DREDIS_TEST=1 -MMD -o $@ -c $<

外面的MMD是什么含意呢,上面参考文章有具体的解释,这里总结一下
. M 依赖的文件
. MM 去除#include援用的依赖后的依赖
. D 是生成依赖文件,后缀为.d, 所以有MD 和MMD,这里用的MMD

linux下原子操作是C11中的封装。

gcc -MM zmalloc.c

输入为:zmalloc.o: zmalloc.c zmalloc.h atomicvar.h

redis zmalloc & atomic api

  • size_t zmalloc_used_memory(void) — 动静分配内存
  • void *zmalloc(size_t size)–分配内存
  • void zrealloc(void ptr, size_t size)– 从新分配内存
  • void zfree(void *ptr) — 开释内存
  • atomicIncr(var,count) — 原子加
  • atomicGetIncr(var,oldvalue_var,count) — Get and increment the atomic counter
  • atomicDecr(var,count) — 原子减
  • atomicGet(var,dstvar) — 原子取
  • atomicSet(var,value) — 原子设置数
  • atomicGetWithSync(var,value) — 原子取, 不胜利始终循环
  • atomicSetWithSync(var,value) — 原子设置, 不胜利始终循环

参考

MMD含意

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理