Redis源码学习(23),sds学习,sds.c(二)

1 sdsMakeRoomFor

1.1 方法说明

  扩容方法,扩大sds字符串末尾的空闲空间

1.2 方法源代码

/* Enlarge the free space at the end of the sds string so that the caller
 1. is sure that after calling this function can overwrite up to addlen
 2. bytes after the end of the string, plus one more byte for nul term.
 3.  4. Note: this does not change the *length* of the sds string as returned
 5. by sdslen(), but only the free buffer space we have. */
sds sdsMakeRoomFor(sds s, size_t addlen) {
    struct sdshdr *sh, *newsh;
	
	//获取sds空闲空间
    size_t free = sdsavail(s);
    size_t len, newlen;
	
	//如果空闲空间大于要增加的空间,则直接返回
    if (free >= addlen) return s;
	
	//获取sds的长度
    len = sdslen(s);
	
	//获取sds的指针
    sh = (void*) (s-(sizeof(struct sdshdr)));

	//计算新的字符串长度
    newlen = (len+addlen);

	//如果新的长度小于SDS最大预分配长度,则新的长度翻倍
    if (newlen < SDS_MAX_PREALLOC)
        newlen *= 2;

	//如果大于最大最大预分配,则加上着最大预分配长度
    else
        newlen += SDS_MAX_PREALLOC;

	//重新分配内存
    newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1);
    if (newsh == NULL) return NULL;
	
	//计算新的空闲空间
    newsh->free = newlen - len;
	
	//返回新的字符串
    return newsh->buf;
}

//sds.h
#define SDS_MAX_PREALLOC (1024*1024)

1.3方法理解

  1. 先获取原先sds的空闲空间。
  2. 判断空间空间是否足够需要增加的空间,如果空闲空间大于要增加的空间,则直接返回。
  3. 获取原先sds的长度和指针。
  4. 计算新的字符空间。
  5. 判断新的字的字符长度是否大于预分配配置,这个值在sds.h中定义,值为1M。
  6. 如果新的长度小于1M,则这次分配的空间为新长度的两倍。
  7. 如果新的长度大于1M,则在新长度的基础上加上1M。
  8. 分配新的sds空间。
  9. 计算新sds的空闲空间。
  10. 10.返回新的字符串指针。

  这个方法核心功能是对SDS动态扩容,如何扩容取决于新增的长度多少,如果没有超过1M则翻倍,超过了1M则加上1M。

2 sdsIncrLen

2.1 方法说明

  增加sds的字符长度,并减少相应的空闲空间,并在字符结尾设置结束符。

2.2 方法源代码

void sdsIncrLen(sds s, int incr) {
	
	//获取sds指针
    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
	
	//断言空间空间 是否大于新增的长度
    if (incr >= 0)
        assert(sh->free >= (unsigned int)incr);
    else
        assert(sh->len >= (unsigned int)(-incr));

	//字符长度 增加 
    sh->len += incr;

	//空间空间 减少
    sh->free -= incr;
	
	//字符结尾增加结束符
    s[sh->len] = '\0';
}

2.3 方法理解

  这个方法主要是对sds结构体中的len和free属性进行设置,增加了指定的字符长度,就要减少相应的空闲空间,并在字符结尾设置结束符。

3 sdscatlen

3.1 方法说明

  将字符串添加到sds字符串的结尾。

3.2 方法源代码

/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the
 * end of the specified sds string 's'.
 *
 * After the call, the passed sds string is no longer valid and all the
 * references must be substituted with the new pointer returned by the call. */
sds sdscatlen(sds s, const void *t, size_t len) {
    struct sdshdr *sh;
    size_t curlen = sdslen(s);
	
	//根据添加的字符串,进行动态扩容
    s = sdsMakeRoomFor(s,len);
    if (s == NULL) return NULL;
    sh = (void*) (s-(sizeof(struct sdshdr)));

	//将字符串复制到sds字符数组的结尾
    memcpy(s+curlen, t, len);

	//重新计算字符长度
    sh->len = curlen+len;
	
	//重新计算空闲空间
    sh->free = sh->free-len;
	
	//字符数组结尾设置结束符
    s[curlen+len] = '\0';
    return s;
}


/* Append the specified null termianted C string to the sds string 's'.
 *
 * After the call, the passed sds string is no longer valid and all the
 * references must be substituted with the new pointer returned by the call. */
sds sdscat(sds s, const char *t) {
    return sdscatlen(s, t, strlen(t));
}

/* Append the specified sds 't' to the existing sds 's'.
 *
 * After the call, the modified sds string is no longer valid and all the
 * references must be substituted with the new pointer returned by the call. */
sds sdscatsds(sds s, const sds t) {
    return sdscatlen(s, t, sdslen(t));
}

3.3 方法理解

  1. 根据添加的字符串,调用 sdsMakeRoomFor 方法进行动态扩容。
  2. 将字符串复制到sds字符数组的结尾。
  3. 重新计算sds的len和free属性。
  4. 结尾设置结束符,返回字符串指针。

4 总结

  1. sds结构需要增加字符串长度的时候会先调用 sdsMakeRoomFor 方法进行动态扩容。
  2. 一般操作了字符串都会变动 sds 的 len和free属性,两者一般是一加一减的关系。
  3. 每次变更sds都会在字符尾部设置结束符。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis中的SDS(Simple Dynamic Strings)使用空间预分配策略来优化字符串的增长操作。当需要对SDS进行修改并且需要扩展SDS的空间时,RedisSDS分配修改所需的空间,并额外分配一些未使用的空间。这样可以减少内存重分配的次数,提高性能。\[1\] SDS的空间分配策略可以杜绝缓冲区溢出的可能性。在执行修改操作之前,API先检查SDS的空间是否满足修改所需的需求,如果不满足,则自动将SDS的空间扩展至所需的大小,然后再执行实际的修改操作,并同时分配未使用的空间。这样可以确保SDS出现缓冲区溢出问题。\[2\] 总结来说,RedisSDS使用空间预分配策略来优化字符串的增长操作,并通过检查和自动扩展空间来避免缓冲区溢出问题。这些策略可以提高Redis的性能和安全性。 #### 引用[.reference_title] - *1* [RedisSDS](https://blog.csdn.net/sssxlxwbwz/article/details/123064278)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Redis底层数据结构-SDS](https://blog.csdn.net/weixin_45275107/article/details/126037496)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [redis SDS介绍](https://blog.csdn.net/Mr_Z2017512/article/details/122232918)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值