字节对齐

Ehcache计算Java对象内存大小

最后都变了- 提交于 2020-03-24 06:25:00
在EHCache中,可以设置maxBytesLocalHeap、maxBytesLocalOffHeap、maxBytesLocalDisk值,以控制Cache占用的内存、磁盘的大小(注:这里Off Heap是指Element中的值已被序列化,但是还没写入磁盘的状态,貌似只有企业版的EHCache支持这种配置;而这里maxBytesLocalDisk是指在最大在磁盘中的数据大小,而不是磁盘文件大小,因为磁盘文中有一些数据是空闲区),因而EHCache需要有一种机制计算一个类在内存、磁盘中占用的字节数,其中在磁盘中占用的字节大小计算比较容易,只需要知道序列化后字节数组的大小,并且加上一些统计信息,如过期时间、磁盘位置、命中次数等信息即可,而要计算一个对象实例在内存中占用的大小则要复杂一些。 计算一个实例内存占用大小思路 在Java中,除了基本类型,其他所有通过字段包含其他实例的关系都是引用关系,因而我们不能直接计算该实例占用的内存大小,而是要递归的计算其所有字段占用的内存大小的和。在Java中,我们可以将所有这些通过字段引用简单的看成一种树状结构,这样就可以遍历这棵树,计算每个节点占用的内存大小,所有这些节点占用的内存大小的总和就当前实例占用的内存大小,遍历的算法有:先序遍历、中序遍历、后序遍历、层级遍历等。但是在实际情况中很容易出现环状引用(最简单的是两个实例之间的直接引用

内存对齐

只愿长相守 提交于 2020-02-26 20:03:32
在结构体中,首次接触到了内存对齐 typedef struct inf { char name ; int age ; char sex ; } inf ; int main ( ) { inf zhang ; printf ( "sizefof = %d\n" , sizeof ( zhang ) ) ; return 0 ; } 结果: [ jwq@localhost memory ] $ . / mem_alg sizefof = 12 为什么要内存对齐? 计算机的内存是以字节(Byte)为单位划分的,理论上cpu可以访问任意编号的字节,但实际上不是如此。 以32位cpu为例,一次可以处理32位的数据,因此命令地址总线每次读取4字节的数据(32位)。这样能最有效的处理数据,因此 cpu寻址 以4字节为一个 步长 ,这样可以最快的速度寻址并处理数据,同时又不会造成遗漏。 对与程序来说一个变量最好位于一个寻址步长之内。若果不是那么需要分次读取再拼接数据,这样效率变低。 **将一个数据尽量放在一个步长之内,避免跨步长存储,这称为内存对齐。**这是一种牺牲空间换时间的做法。 最后,内存对齐的大小可以自己设定。 来源: CSDN 作者: 和平精英总指挥 链接: https://blog.csdn.net/weixin_44997886/article/details/104519485

C内存对齐

一世执手 提交于 2020-02-10 18:55:38
1.C语言中的结构体 1.1 定义 结构体 是由一系列相同或不同类型的变量组成的集合。 struct 结构体名{ //struct为关键字,“结构体名”为用户定义的 类型标识 。 数据类型1 成员名1; //{ }中是组成该结构体的成员,其中数据类型可以是C语言所允许的任何数据类型。 数据类型2 成员名2; ... 数据类型n 成员名n; }; 1.2 结构体的内存分配(方法一) 结构体在内存中分配一块连续的内存,但结构体内的变量并不一定是连续存放的,这涉及到内存对齐。 原则1 数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。 原则2 结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。) 原则3 收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。 例1. struct A{ struct B{ int a; char b; char b; int a; short c; short c; };

struct内存对齐

房东的猫 提交于 2020-02-03 08:38:28
内存对齐其实是为了在程序运行的时候更快的查找内存而做的一种编译器优化。 我们先看这样一个例子: 1 #include <iostream> 2 using namespace std; 3 4 struct vpoet 5 { 6 int a; //4 bytes 7 char b; //1 bytes 8 double c; // 8 bytes 9 char *d; //4 bytes 10 int e; //4 bytes 11 }; 12 13 int main() 14 { 15 cout<<"sizeof(vpoet)="<<sizeof(vpoet)<<endl; 16 return 0; 17 } 运行结果: 这个结构体大小为24个字节,但是我们仔细算一算其字节数 发现其实际上只有4+1+8+4+4=21个字节,那是如何算 出来24个字节的 呢,其实在默认情况下编译器是按照结构体 中所占字节最大的成员来进行内存对齐的。比如在结构体 vpoet中最大的是double double 占8个字节,那么 编译器 默认按8个字节的方式对齐那么编译器将按照大于实际字节数 的double最小整数倍来进行内存分配 。因而这里 实际是在结构体 的成员b后面填充了三个字节用于对齐。 那么问题来了,对齐方式可以改吗? 可以我们可以在文件头加上 1 #pragma pack(n)

python struct 官方文档

会有一股神秘感。 提交于 2020-01-27 08:42:29
from python3.6 7.1。struct-解释字节打包二进制数据 源代码: Lib / struct.py 此模块在Python值和表示为Python bytes对象的C结构之间执行转换。除其他来源外,它可用于处理存储在文件中或来自网络连接的二进制数据。它使用 格式字符串作为C结构布局的紧凑描述以及与Python值之间的预期转换 注意:默认情况下,打包给定C结构的结果包括填充字节,以维护所涉及C类型的正确对齐;同样,拆箱时也要考虑对齐方式。选择此行为是为了使打包结构的字节与对应的C结构的内存中的布局完全对应。要处理与平台无关的数据格式或忽略隐式填充字节,请使用standard大小和对齐方式,而不是 native大小和对齐方式:有关详细信息,请参见字节顺序,大小和对齐方式。 几个struct函数(和的方法Struct)采用一个缓冲区 参数。这是指实现缓冲区协议并提供可读或可写缓冲区的对象。用于此目的的最常见类型是bytes和bytearray,但是可以看作字节数组的许多其他类型实现了缓冲区协议,因此可以读取/填充它们,而无需从bytes对象进行其他复制。 7.1.1。功能和异常 该模块定义了以下异常和功能: 异常struct.error 在各种情况下都会出现例外;参数是描述错误的字符串。 struct.pack(fmt,v1,v2,… ) 返回一个字节对象

C语言内存对齐和结构补齐

我只是一个虾纸丫 提交于 2020-01-21 00:15:25
首先我们先看看下面的C语言的结构体: [cpp] view plain copy typedef struct MemAlign { int a; char b[3]; int c; }MemAlign; 以上这个结构体占用内存多少空间呢?也许你会说,这个简单,计算每个类型的大小,将它们相加就行了,以32为平台为例,int类型占4字节,char占用1字节,所以:4 + 3 + 4 = 11,那么这个结构体一共占用11字节空间。好吧,那么我们就用实践来证明是否正确,我们用sizeof运算符来求出这个结构体占用内存空间大小,sizeof(MemAlign),出乎意料的是,结果居然为12?看来我们错了?当然不是,而是这个结构体被优化了,这个优化有个另外一个名字叫“对齐”,那么这个对齐到底做了什么样的优化呢,听我慢慢解释,再解释之前我们先看一个图,图如下: 相信学过汇编的朋友都很熟悉这张图,这张图就是CPU与内存如何进行数据交换的模型,其中,左边蓝色的方框是CPU,右边绿色的方框是内存,内存上面的0~3是内存地址。这里我们这张图是以32位CPU作为代表,我们都知道,32位CPU是以双字(DWORD)为单位进行数据传输的,也正因为这点,造成了另外一个问题,那么这个问题是什么呢?这个问题就是,既然32位CPU以双字进行数据传输,那么,如果我们的数据只有8位或16位数据的时候

C语言基础--结构体对齐,位域,联合体

末鹿安然 提交于 2020-01-10 03:57:53
结构体对齐 1--结构体对齐的原因与意义 许多计算机系统对基本数据类型的可允许地址做出了一些限制,要求某种类型的对象的地址必须是某个值K(通常是2,4,8)的倍数,而这个k则被称为该数据类型的对齐模数(alignment modulus)。这种对其限制不仅简化了处理器与存储系统之间的接口的硬件设计,而且提高了存储系统的性能。 2 -- 结构体对齐包括两个方面的含义 1)结构体总长度 2)结构体内各数据成员的内存对齐,即该数据成员相对结构体的起始位置 3--不同编译器的对其策略 1)Linux沿用的对其策略是2字节的数据类型(例如short)的地址必须是2的倍数,而更大的数据类型(如int,double)的地址必须是4的倍数。 2)Windows对齐要求更要严格些,任何K字节(基本)对象的地址都必须是k的倍数。 4 -- 结构体大小的计算方法和步骤 1)将结构体内所有数据成员的长度值相加,记为sum_a; 2)将各数据成员为了内存对齐,按各自对齐模数而填充的字节数累加到和sum_a上,记为sum_b。对齐模数是#pragma pack指定的数值以及该数据成员自身长度中数值较小者。该数据相对起始位置应该是对齐模式的整数倍; 3)将和sum_b向结构体模数对齐,该模数是#pragma pac指定的数值和结构体内部最大的基本数据类型成员长度中数值较小者。结构体的长度应该是该模数的整数倍.

