Redis源码精读:字符串

文章目录

  • 前言
  • 代码位置
  • 核心类型
  • SDS结构
  • 获取sds字符串的元数据的宏
  • 获取字符串长度
  • 重新设置sds长度
  • 创建字符串
  • 感悟
  • 最后

前言

Redis中实现了sds(simple dynamic string)这种字符串,它比c语言标准库的char*字符串更加实用

代码位置

src/sdc.h
src/sdc.c

核心类型

// 底层字符数组
typedef char *sds;// 不同大小的sds的元数据和底层字符数组/* Note: sdshdr5 is never used, we just access the flags byte directly.* However is here to document the layout of type 5 SDS strings. */
struct __attribute__ ((__packed__)) sdshdr5 {unsigned char flags; /* 3 lsb of type, and 5 msb of string length */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {uint8_t len; /* used */uint8_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {uint16_t len; /* used */uint16_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {uint32_t len; /* used */uint32_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {uint64_t len; /* used */uint64_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};

SDS结构

在这里插入图片描述
类型别名sds实际就是底层的字符数组

获取sds字符串的元数据的宏

#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))

获取字符串长度

static inline size_t sdslen(const sds s) {// 根据偏移获取sds类型unsigned char flags = s[-1];// 根据相应sds类型获取sds对应的元数据,最后获取长度switch(flags&SDS_TYPE_MASK) {case SDS_TYPE_5:return SDS_TYPE_5_LEN(flags);case SDS_TYPE_8:return SDS_HDR(8,s)->len;case SDS_TYPE_16:return SDS_HDR(16,s)->len;case SDS_TYPE_32:return SDS_HDR(32,s)->len;case SDS_TYPE_64:return SDS_HDR(64,s)->len;}return 0;
}

重新设置sds长度

// newlen: sds新长度
static inline void sdssetlen(sds s, size_t newlen) {// 根据偏移获取sds类型unsigned char flags = s[-1];// 根据相应sds类型获取sds对应的元数据,然后设置其长度switch(flags&SDS_TYPE_MASK) {case SDS_TYPE_5:{unsigned char *fp = ((unsigned char*)s)-1;*fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS);}break;case SDS_TYPE_8:SDS_HDR(8,s)->len = newlen;break;case SDS_TYPE_16:SDS_HDR(16,s)->len = newlen;break;case SDS_TYPE_32:SDS_HDR(32,s)->len = newlen;break;case SDS_TYPE_64:SDS_HDR(64,s)->len = newlen;break;}
}

创建字符串

// initlen: 初始化的长度
sds _sdsnewlen(const void *init, size_t initlen, int trymalloc) {//sds指针void *sh;// sds变量sds s;// 判定sds的类型char type = sdsReqType(initlen);/* Empty strings are usually created in order to append. Use type 8* since type 5 is not good at this. */if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8;int hdrlen = sdsHdrSize(type);unsigned char *fp; /* flags pointer. */size_t usable;assert(initlen + hdrlen + 1 > initlen); /* Catch size_t overflow */// 分配内存sh = trymalloc?s_trymalloc_usable(hdrlen+initlen+1, &usable) :s_malloc_usable(hdrlen+initlen+1, &usable);if (sh == NULL) return NULL;if (init==SDS_NOINIT)init = NULL;else if (!init)memset(sh, 0, hdrlen+initlen+1);// 指向sh底层的字符数组s = (char*)sh+hdrlen;fp = ((unsigned char*)s)-1;usable = usable-hdrlen-1;if (usable > sdsTypeMaxSize(type))usable = sdsTypeMaxSize(type);// 根据类型进行相应元数据的设置switch(type) {case SDS_TYPE_5: {*fp = type | (initlen << SDS_TYPE_BITS);break;}case SDS_TYPE_8: {SDS_HDR_VAR(8,s);sh->len = initlen;sh->alloc = usable;*fp = type;break;}case SDS_TYPE_16: {SDS_HDR_VAR(16,s);sh->len = initlen;sh->alloc = usable;*fp = type;break;}case SDS_TYPE_32: {SDS_HDR_VAR(32,s);sh->len = initlen;sh->alloc = usable;*fp = type;break;}case SDS_TYPE_64: {SDS_HDR_VAR(64,s);sh->len = initlen;sh->alloc = usable;*fp = type;break;}}if (initlen && init)// 拷贝指定长度的字符串给smemcpy(s, init, initlen);// 设置结束符s[initlen] = '\0';// 返回底层字符数组return s;
}// 创建指定长度的字符串
sds sdsnewlen(const void *init, size_t initlen) {return _sdsnewlen(init, initlen, 0);
}

感悟

