Redis原始碼分析(二十八)--- object建立和釋放redisObject物

來源:互聯網
上載者:User

標籤:

          今天的學習更有效率。該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物

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.