[go]内存对齐

余生长醉 提交于 2020-01-07 18:29:31
参考 参考-校对版 理解类型的本质 当我使用 C/C++ 编写代码时,理解类型(type)是非常有必要的。如果不理解类型,你就会在编译或者运行代码的时候,碰到一大堆麻烦。无论什么语言,类型都涉及到了编程语法的方方面面。 加强对于类型和指针的理解,对于提高编程水平十分关键。 本文会主要讲解类型。 我们首先来看看这几个字节的内存: 内存地址: FFE4 FFE3 FFE2 FFE1 存储的值: 00000000 11001011 01100101 00001010 请问地址 FFE1 上字节的值是多少? 如果你试图回答一个结果,那就是错的。为什么?因为我还没有告诉你这个字节表示什么。(不同类型的含义不同) 回答 10,那么你又错了。为什么?因为当我说这是数字的时候,你认为我是指十进制的数字。 基数(number base): 所有编号系统(numbering system)要发挥作用,都要有一个基(base)。 从你出生的时候开始,人们就教你用基数 10 来数数了。 这可能是因为我们大多数人都有 10 个手指和 10 个脚趾。另外,用基数 10 来进行数学计算也很自然。 基定义了编号系统所包含的符号数。基数 10 会有 10 个不同的符号,用以表示我们可以计量的无限事物。 基数 10 的编号系统为 0、1、2、3、4、5、6、7、8、9。一旦超过了 9,我们需要增加数的长度。 例如

