c# - 数组元数据问题(缓存行)

标签 c# .net

得到了一些简单的代码

Int32[] tmpInt = new Int32[32];

            long lStart = DateTime.Now.Ticks;


            Thread t1 = new Thread(new ThreadStart(delegate()
            {
                for (Int32 i = 0; i < 100000000; i++)
                    Interlocked.Increment(ref tmpInt[5]);
            }));

            Thread t2 = new Thread(new ThreadStart(delegate()
            {
                for (Int32 i = 0; i < 100000000; i++)
                    Interlocked.Increment(ref tmpInt[20]);
            }));


            t1.Start();
            t2.Start();

            t1.Join();
            t2.Join();

            Console.WriteLine(((DateTime.Now.Ticks - lStart)/10000).ToString());

这在我的 core 2 duo 上大约需要 3 秒。如果我将 t1 中的索引更改为 tmpInt[4],则需要约 5.5 秒。

无论如何,第一个缓存行在索引 4 处结束。因为一个缓存行有 64 个字节,而 5 个 int32 只有 20 个字节,这意味着在实际数组之前有 44 个字节的元数据和/或填充。

我测试的另一组值,其中 5 和 21。5 和 21 需要大约 3 秒,但是 5 和 20 需要大约 5.5 秒,但这是因为索引 20 与索引 5 共享相同的缓存行,因为它们是间隔开的在相同的 64 字节内。

所以我的问题是,.Net 在数组之前保留了多少数据,这个数量在 32 位和 64 位系统之间是否有变化?

谢谢:-)

最佳答案

当 CPU 尝试加载您的数组并遇到缓存未命中时,它会获取包含您的数组的内存块,但不一定从它开始。 .NET 不保证您的数组将缓存对齐。

为了回答您的问题,44 字节的填充大部分是来自关联页面的其他数据,这些数据恰好位于同一缓存行中。

编辑:http://msdn.microsoft.com/en-us/magazine/cc163791.aspx似乎表明一个数组有 16 个字节的额外存储空间。 4 个字节是同步块(synchronized block)索引,4 个字节用于类型句柄元数据,其余是对象本身。

作为附带评论,很难准确地说虚假共享是您在这里延迟的原因。很可能给定了时间,但您应该使用一个好的分析器来检查缓存未命中率。如果它在您的给定案例中跳得很高,您可以非常确定您看到了虚假分享。

关于c# - 数组元数据问题(缓存行),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4403278/

相关文章:

c# - 确定是否设置了 "24-hour clock"设置

c# - 使用knockoutjs过滤有界项目

.net - 如何使用 .NET Compact Framework 显示动画 gif

c# - 如何实现业务伙伴提供的WSDL?

c# - 带输出的命令行病毒扫描

c# - 在 C# 中处理大文件时出现内存不足异常

c# - 使用 Visual C# 连接到远程 MySQL 数据库

c# - 路径存储在配置文件中?

c# - 从 UWP 应用程序请求永久访问文件夹

.net - 在安装新的 .net 框架之前安装以前的 .net 框架吗?