Redis sds packed对齐理解
Redis sds 的源码中,使用了 __attribute__ ((__packed__))
,一般情况下,结构体会按其所有变量大小的最小公倍数做字节对齐,而用packed
修饰以后,结构体则变为按1字节进行对齐。这个最小公倍数如何进行理解呢?
以以下结构进行举例:
#include <stdio.h>typedef struct MemAlign
{ char a[18]; double b; char c; int d; short e;
}MemAlign;typedef struct __attribute__ ((__packed__)) MemAlignPacked
{ char a[18]; double b; char c; int d; short e;
}MemAlignPacked; int main(void){struct MemAlign m;struct MemAlignPacked mp;printf("========>%d", sizeof(m));printf("========>%d", sizeof(mp));
}
内存存放数据是为了给CPU进行使用,而CPU访问内存数据时会受到地址总线宽度的限制,并且CPU从内存中获取数据时起始地址必须是地址总线宽度的倍数,也就是说CPU是将内存分为一块一块的,块的大小取决于地址总线宽度,并且CPU读取数据也是一块一块读取的,块的大小称为(memory granularity)内存读取粒度。
上面的结构中,有char a[18]
这个属性,说明这个属性是占个字节的,在32位CPU的内存模型中,以4个字节对齐(如下图1),属性char a[18]
因为占了18个字节,会需要补齐2个字节达到4的最小公倍数20,然后接着分配double b
的内存地址(如下图2)。而使用了__packed__
修饰以后,就不需要补齐。
而在64位CPU的内存模型中,以8个字节进行对齐(如下图1)。则案例结构如下图2。我的mac是64位的,跑文章开始的代码跑出的结果和猜测的一样。
所以在redis的sds的源码中,出现的sdshdr5 、sdshdr8、sdshdr16、sdshdr32、sdshdr64,都使用了 __attribute__ ((__packed__))
进行紧凑排列。好处在于节省内存和方便buf[-1]取到flags地址,获取类型更加方便。
/* 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[];
};
一般情况下windows64位一般使用LLP64模型,64位Unix,Linux使用的是LP64模型
Datetype | LP64 | ILP64 | LLP64 | ILP32 | LP32 |
---|---|---|---|---|---|
char | 8 | 8 | 8 | 8 | 8 |
short | 16 | 16 | 16 | 16 | 16 |
int | 32 | 64 | 32 | 32 | 16 |
long | 64 | 64 | 32 | 32 | 32 |
long long | 64 | 64 | 64 | 64 | 64 |
pointer | 64 | 64 | 64 | 32 | 32 |
参考:
https://juejin.cn/post/7074538808259117064
https://blog.csdn.net/wejack/article/details/127686029
https://blog.csdn.net/weixin_40997360/article/details/79948968
https://zhuanlan.zhihu.com/p/140063999
https://juejin.cn/post/6922352059517779976
Redis sds packed对齐理解相关推荐
- redis sds的申请扩容源码
sds是redis中简单的字符串实现 sdsnewlen()方法可以用来申请sds. sds sdsnewlen(const void *init, size_t initlen); 第一个参数是sd ...
- Vins_mono重力对齐理解
// 6 通过将重力旋转到z轴上,得到世界坐标系与摄像机坐标系c0之间的旋转矩阵rot_diff// 此处解算得到的g是枢纽帧下的重力// 关于vins是4自由度的理解 四自由度应该指的是 x y z ...
- 缓存成神路:Redis读写分离难以理解?一文解析Redis读写分离技术
背景 云数据库Redis版不管主从版还是集群规格,replica作为备库不对外提供服务,只有在发生HA的时候,replica提升为master后才承担读写流量.这种架构读写请求都在master上完成, ...
- linux ls 输出对齐,理解 Linux 中 `ls` 的输出
ls 的输出会因各 Linux 版本变种而略有差异,这里只讨论一般情况下的输出. 下面是来自 man page 关于 ls 的描述: $ man ls ls - list directory cont ...
- 对于redis底层框架的理解(一)
近期学习了redis底层框架,好多东西之前都没听说过,算是大开眼界了. 先梳理下redis正常的通讯流程吧 首先服务器启动都有主函数main,这个main函数就在redis.c里 首先是initser ...
- redis并发锁 thinkphp5_资深架构师经典总结:Redis分布式锁实现理解
在Redis上,可以通过对key值的独占来实现分布式锁,表面上看,Redis可以简单快捷通过set key这一独占的方式来实现,也有许多重复性轮子,但实际情况并非如此. 总得来说,Redis实现分布式 ...
- c语言实现string sds,redis学习 - sds字符串
redis学习 - sds字符串 Redis 设计与实现:如果想要知道redis底层,这本书可以给予不少的帮助,非常推荐每一位学习redis的同学去翻一翻. sds字符串建议多看看源代码的实现,这篇文 ...
- Redis源码分析(sds)
源码版本:redis-4.0.1 源码位置:https://github.com/antirez/sds 一.SDS简介 sds (Simple Dynamic String),Simple的意思是简 ...
- 一、redis原理之string底层数据结构SDS
一.前言 我们说Redis 是用 C 语言写的,,但是对于Redis的字符串,却不是 C 语言中的字符串(即以空字符'\0'结尾的字符数组),它是自定义的数据结构SDS(simple dynamic ...
最新文章
- 生物识别技术在我们日常生活中的应用
- C# 轻量级ORM 编写思维
- 微信小程序实战篇:商品属性联动选择(案例)
- centos7开放80端口_Centos7.4系统 httpd模式搭建文件服务器
- hdu 2063 过山车(模板)
- [bzoj2588] Count on a tree
- java spark命令行执行参数
- c++按行读取txt文件中的内容,并按特定字符分割
- 国家信息安全水平考试NISP一级模拟题(01)
- 视频教程-Linux基础入门视频课程-Linux
- 【转载】ASP.Net请求处理机制初步探索之旅 - Part 3 管道
- openwrt之mwan3负载均衡·多线多拨
- PHP调用wsdl接口实例化SoapClient抛出异常
- 今天教你5种爆款标题,自媒体短视频标题写得好,月入过万少不了
- 手机端的日期选择的插件
- JAVA-多线程 三 {多线程状态}JAVA从基础开始 -- 3
- Week2 Assignment - Princeton-Algorithms-PartI
- 我对计算机的看法英语作文,我对网络的看法 My Concepts on Internet 英语作文范文...
- Office 2016 定制安装工具 v1.0 | Office 2016 自定义安装组件
- zw2012激活方法
热门文章
- python是一种解释型编程语言_python是不是解释型语言
- 思-中国移动通信研究院的面试题
- C语言循环语句实训项目,C语言程序设计与项目实训
- html输入框是一条横线,html把输入的文本框变成一个下横线css样式
- 手眼标定+jaka机械臂
- C# 图书管理系统(MySQL)——属性设计(三)
- 网络项目寻找创业合作伙伴
- python做社会网络分析_科学网-python 社会网络分析工具之igraph-郗强的博文
- word关闭未响应_写了两小时的文档没保存?!一个word小技巧来拯救
- 领英更新改版后,怎么登录国际版领英继续搜索开发客户?详细教程