【发布时间】:2014-05-26 18:48:47
【问题描述】:
出于好奇,我尝试同时使用value 和reference 类型来测试List<T> 的性能。
结果与我预期的不一样,这让我相信我对这些对象在内存中的布局方式的理解可能不正确。
这是我的实验:
创建一个基本的
class,只包含两个成员,一个int和一个bool创建 2 个
List<T>对象来保存我的测试类(List1和List2)随机生成测试对象并交替添加到
List1和List2遍历
List1需要多长时间(执行一些任意工作,例如递增计数器然后访问元素)
然后我用struct 代替class 重复了一遍
我的假设是,当使用 class 时,List<T> 中的引用是连续的,但由于我创建它们的方式(在添加到 List1 和 List2 之间切换),它们的对象指向可能不会。
我认为当使用 struct 时,因为它是一种值类型,所以对象本身将连续保存在内存中(因为 List<T> 保存实际项目而不是引用集合)。
因此,我希望 struct 表现更好(由于预取器等)
事实上,两者非常相似。
这是怎么回事?
编辑 - 添加代码以实际访问迭代器中的元素,包括代码示例
测试类(或结构)
public class/struct TestClass
{
public int TestInt;
public bool TestBool;
}
创建随机列表:
var list1 = new List<TestClass>();
var list2 = new List<TestClass>();
var toggle = false;
for (var i=0; i < 4000000; i++)
{
// Random object generation removed for simplicity
if (toggle)
list1.Add(randomObject);
else
list2.Add(randomObject);
toggle = !toggle;
}
测试:
var stopWatch = new Stopwatch();
var counter = 0;
var testBool = false;
stopwatch.Start();
foreach(var item in list1)
{
// Access the element
testBool = item.TestBool;
counter++;
}
stopwatch.Stop();
将TestObject 重复为class 和struct。
我意识到没有太大区别,但我预计 struct 的性能明显优于 class
【问题讨论】:
-
向我们展示您的基准
-
像这样的微基准测试是出了名的不可靠。代码太快了,像未对齐的分支目标这样简单的事情就可以产生很大的不同。标准错误是测量抖动时间并且没有重复测试至少 10 次。
-
@HansPassant 谢谢我尝试访问元素(代码示例和指标更新)性能似乎更加平等。我仍然希望
struct表现更好,但也许正如你所说,这个测试并不代表真实场景。 -
@HansPassant 您能否建议我如何正确地进行基准测试,或者在这样的简化示例中不可能给出真正的结果?
标签: c# memory-management struct clr prefetch