当前位置: 首页 > news >正文

怎样设计手机网站建设网站域名到期怎么续费

怎样设计手机网站建设,网站域名到期怎么续费,网站qq联系怎么做,wordpress 写博客问题: 1. sds 是什么 ? 2. sds 相对于char * 有什么好处 ?解决了哪些疑难杂症? 3. sds 有什么不足?可以优化的点? 思考下: 平常工作开发中,我们记录一条用户信息、订单信息&…

问题:

1. sds 是什么 ?

2. sds 相对于char * 有什么好处 ?解决了哪些疑难杂症?

3. sds 有什么不足?可以优化的点?

思考下:

平常工作开发中,我们记录一条用户信息、订单信息,redis内部是怎么帮我们把数据存起来的呢,是随意allot 一个内存,放进去嘛 ?

键值对中的键是字符串,值有时也是字符串。我们在 Redis 中写入一条用户信息,记录了用户姓名、性别、所在城市等,这些都是字符串,如下所示:

SET user:id:100 {"name": "zhangsan", "gender": "M","city":"beijing"}

大家如果有实际使用过redis那么都应该知道,类似这种字符串的操作在Redis中其实是最常见的,那么既然它被使用这么频繁,字符串的存储需要满足什么要求吗 ?

  1. 能支持丰富且高效的字符串操作,比如字符串追加、拷贝、比较、获取长度等;
  2. 能保存任意的二进制数据,比如图片等 能尽可能地节省内存开销。

在C语言中,使用char来实现字符串存储,定义了很多方法来满足日常开发,比如字符串比较函数 strcmp、字符串长度计算函数 strlen、字符串追加函数 strcat 等。那么下面来看下为什么不能直接使用Char

为什么Redis 不使用C的char呢 ?

首先redis是一个纯内存操作,结合它的使用属性,可以想到redis 要求性能高、存储小等特点,那么反过来看下char是否可以满足呢?

首先以字符串‘redis’为例看下使用char的存储结构,一块连续的内存空间,依次存放了字符串中的每一个字符数组结构。

\0 ,表示一个字符串的结尾,在C语言中,char* 指针只是指向字符数组的起始位置,而字符数组的结尾位置就用”\0"表示

如strlen 函数流程:

通过一段代码,可以更清晰看到\0的作用,这里我创建了两个字符串变量 a 和 b,分别给它们赋值为"red\0is"和"redis\0”。然后,我用 strlen 函数计算这两个字符串长度,如下所示:

  include <stdio.h>include <string.h>int main(){char *a = "red\0is";char *b = "redis\0";printf("%lu\n", strlen(a));printf("%lu\n", strlen(b));return 0;}

代码执行后,输出结果分别是3和5,a =3 , b= 5 字节。那么看到这问题也就出来了,我们都知道Redis是有保存二进制数据的需求的。如果使用char来存储会使二进制数据被截断,完全支持不了。

另外,回过来看strlen函数,虽然可以计算字符串长度,但是它也会带来另一方面的负面影响,也就是会导致操作函数的复杂度增加。需要遍历字符数组中的每一个字符,才能得到字符串长度,所以这个操作函数的复杂度是 O(N)。

