今天的学习更有效率。该Rio分析过,学习之间的另一种方式RedisObject文件,只想说RedisObject有些生成和转换。都是很类似的。列出里面长长的API列表:

/* ------------  API --------------------- */
robj *createObject(int type, void *ptr) /* 最初的创建robj对象方法,后面的创建方法与此相似 */
robj *createStringObject(char *ptr, size_t len)
robj *createStringObjectFromLongLong(long long value)
robj *createStringObjectFromLongDouble(long double value)
robj *dupStringObject(robj *o)
robj *createListObject(void)
robj *createZiplistObject(void)
robj *createSetObject(void)
robj *createIntsetObject(void)
robj *createHashObject(void)
robj *createZsetObject(void)
robj *createZsetZiplistObject(void)
void freeStringObject(robj *o) /* free Obj中的特定对象,这里free的是r->ptr */
void freeListObject(robj *o)
void freeSetObject(robj *o)
void freeZsetObject(robj *o)
void freeHashObject(robj *o) /* 释放hashObject有2种形式,1个是o-ptr的字典对象,还有1个回事压缩表o->ptr */
void incrRefCount(robj *o) /* robj对象增减引用计数,递增robj中的refcount的值 */
void decrRefCount(robj *o) /* 递减robj中的引用计数。引用到0后。释放对象 */
void decrRefCountVoid(void *o)
robj *resetRefCount(robj *obj)
int checkType(redisClient *c, robj *o, int type) /* 检查robj的类型是否为给定的Type类型 */
int isObjectRepresentableAsLongLong(robj *o, long long *llval)
robj *tryObjectEncoding(robj *o) /* 编码一个robj中的额字符对象,主要是为了省空间 */
robj *getDecodedObject(robj *o) /* 获取解码后的robj */
int compareStringObjectsWithFlags(robj *a, robj *b, int flags)
int compareStringObjects(robj *a, robj *b)
int collateStringObjects(robj *a, robj *b)
int equalStringObjects(robj *a, robj *b)
size_t stringObjectLen(robj *o)
int getDoubleFromObject(robj *o, double *target) /* 从robj中获取double数值 */
int getDoubleFromObjectOrReply(redisClient *c, robj *o, double *target, const char *msg)
int getLongDoubleFromObject(robj *o, long double *target)
int getLongDoubleFromObjectOrReply(redisClient *c, robj *o, long double *target, const char *msg)
int getLongLongFromObject(robj *o, long long *target)
int getLongLongFromObjectOrReply(redisClient *c, robj *o, long long *target, const char *msg)
int getLongFromObjectOrReply(redisClient *c, robj *o, long *target, const char *msg)
char *strEncoding(int encoding)
unsigned long estimateObjectIdleTime(robj *o)
robj *objectCommandLookup(redisClient *c, robj *key) /* obj的查找命令, */
robj *objectCommandLookupOrReply(redisClient *c, robj *key, robj *reply)
void objectCommand(redisClient *c)

从前往后看。第一个创建obj:

/* 最初的创建robj对象方法 */
robj *createObject(int type, void *ptr) {
robj *o = zmalloc(sizeof(*o));
o->type = type;
o->encoding = REDIS_ENCODING_RAW;
o->ptr = ptr;
o->refcount = 1; /* Set the LRU to the current lruclock (minutes resolution). */
o->lru = server.lruclock;
return o;
}

有创建就必定会有释放的free方法:

/* free Obj中的特定对象 */
void freeStringObject(robj *o) {
if (o->encoding == REDIS_ENCODING_RAW) {
sdsfree(o->ptr);
}
}

free方法有非常多衍生的方法。看你要释放哪种类型的空间了,能够,set,dict,ziplist等等。有以下的一些类型:

 switch(o->type) {
case REDIS_STRING: freeStringObject(o); break;
case REDIS_LIST: freeListObject(o); break;
case REDIS_SET: freeSetObject(o); break;
case REDIS_ZSET: freeZsetObject(o); break;
case REDIS_HASH: freeHashObject(o); break;
default: redisPanic("Unknown object type"); break;
}

重点介绍里面的关于引用计数的相关方法,通过robj->refcount的数值进行控制的:

/* robj对象增减引用计数,递增robj中的refcount的值 */
void incrRefCount(robj *o) {
//递增robj中的refcount的值
o->refcount++;
}

添加引用计数就一行代码,可是递减的话。我们猜也能够猜到,引用计数变为0的时候,说明无人使用了,就能够释放空间了;