C语言 结构体对齐

你说的曾经没有我的故事 提交于 2020-01-01 14:29:56
结构体本来应该占用1(char)+4(int)=5个字节,但是为了对齐,实际上占了1(char)+3(补充)+4(int)=8个字节 这是因为计算机读取数据时,一般标准化4个字节读取,为了节约时间,牺牲3个字符大小的内存,以空间换时间 # pragma warning(disable:4996) # include <stdio.h> struct test { char a ; int b ; } ; int main ( int argc , char * argv [ ] ) { struct test a = { 'a' , 1 } ; struct test * p = & a ; printf ( "结构体内存空间:%d字节,起始地址:%x,结束地址:%x\n" , sizeof ( struct test ) , p , p + sizeof ( struct test ) ) ; system ( "pause" ) ; return 0 ; } 参考: https://www.jianshu.com/p/f47e1fadb78e 来源: CSDN 作者: Claroja 链接: https://blog.csdn.net/claroja/article/details/103714766

字节对齐 详解

你离开我真会死。 提交于 2019-12-25 08:51:25
一.什么是字节对齐,为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任 何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的 排放,这就是对齐。 对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型 的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问 一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没 有这种情况,但是最常见的是如果不按照适合其平台要求对 数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int 型(假设为32位系统)如果存放在偶地址开始的地方,那 么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出 的结果的高低字节进行拼凑才能得到该32bit数 据。显然在读取效率上下降很多。 二.字节对齐对程序的影响: 先让我们看几个例子吧(32bit,x86环境,gcc编译器): 设结构体如下定义: struct A { int a; char b; short c; }; struct B { char b; int a; short c; };