再来看另一个函数,也是常用的strcat追加功能。strcat 函数是将一个源字符串 src 追加到一个目标字符串的末尾。该函数的代码如下所示:

  char *strcat(char *dest, const char *src) {//将目标字符串复制给tmp变量char *tmp = dest;//用一个while循环遍历目标字符串,直到遇到"\0"跳出循环,指向目标字符串的末尾while(*dest)dest++;//将源字符串中的每个字符逐一赋值到目标字符串中,直到遇到结束字符while((*dest++ = *src++) != '\0' )return tmp;}

从代码中可以看到,strcat 函数和 strlen 函数类似,复杂度都很高,也都需要先通过遍历字符串才能得到目标字符串的末尾。对于 strcat 函数来说,还要再遍历源字符串才能完成追加。另外,它在把源字符串追加到目标字符串末尾时,还需要确认是否空间足够。

SDS的设计

SDS(即简单动态字符串)的数据结构。下面我们一起来看看SDS 结构设计

SDS 结构里包含了一个字符数组 buf[],用来保存实际数据。同时,SDS 结构里还包含了三个元数据,分别是字符数组现有长度 len 、分配给字符数组的空间长度 alloc ,以及 SDS 类型 flags

typedef char *sds;

Redis 源码中 SDS 的定义,Redis 使用 typedef 给 char* 类型定义了一个别名,这个别名就是 sds。如上。那么到这里也可看得出本质其实还是个字符数组,只是在字符数组基础上增加了额外的元数据。

接下来,看下sdsnewlen 函数:

sds sdsnewlen(const void *init, size_t initlen) {void *sh;  //指向SDS结构体的指针sds s;     //sds类型变量,即char*字符数组...sh = s_malloc(hdrlen+initlen+1);   //新建SDS结构,并分配内存空间...s = (char*)sh+hdrlen;              //sds类型变量指向SDS结构体中的buf数组,sh指向SDS结构体起始位置,hdrlen是SDS结构体中元数据的长度...if (initlen && init)memcpy(s, init, initlen);    //将要传入的字符串拷贝给sds变量ss[initlen] = '\0';               //变量s末尾增加\0,表示字符串结束return s;

详细说下,创建一个SDS的过程:sdsnewlen 函数会新建 sds 类型变量(也就是 char* 类型变量),并新建 SDS 结构体,把 SDS 结构体中的数组 buf[] 赋给 sds 类型变量。最后,sdsnewlen 函数会把要创建的字符串拷贝给 sds 变量。

到此,我们已经了解SDS底层数据结构,那么对比一下与传统的C语言操作字符串,SDS有哪些优点:SDS 结构中记录了字符数组已占用的空间和被分配的空间,提高读写效率。同样以字符串追加为例,Redis 中实现字符串追加的函数是 sds.c 文件中的 sdscatlen 函数。

sds sdscatlen(sds s, const void *t, size_t len) {//获取目标字符串s的当前长度size_t curlen = sdslen(s);//根据要追加的长度len和目标字符串s的现有长度,判断是否要增加新的空间s = sdsMakeRoomFor(s,len);if (s == NULL) return NULL;//将源字符串t中len长度的数据拷贝到目标字符串结尾memcpy(s+curlen, t, len);//设置目标字符串的最新长度:拷贝前长度curlen加上拷贝长度sdssetlen(s, curlen+len);//拷贝后,在目标字符串结尾加上\0s[curlen+len] = '\0';return s;
}

同样,我们来画个流程图来梳理一下sdscatlen执行流程:

和char操作相比,SDS 通过记录字符数组的使用长度和分配空间大小,避免了对字符串的遍历操作,降低了操作开销,进一步就可以帮助诸多字符串操作更加高效地完成.

紧凑型字符串结构

        简单点说,sds设计了不同的结构头(也就是不同的类型),为了能灵活的保存不同大小的字符串,从而有效节省内存空间。保存不同大小的字符串时,结构头占用的内存空间也不一样,在保存小字符串时,结构头占用的空间也比较少。

        官方话语来说就是:SDS 一共设计了 5 种类型,分别是 sdshdr5、sdshdr8、sdshdr16、sdshdr32 和 sdshdr64。主要区别就在于,它们数据结构中的字符数组现有长度 len 和分配空间长度 alloc,这两个元数据的数据类型不同。

// attribute__ (__packed__) 采用紧凑的方式分配内存
struct __attribute__ ((__packed__)) sdshdr8 {uint8_t len; /* 字符数组现有长度*/uint8_t alloc; /* 字符数组的已分配空间,不包括结构体和\0结束字符*/unsigned char flags; /* SDS类型*/char buf[]; /*字符数组*/
};

上面代码片段可以看到,len、 alloc 都是uint_t 类型。是一个8位无符号整数,每个占用一个字节的空间,也就是说当字符串类型是 sdshdr8 时,它能表示的字符数组长度2的8次方。

同理, sdshdr16、sdshdr32、sdshdr64 三种类型来说,它们的 len 和 alloc 数据类型分别是 uint16_t、uint32_t、uint64_t,即它们能表示的字符数组长度,分别不超过 2 的 16 次方、32 次方和 64 次方。

说到这里也就大概了解不同的类型的作用了,那么还有一点要提一下,字节对齐方式和紧凑的方式分配内存

对齐和紧凑分配内存

        在默认情况下,编译器会按照 8 字节对齐的方式,给变量分配内存。也就是说,即使一个变量的大小不到 8 个字节,编译器也会给它分配 8 个字节。

看下面的两个例子,大概就懂了

 include <stdio.h>int main() {struct s1 {char a;int b;} ts1;printf("%lu\n", sizeof(ts1));struct __attribute__((packed)) s2{char a;int b;} ts2;printf("%lu\n", sizeof(ts2));}

char 类型占用 1 个字节,int 类型占用 4 个字节.,sizeof(ts1) ==8 , sizeof(ts2) == 5,剩下的自己琢磨啦

小结

加油、学到就是赚到,哪怕应付面试呢

http://www.yayakq.cn/news/761596/

相关文章:

  • 做短视频网站需要审批教新手做网站难吗
  • 成都网站设计网站广告软文营销平台
  • 网站建设中关村制作公司网站的公司
  • 有没有教做韩餐的网站美食网站建设项目规划书
  • 无锡网站维护公司软件开发app制作公司
  • 万网网站后台网站建站的职位
  • .net 网站管理系统建设大学网站费用
  • 网站热区图阿里巴巴网站建设公司
  • 网站底部技术支持企业服务网
  • 医疗网站建设策划书网页设计学习总结
  • 免费制作网站模板网页设计html代码大全划掉线
  • 网站建站需求电子商务类网站建设
  • 网站怎样做链接品牌网站建设搭建
  • 免费制作简历模板网站中国住房和城乡建设部网站首页
  • 自助建站什么意思微商城平台哪个好
  • 东莞房地产网站建设有培训做网站 小程序的学校
  • 网站建设规划书样板wordpress熊掌号自动推送
  • 怎么用ps做京东网站模板江苏营销型网站策划
  • 做网站设计的长宽一般是多少钱网片生产厂家
  • 用phpcms建站的网站国家企业信用系统官网
  • 沧浪设计网站公司网络营销导向网站建设的基础是什么
  • 顺德营销型网站淄博网站建设选哪家
  • 宁夏枸杞网站建设方案张家界网站制作公司
  • 一家只做家纺的网站ui设计案例作品
  • 广州网站建设 易企建站公司中国电信六大外包公司
  • 网站建设实训总结封面低代码开发平台公司
  • 购买网站开发服务费入账物流网站的建设方案
  • 已购买域名 如何做网站免费网页空间到哪申请
  • wordpress网站怎么样响应式网站可以做缩放图吗
  • 健康类网站模板wordpress 打赏功能