首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么每个人都使用2^n号来分配?->新StringBuilder(256)

为什么每个人都使用2^n号来分配?->新StringBuilder(256)
EN

Stack Overflow用户
提问于 2013-08-13 06:03:21
回答 5查看 723关注 0票数 10

15年前,当我使用Pascal编程时,我明白了为什么要使用两个人的能力来分配内存。但这似乎仍然是最先进的。

C#示例:

代码语言:javascript
运行
复制
new StringBuilder(256);
new byte[1024];
int bufferSize = 1 << 12;

我还是看到了几千次,我自己也用过这个,我还在质疑:

我们在现代编程语言和现代硬件中需要这一点吗?

我想这是很好的做法,但原因是什么呢?

编辑

例如,一个byte[]数组,正如这里的答案所述,2的幂是没有意义的:数组本身将使用16个字节(?),那么使用240 (=256-16)来容纳总共256个字节是否有意义?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-08-13 06:21:03

我们在现代编程语言和现代硬件中需要这一点吗?我想这是很好的做法,但原因是什么呢?

那得看情况。这里有两件事需要考虑:

  1. 对于小于内存页大小的大小,在分配空间的功率为2和任意数字之间没有明显的差别;
  2. 您主要是在C#中使用托管数据结构,因此您甚至不知道在下面实际分配了多少字节。

假设您正在使用malloc()进行低级别的分配,那么使用页面大小的倍数将被认为是一个好主意,即4096或8192;这是因为它允许更有效的内存管理。

我的建议是只分配您需要的东西,让C#为您处理内存管理和分配。

票数 4
EN

Stack Overflow用户

发布于 2013-08-13 06:47:50

可悲的是,如果你想把一个内存块保存在一个4k的内存页中,那是相当愚蠢的。人们甚至不知道:-) (直到10分钟前我才知道.我只有一个预感)..。一个例子..。它是不安全的代码和实现依赖(使用.NET 4.5在32/64位)

代码语言:javascript
运行
复制
byte[] arr = new byte[4096];

fixed (byte* p = arr)
{
    int size = ((int*)p)[IntPtr.Size == 4 ? -1 : -2];
}

因此CLR至少分配了4096 + (1或2)大(Int).所以它已经超过了一个4k内存页。这是合乎逻辑的。它必须保持数组的大小,并且将它与数组放在一起是最明智的事情(对于那些知道Pascal和BSTR是什么的人来说,是的,这是相同的原则)

我要补充的是,.NET中的所有对象都有一个同步数字和一个RuntimeType.它们至少是int (如果不是IntPtr ),所以总共有8到16个字节/对象(这在不同的地方都有解释.如果你感兴趣的话,试着去找.net object header )

票数 2
EN

Stack Overflow用户

发布于 2013-08-13 06:32:48

在某些情况下,这仍然是有意义的,但我更愿意逐个分析我是否需要这种规范,而不是盲目地把它作为良好的实践。

例如,在某些情况下,您可能希望使用确切的8位信息(1字节)来寻址表。

在这种情况下,我会让表的大小为2^8。

代码语言:javascript
运行
复制
Object table = new Object[256];

这样,您就可以只使用一个byte来处理表中的任何对象。

即使该表实际上较小,并且没有使用所有256个位置,您仍然可以保证从表到索引和从索引到表之间的双向映射,这可以防止出现错误,例如,如果您有:

代码语言:javascript
运行
复制
Object table = new Object[100];

然后有人(可能是其他人)使用超出表范围的字节值访问它。

也许这种双射行为可能是好的,也许你可以有其他的方法来保证你的约束。

也许,鉴于当前编译器的智能性增加,这不再是唯一的好做法了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18201761

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档