内存分配量计算

news/2024/11/8 6:30:01/

内存池采用了slab分配思路,内存被划分成多种不同大小的内存单元,在分配内存时根据使用者请求的内存大小进行计算,匹配最接近的内存单元。在计算时分下面几种情况:

请求的内存大小是否超过了chunkSize,如果已超出说明一个该内存已经超出了一个chunk能分配的范围,这种内存内存池无法分配应由JVM分配,直接返回原始大小。

请求大小大于等于512,返回一个512的2次幂倍数当做最终的内存大小,当原始大小是512时,返回512,当原始大小在(512,1024]区间,返回1024,当在(1024,2048]区间,返回2048等等。

请求大小小于512,返回一个16的整数倍,原始大小(0,16]区间返回16,(16,32]区间返回32,(32,48]区间返回48等等,这些大小的内存块在内存池中叫tiny块。

相关代码在PoolArena的normalizeCapacity方法:

    int normalizeCapacity(int reqCapacity) {if (reqCapacity < 0) {throw new IllegalArgumentException("capacity: " + reqCapacity + " (expected: 0+)");}if (reqCapacity >= chunkSize) {return directMemoryCacheAlignment == 0 ? reqCapacity : alignCapacity(reqCapacity);}if (!isTiny(reqCapacity)) { // >= 512// Doubledint normalizedCapacity = reqCapacity;normalizedCapacity --;normalizedCapacity |= normalizedCapacity >>>  1;normalizedCapacity |= normalizedCapacity >>>  2;normalizedCapacity |= normalizedCapacity >>>  4;normalizedCapacity |= normalizedCapacity >>>  8;normalizedCapacity |= normalizedCapacity >>> 16;normalizedCapacity ++;if (normalizedCapacity < 0) {normalizedCapacity >>>= 1;}assert directMemoryCacheAlignment == 0 || (normalizedCapacity & directMemoryCacheAlignmentMask) == 0;return normalizedCapacity;}if (directMemoryCacheAlignment > 0) {return alignCapacity(reqCapacity);}// Quantum-spacedif ((reqCapacity & 15) == 0) {return reqCapacity;}return (reqCapacity & ~15) + 16;}

分配的内存大小小于512时内存池分配tiny块,大小在[512,pageSize]区间时分配small块,tiny块和small块基于page分配,分配的大小在(pageSize,chunkSize]区间时分配normal块,normall块基于chunk分配,内存大小超过chunk,内存池无法分配这种大内存,直接由JVM堆分配,内存池也不会缓存这种内存。

 

关于Doubled算法:

            int normalizedCapacity = reqCapacity;normalizedCapacity |= normalizedCapacity >>>  1;normalizedCapacity |= normalizedCapacity >>>  2;normalizedCapacity |= normalizedCapacity >>>  4;normalizedCapacity |= normalizedCapacity >>>  8;normalizedCapacity |= normalizedCapacity >>> 16;normalizedCapacity ++;

以128 双倍为例:

10000000

|

01000000

=

11000000

 

11000000

|

00110000

=

11110000

 

11110000

|

00001111

=

11111111

 

11111111

|

00000000

=

11111111

 

11111111

|

00000000

=

11111111

最后结果:256

 

解析:

对于不超过2的16方的数,最高数字位是1,右移一位,做或运算,可以保证最高两位数字位全是1;再右移两位,做或运算后,最高四位数字位全是1;依次类推,最高位是1的个数倍增。

据此,255 运算后,因为全部数字位都是1,所以运算后,还是255。

转载于:https://www.cnblogs.com/pugongying017/p/9616333.html


http://www.ppmy.cn/news/241128.html

相关文章

输入压缩空间量是分区量吗_如何调整分区大小,系统分区该分几个?

小编今天讲下新电脑 调整分区大小 和 系统分区数量 的问题。目前出厂电脑部分仅有一个 C 盘( 机械硬盘笔记本常见 )存在,还有预分 C ( 常见容量在 70 - 80 GB 之间 )和 D 两个分区。小编建议 前者 再分区个 D 盘用来 保存文件、安装软件,建议 后者 对 C 盘进行扩容至 100GB 以…

位段和联合体的内存分配及大小计算

目录 一、位段 二、联合体 一、位段 位段一次开辟1或4个字节的空间&#xff0c;不够再继续开辟。 struct A {int a : 2;int b : 5;int c : 10;int d : 30; }; int a : 2; 给a分配两个byte的内存空间 因为a的参数类型为int&#xff0c;一次开辟4个字节 a占2byte&#xf…

STL中的内存分配方式

转自(http://www.cnblogs.com/LUO77/p/5824625.html) 在STL中考虑到小型区块所可能造成的内存碎片问题&#xff0c;SGI STL设计了双层级配置器&#xff0c;第一级配置器直接使用malloc()和free();第二级配置器则视情况采用不同的策略&#xff1a;当配置区块超过128bytes 时&am…

S32K144内存分配

本文将通过实际的工程代码介绍NXP S32K144单片机变量地址分配&#xff0c;应用笔记仅用于自己学习及大家参考。 示例代码如下&#xff1a; uint8_t num_byte[4]; uint32_t num_word; const uint32_t num_word_const 0x1234; uint32_t *point_heap; int main(void) { uint8_t…

内存管理(一)——内存分配

前言 我们都知道&#xff0c;计算机工作的过程概括起来就是 CPU 去内存中读取指令并执行的过程&#xff0c;但是如果运行我们的程序直接操作物理内存&#xff0c;将会引发很多的问题&#xff08;比如不同进程之间访问/修改的隔离、权限等等&#xff09;&#xff0c;所以爱操心…

DDR3地址及容量大小

DDR3 地址线 DDR3为减少地址线&#xff0c;把地址线分为行地址线和列地址线&#xff0c;在硬件上是同一组地址线&#xff1b;地址线和列地址线是分时复用的&#xff0c;即地址要分两次送出&#xff0c;先送出行地址&#xff0c;再送出列地址。 一般来说列地址线是10位&a…

STM32——根据地址计算存储空间的大小

首先要知道 1MB1024KB 1KB1024Byte 1Byte8bit 存储空间大小结束地址-起始地址1&#xff08;用十进制来算&#xff0c;得到结果的单位是Byte&#xff09; 十六进制与2进制转换表 十六进制2进制00000100012001030011401005010160110701118100091001A&#xff08;10&#xf…

STL六大组件之——分配器(内存分配,好深奥的东西)

SGI设计了双层级配置器&#xff0c;第一级配置器直接使用malloc()和free()&#xff0c;第二级配置器则视情况采用不同的策略&#xff1a;当配置区块超过128bytes时&#xff0c;视之为“足够大”&#xff0c;便调用第一级配置器&#xff1b;当配置区小于128bytes时&#xff0c;视…