/* 递减robj中的引用计数,引用到0后。释放对象 */
void decrRefCount(robj *o) {
//假设之前的引用计数已经<=0了,说明出现异常情况了
if (o->refcount <= 0) redisPanic("decrRefCount against refcount <= 0");
if (o->refcount == 1) {
//假设之前的引用计数为1,再递减一次。恰好内有被不论什么对象引用了,所以就能够释放对象了
switch(o->type) {
case REDIS_STRING: freeStringObject(o); break;
case REDIS_LIST: freeListObject(o); break;
case REDIS_SET: freeSetObject(o); break;
case REDIS_ZSET: freeZsetObject(o); break;
case REDIS_HASH: freeHashObject(o); break;
default: redisPanic("Unknown object type"); break;
}
zfree(o);
} else {
//其它对于>1的引用计数的情况,仅仅须要按常规的递减引用计数就可以
o->refcount--;
}
}

标准的引用计数法控制内存的管理。(提醒一下,在JVM中的对象的生命周期管理用的是根搜索法。不是引用计数)。另一个在robj中的编码方法的实现也是定义在这个文件里:

/* Try to encode a string object in order to save space */
/* 编码一个robj中的额字符对象。主要是为了省空间 */
robj *tryObjectEncoding(robj *o) {
long value;
sds s = o->ptr;
size_t len; if (o->encoding != REDIS_ENCODING_RAW)
//假设robj已经被编码了,则直接返回
return o; /* Already encoded */ /* It's not safe to encode shared objects: shared objects can be shared
* everywhere in the "object space" of Redis. Encoded objects can only
* appear as "values" (and not, for instance, as keys) */
/* 假设robj的引用计数超过1个人引用的时候。是不安全的去编码obj,由于对象是共享的 */
if (o->refcount > 1) return o; /* Currently we try to encode only strings */
redisAssertWithInfo(NULL,o,o->type == REDIS_STRING); /* Check if we can represent this string as a long integer */
len = sdslen(s);
if (len > 21 || !string2l(s,len,&value)) {
/* We can't encode the object...
*
* Do the last try, and at least optimize the SDS string inside
* the string object to require little space, in case there
* is more than 10% of free space at the end of the SDS string.
*
* We do that for larger strings, using the arbitrary value
* of 32 bytes. This code was backported from the unstable branch
* where this is performed when the object is too large to be
* encoded as EMBSTR. */
if (len > 32 &&
o->encoding == REDIS_ENCODING_RAW &&
sdsavail(s) > len/10)
{
//调用sdsRemoveFreeSpace把0->ptr中的字符串中的空格给移除掉
o->ptr = sdsRemoveFreeSpace(o->ptr);
}
/* Return the original object. */
return o;
}
.....

就是移除字符串中的空格所占的空间。

想相应也存在一个getDecodeObject(),:

/* Get a decoded version of an encoded object (returned as a new object).
* If the object is already raw-encoded just increment the ref count. */
/* 获取解码后的robj */
robj *getDecodedObject(robj *o) {
robj *dec; if (o->encoding == REDIS_ENCODING_RAW) {
//假设没有编码方式。则直接添加引用计数。并返回
incrRefCount(o);
return o;
}
if (o->type == REDIS_STRING && o->encoding == REDIS_ENCODING_INT) {
char buf[32];
//假设是string。Type并且是encoding_int方式的,先做一步转换
ll2string(buf,32,(long)o->ptr);
dec = createStringObject(buf,strlen(buf));
return dec;
} else {
redisPanic("Unknown encoding type");
}
}

以上是对RedisObject简单分析。

版权声明:本文博主原创文章。博客,未经同意不得转载。

Redis源代码分析(二十八)--- object创建和释放redisObject物的更多相关文章

  1. Spring源码分析(十八)创建bean

    本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.创建bean的实例 1. autowireConstructor 2 ...

  2. Redis源代码分析(十二)--- redis-check-dump本地数据库检測

    这个文件我在今天分析学习的时候,一直有种似懂非懂的感觉,代码量700+的代码,最后开放给系统的就是一个process()方法.这里说的说的数据库检測,是针对key的检測,会用到,以下提到的结构体: / ...

  3. ABP源码分析二十八:ABP.MemoryDB

    这个模块简单,且无实际作用.一般实际项目中都有用数据库做持久化,用了数据库就无法用这个MemoryDB 模块了.原因在于ABP限制了UnitOfWork的类型只能有一个(前文以作介绍),一般用了数据库 ...

  4. Redis源代码分析(十)--- testhelp.h小测试框架和redis-check-aof.c 日志检测

    周期分析struct结构体redis代码.最后,越多越发现很多的代码其实大同小异.于struct有袋1,2不分析文件,关于set集合的一些东西,就放在下次分析好了,在选择下个分析的对象时,我考虑了一下 ...

  5. Vue.js 源码分析(二十八) 高级应用 transition组件 详解

    transition组件可以给任何元素和组件添加进入/离开过渡,但只能给单个组件实行过渡效果(多个元素可以用transition-group组件,下一节再讲),调用该内置组件时,可以传入如下特性: n ...

  6. PostgreSQL的 initdb 源代码分析之十八

    继续分析: setup_conversion(); 展开: 其实质是: 运行命令:"/home/pgsql/project/bin/postgres" --single -F -O ...

  7. WCF技术剖析之二十八:自己动手获取元数据[附源代码下载]

    原文:WCF技术剖析之二十八:自己动手获取元数据[附源代码下载] 元数据的发布方式决定了元数据的获取行为,WCF服务元数据架构体系通过ServiceMetadataBehavior实现了基于WS-ME ...

  8. JAVA之旅(二十八)——File概述,创建,删除,判断文件存在,创建文件夹,判断是否为文件/文件夹,获取信息,文件列表,文件过滤

    JAVA之旅(二十八)--File概述,创建,删除,判断文件存在,创建文件夹,判断是否为文件/文件夹,获取信息,文件列表,文件过滤 我们可以继续了,今天说下File 一.File概述 文件的操作是非常 ...

  9. Bootstrap <基础二十八>列表组

    列表组.列表组件用于以列表形式呈现复杂的和自定义的内容.创建一个基本的列表组的步骤如下: 向元素 <ul> 添加 class .list-group. 向 <li> 添加 cl ...

随机推荐

  1. SWT的TreeViewer和TableViewer的交互

    左边是一个TreeViewer,右边是一个TableViewer.当点击左边的treeitem的时候,右边的tableViewer要将该item的子节点信息显示出来.就像这样: 左边的treeView ...

  2. 推测的手机型号和cpu模型

    <span style="font-size:18px;">推断手机型号:</span> <span style="font-size:18 ...

  3. oracle database 12c R1 安装文档

    INSTALLORACLE DATABASE 12C 完整的安装文档下载地址: http://download.csdn.net/detail/royjj/5665869 OS:ORALCE LINU ...

  4. ECLIPSE JSP TOMCAT 环境搭建

    ECLIPSE JSP TOMCAT 环境搭建(完整) 要学习一门语言,首先要做的就是搭建环境,然后能写一个小的Demo(类似Helloworld),不仅可以建立信心,而且还可以为之后的学习搭建一个验 ...

  5. hbase列表排序

    hbase都是依照字典序进行排序的,也就是降序,在页面的表现就是最早的数据(rowkey最小的)排在前面. 眼下的解决方式是:给主键添加一个外键关联表.外键的生成规则是 400000000000-主键 ...

  6. 华为-on练习--小写字符数的统计显示

    主题: 手动输入一个字符串,只有小写字母,统计每个字符和输出频率中出现的串,输出.提示可以使用map 样例:输入:aaabbbccc 输出:a 3 b 3 c 3 分析: 看到后面的提示,简直就是不用 ...

  7. android 如何分析java.lang.IllegalArgumentException: Cannot draw recycled bitmaps异常

    这类问题的分析,通常你需要找到bitmap对象已经在那个位置recyle,然后检查代码. 如何定位的位置,其中代码具有对bitmap 目的recyle.能够 Bitmap.java的recycle方法 ...

  8. atitit.报告最佳实践oae 和报告引擎的选择

    atitit.报告最佳实践oae 与报表引擎选型 1. 报表的基本的功能and结构 2 1.1. 查询设计器(配置化,metadata in html) ,anno 2 1.2. 查询引擎 2 1.3 ...

  9. Codeforces Round #248 (Div. 1)——Nanami&#39;s Digital Board

    题目连接 题意: 给n*m的0/1矩阵,q次操作,每次有两种:1)将x,y位置值翻转 2)计算以(x,y)为边界的矩形的面积最大值 (1 ≤ n, m, q ≤ 1000) 分析: 考虑以(x,y)为 ...

  10. 如何设置一个activity透明

    1.在AndroidManifest.xml文件中设置: android:theme="@android:style/Theme.Translucent 此代码固定为全背景透明. 2.在Ac ...