  1. 相比于c语言char*,sds更加易用,可以通过元数据获取信息,无需像char*每次获取长度时进行遍历
  2. sds可以表示含有“\0”的数据,因为sds是通过长度来界定字符串的,而不是像char*通过"\0"来确定字符串
  3. sds使用不同类型来表示不同大小的字符串,不同类型的sds使用attribute ((packed))的紧凑型内存布局来节省内存

最后

我是醉墨居士,我会继续分享Redis源码相关内容😊

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/527569.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python自动化测试脚本可以测php吗_python unittest实现api自动化测试_python

这篇文章主要为大家详细介绍了python unittest实现api自动化测试的方法&#xff0c;具有一定的参考价值&#xff0c;感兴趣的小伙伴们可以参考一下 项目测试对于一个项目的重要性&#xff0c;大家应该都知道吧&#xff0c;写python的朋友&#xff0c;应该都写过自动化测试脚本。…

Linux服务器版本鼠标,安装GPM给Linux虚拟控制台提供配置鼠标支持

给你的 Linux 系统安装 GPM&#xff0c;这样我们就可以在虚拟控制台中配置鼠标&#xff0c;比如进行复制与粘贴操作。GPM 是一个守护程序&#xff0c;是通用鼠标的首字母的缩写&#xff0c;它可以帮助你配置 Linux 虚拟控制台的鼠标支持。GPM 在以下场景中特别有用&#xff1a;…

valgrind 内存泄漏_应用 AddressSanitizer 发现程序内存错误

应用 AddressSanitizer 发现程序内存错误作为 C/ C 工程师&#xff0c;在开发过程中会遇到各类问题&#xff0c;最常见便是内存使用问题&#xff0c;比如&#xff0c;越界&#xff0c;泄漏。过去常用的工具是 Valgrind&#xff0c;但使用 Valgrind 最大问题是它会极大地降低程序…

linux软件读取不到空间,Linux下Oracle软件、数据文件等所在的磁盘分区空间不足的解决思路...

虚拟机中的Oracle运行的久了&#xff0c;归档、数据文件不断增长&#xff0c;原来安装ORACLE的分区空间不足。此时可以重新向虚拟机增加一块硬盘&#xff0c;将ORACLE的数据文件或归档的目录挂载到新增加的磁盘分区上。--我这里未新增加磁盘&#xff0c;而是将原磁盘未划分分区…

linux qt 读系统信息,使用Qt获取系统版本

获取Windows&#xff0c;Mac&#xff0c;IOS&#xff0c;Android&#xff0c;Linux等系统版本信息。Qt 4版本可以获取到系统版本的变量或函数头文件#include 使用公有静态变量和静态方法获取Windows系统版本const WinVersion WindowsVersionWinVersion windowsVersion ()使用公…

python元组元素删除_Python3基础 通过拆分元素 把元组的数据删除

镇场诗&#xff1a; 诚听如来语&#xff0c;顿舍世间名与利。愿做地藏徒&#xff0c;广演是经阎浮提。 愿尽吾所学&#xff0c;成就一良心博客。愿诸后来人&#xff0c;重现智慧清净体。 ——————————————————————————————————————————…

上海建桥学院linux网络管理实验报告,上海建桥学院信息技术系《操作系统(Linux).PDF...

上海建桥学院信息技术系《操作系统(Linux).PDF上海建桥学院信息技术系《操作系统(Linux )》课程教学大纲一、课程的性质与任务(一)本课程的性质本课程主要面向信息技术系专科各专业&#xff0c;为专业基础课。(二)本课程的任务本课程作为主要课程体现在信息技术系专科各专业的培…

配置文件存int类型_Redis详解(五)------ redis的五大数据类型实现原理

> 本系列教程持续更新&#xff0c;可以微信搜索「 IT可乐 」第一时间阅读。回复《电子书》有我为大家特别筛选的书籍资料前面两篇博客&#xff0c;第一篇介绍了五大数据类型的基本用法&#xff0c;第二篇介绍了Redis底层的六种数据结构。在Redis中&#xff0c;并没有直接使用…

Linux配置rsylogs日志发送,syslog强大而安全的日志处理系统

Ryslog是一个强大而安全的日志处理系统。Rsylog通过多个物理或虚拟服务器在网络上接收日志&#xff0c;并监视不同服务的健康状况。使用Rsyslog&#xff0c;您可以从集中位置监视其他服务器、网络设备和远程应用程序的日志。简介日志对于分析和排除Linux中的任何问题非常有用。…

java list 占用内存不释放_性能不打折,内存占用减少90%,Facebook提出极致模型压缩方法Quant-Noise...

对于动辄上百 M 大小的神经网络来说&#xff0c;模型压缩能够减少它们的内存占用、通信带宽和计算复杂度等&#xff0c;以便更好地进行应用部署。最近&#xff0c;来自 Facebook AI 的研究者提出了一种新的模型量化压缩技术 Quant-Noise&#xff0c;让神经网络在不降低性能的前…

苹果系统安装python环境_如何在mac下配置python虚拟环境

安装python虚拟环境核心目的就是为了复制一个python环境,这样新项目下载的所有包,都会存放在虚拟环境下的python site-package 中 首先安装 1. sudo pip install virtualenv # 安装虚拟环境 2. sudo pip install virtualenvwrapper # 安装虚拟环境扩展包 3. vim .bash_profile …

linux程序无法获取cpu资源,Linux系统编程获取系统的CPU资源

还是纯干货&#xff0c;代码拿来&#xff1a;#include #include #include #include #include #include #include void work(){FILE *f;int i;double x 4.5;f tmpfile();for(i 0; i < 10000;i){fprintf(f,"Do some output\n");if (ferror(f)){fprintf(stderr,&q…

为什么python除法结果会有小数点0_关于python:为什么整数除法会在许多脚本语言中向下取整?...

在我测试过的语言中&#xff0c;- (x div y )不等于-x div y&#xff1b; 我已经在Python中测试了//&#xff0c;在Ruby中测试了/&#xff0c;在Perl 6中测试了div&#xff1b; C具有类似的行为。 该行为通常是按照规范进行的&#xff0c;因为div通常被定义为除法结果的四舍五入…

linux udhcpc指令,dhcpclient和udhcpc区别和用法

udhcpc&#xff1a;1.开发板支持的指令&#xff0c;内核移植时通过make menuconfig打开或关闭,并且需要修改Busybox2.udhcpc只作为客户端使用&#xff0c;服务器指令为udhcpd.3.使用方法-i INTERFACE Interface to use (default: eth0)-r IP IP address to reques…

python求图形面积_求高效的,计算两多边形重叠面积的算法,python实现

[Asm] 纯文本查看 复制代码import random import time from sympy.geometry import * import numpy as np from scipy import stats def polygon_over_area(obj_a, obj_b): p_a obj_a # sympy.geometry.Polygon p_b obj_b x_obj p_a.intersection(p_b) if not x_obj: if p_b…

linux下c代码调用.so,Linux下C程序调用.so(动态链)的一个例子

/*********************************************** 使用Linux下C的动态链接库.So文件* void *pdlHandle;* pdlHandle dlopen("/home/fengsy/len/Len.So/len.so", RTLD_LAZY);* pnswapdlsym(pdlHandle, "swap");****************************************…

dbnetlib sqlserver不存在或拒绝访问_404:对不起,您访问的网页不存在

404&#xff1a;对不起您访问的网页不存在https://www.zhihu.com/video/1101123296195723264你可能在上网时也好奇过&#xff0c;为什么点开一个无法显示信息的页面&#xff0c;上面会出现数字404&#xff1f;要解释这个问题&#xff0c;我们需要从互联网诞生之初说起。20世纪8…

linux中控和安卓中控哪个比较好,原厂中控和改装中控有什么区别?哪个更好?...

很多人都喜欢车辆上有一个大屏的中控。那种大屏的中控不仅功能很多&#xff0c;而且还很实用。但是有很多车需要高配才能有中控。而且还需要加钱。很多人在买车的时候都会选择一些低配的车&#xff0c;然后自己去安装中控。有些人认为原厂的中控不仅价格贵&#xff0c;而且还有…

bufferedreader读取中文乱码_python之pandas模块关于csv文件乱码问题解决

介绍相信部分小伙伴们在处理windows系统生成的csv文件时会遇到中文显示乱码的问题&#xff0c;尤其是使用Excel打开这类文件时这类问题尤为突出。解决如图&#xff0c;我们通过Excel工具打开该csv文件时&#xff0c;中文展示为乱码。此时&#xff0c;只需要我们通过功能强大的数…

linux mint python3.6,Linux 上如何安装并切换最新版本的 Python 3.6

原标题&#xff1a;Linux 上如何安装并切换最新版本的 Python 3.6如果你安装了 Linux 系统&#xff0c;正在学习 Python 并想要使用最新的版本的话&#xff0c;那么这篇文章就是为你而写的。-- ShekinPython是 Linux 中一种最流行的编程语言。它被写成了各种工具和库。除此之外…