c# - C# foreach 性能与内存碎片
问题描述
追踪性能问题(我知道微)我以这个测试程序结束。使用框架 4.5 和发布模式编译,它在我的机器上花费了大约 10 毫秒。
如果我删除这条线有什么困扰我
public int[] value1 = new int[80];
时间接近 2 毫秒。似乎存在一些内存碎片问题,但我未能解释原因。我已经使用 Net Core 2.0 测试了该程序,结果相同。谁能解释这种行为?
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace ConsoleApp4
{
public class MyObject
{
public int value = 1;
public int[] value1 = new int[80];
}
class Program
{
static void Main(string[] args)
{
var list = new List<MyObject>();
for (int i = 0; i < 500000; i++)
{
list.Add(new MyObject());
}
long total = 0;
for (int i = 0; i < 200; i++)
{
int counter = 0;
Stopwatch timer = Stopwatch.StartNew();
foreach (var obj in list)
{
if (obj.value == 1)
counter++;
}
timer.Stop();
total += timer.ElapsedMilliseconds;
}
Console.WriteLine(total / 200);
Console.ReadKey();
}
}
}
更新:
经过一番研究,我得出结论,这只是处理器缓存访问时间。使用 VS 分析器,缓存未命中似乎要高得多
- 无数组
- 带数组
解决方案
有几个含义。
当你有你的 linepublic int[] value1 = new int[80];
时,你有一个额外的内存分配:在一个堆上创建一个新数组,它将容纳 80 个整数(320 字节)+ 类的开销。你做了 500 000 次这样的分配。
这些分配总计超过 160 MB 的 RAM,这可能会导致 GC 启动并查看是否有要释放的内存。
此外,当您分配如此多的内存时,列表中的某些对象很可能不会保留在 CPU 缓存中。当您稍后枚举您的集合时,CPU 可能需要从 RAM 中读取数据,而不是从缓存中读取数据,这将导致严重的性能损失。
推荐阅读
- python - Python为x和y轴上的每个第n个像素更改颜色
- powershell - 在powershell中复制具有匹配文件夹名的文件名
- php - 如何强制 laravel 不从符号链接读取存储文件
- java - 如何使用 AndroidPdfViewer 库从存储中显示 pdf 文件?
- python - 如何在生成 .png 文件的 python 中为 Networkx + Matplotlib 创建 .exe
- java - 以编程方式将 Android 应用程序从后台带回
- c# - 没有引用的 ASP.NET 重定向
- r - 在 R 中以特定日期为条件获取多个站点的天气数据
- django - Django 静态文件未加载到 heroku 服务器上,显示“拒绝应用来自 ' 的样式
' 因为它的 MIME 类型" - html - HTML输入日期,如何减少日期和图标之间的空间?