拍脑袋想出来的内存分配算法,大家来帮我分析分析,完善完善。
这个算法适合可变长对象,并且经常要扩展的内存块的分配,比如字符串。是空间换时间的算法。
想象一张长长的纸条,不断的对折它,就可以把纸条分成一格一格,而且每次对折格子小一半,数量多一倍是吧。这个算法和这个过程很想,因此我命名为折纸算法。
首先申请一块大内存,大小为 O,另外还需要2个变量,X 保存分配的次数,M 保存内部分配的对象的最大大小。
当每次分配内存时,第一次分配在偏移量0的位置,第二次 1/2 * O 的位置,第三次 1/4 * O, 第四次 3/4 * O, 第五次 1/8 * O, 第六次 3/8 * O ...
每次分配的时候,X 不断的 +1,因此从 O 和 X 可以直接计算出分配地址,好比每次都对折纸条,然后从新的折痕依次分配。
由于每次都是对半折,因此从内存块原始大小和分配次数可以计算出格子的大小,记 N。
这样分配的好处,不需要维护链表,只需要更新2个变量及计算就可以完成分配,这两个变量可以直接采用 CAS 操作一次更新,因此可以并行操作。
爆仓后,把引起爆仓的对象从内存池里拿出来就好了。
对象的大小越接近,内存浪费越少。如果对象大小差距比较大,可能比较浪费。但是你不需要预先设定格子的大小,格子是动态调整的,因此,有时候内存利用率比固定的算法更高。
PS: 这样分配对象天然对齐,并且天然免疫缓冲区冲突。
如果你需要分配的对象大小未知,并且经常需要扩展,也许可以试试它?
内存的释放可以采用多种策略,比如如果基于 GC 可以交换被释放对象和最后块(复制 M 个字节就可以了),或者另外维护一个被释放对象的链表等等。
由于 M 会不断变大,不会缩小,而M过大可能造成浪费,因此也可以想一些重置整个内存块的策略。
好了,我应该描述清楚了吧,大家思考一下,看看是否可行吧。