gpt4 book ai didi

c# - Linq 性能和延迟执行

转载 作者:太空宇宙 更新时间:2023-11-03 20:36:48 27 4
gpt4 key购买 nike

我已经为 .Net CF 运行了一些测试。基本上,我想比较 for、foreach、扩展方法 ForEach 和 LINQ 查询。这是整个代码(你可以跳过它,以达到困扰我的地步)

namespace ForEachForLINQPerTest
{
class IntBox
{
public int fieldX;
public int PropertyX { get; set; }
}

public partial class MainPage : PhoneApplicationPage
{
/// <summary>
/// size of tested List
/// </summary>
public const int TEST_SIZE = 1000000;

//
private List<int> m_intList = new List<int>(TEST_SIZE);

//
private List<IntBox> m_intBoxList = new List<IntBox>(TEST_SIZE);

//
private Stopwatch m_stopwatch = null;
// Constructor
public MainPage()
{
InitializeComponent();

for (int i = 0; i < TEST_SIZE; ++i)
{
m_intBoxList.Add( new IntBox());
m_intList.Add(0);
}
}

private void startButton_Click(object sender, RoutedEventArgs e)
{
var forTest = ForTest(); // Jitter preheat
forTest = ForTest();
forResultTextBlock.Text = forTest;

var foreachTest = ForEachTest();
foreachTest = ForEachTest();
foreachResultTextBlock.Text = foreachTest;

var exTest = Extenstion();
exTest = Extenstion();
ExtensionResultTextBlock.Text = exTest;

var linqTest = LINQTest();
linqTest = LINQTest();
LINQResultTextBlock.Text = linqTest;
}

private string LINQTest()
{
m_stopwatch = new Stopwatch();
m_stopwatch.Start();
long temp = 0;
var result = from x in m_intList
select temp += x;
m_stopwatch.Stop();
var intListTime = m_stopwatch.ElapsedMilliseconds;
m_stopwatch.Reset();
result.ToList();


m_stopwatch.Start();
var result2 = from x in m_intBoxList
select temp += x.fieldX;
m_stopwatch.Stop();
var intBoxListFieldTime = m_stopwatch.ElapsedMilliseconds;
m_stopwatch.Reset();
result2.ToList();

m_stopwatch.Start();
var result3 = from x in m_intBoxList
select temp += x.PropertyX;
m_stopwatch.Stop();
var intBoxListPropertyTime = m_stopwatch.ElapsedMilliseconds;
m_stopwatch.Reset();
result3.ToList();
return String.Format("LINQ test List<int> = {0} \n List<IntBox> field = {1} \n List<IntBos> property = {2}", intListTime, intBoxListFieldTime, intBoxListPropertyTime);
}

private string Extenstion()
{
m_stopwatch = new Stopwatch();
m_stopwatch.Start();
long temp = 0;
m_intList.ForEach(i => temp += i);
m_stopwatch.Stop();
var intListTime = m_stopwatch.ElapsedMilliseconds;
m_stopwatch.Reset();


m_stopwatch.Start();
m_intBoxList.ForEach(i => temp += i.fieldX);
m_stopwatch.Stop();
var intBoxListFieldTime = m_stopwatch.ElapsedMilliseconds;
m_stopwatch.Reset();

m_stopwatch.Start();
m_intBoxList.ForEach(i => temp += i.PropertyX);
m_stopwatch.Stop();
var intBoxListPropertyTime = m_stopwatch.ElapsedMilliseconds;
m_stopwatch.Reset();
return String.Format("Extenstion test List<int> = {0} \n List<IntBox> field = {1} \n List<IntBos> property = {2}", intListTime, intBoxListFieldTime, intBoxListPropertyTime);
}

private string ForEachTest()
{
m_stopwatch = new Stopwatch();
long temp = 0;
m_stopwatch.Start();
foreach(int item in m_intList)
{
temp += item;
}
m_stopwatch.Stop();
var intListTime = m_stopwatch.ElapsedMilliseconds;
m_stopwatch.Reset();


m_stopwatch.Start();
foreach (IntBox item in m_intBoxList)
{
temp += item.fieldX;
}
m_stopwatch.Stop();
var intBoxListFieldTime = m_stopwatch.ElapsedMilliseconds;
m_stopwatch.Reset();

m_stopwatch.Start();
foreach (IntBox item in m_intBoxList)
{
temp += item.PropertyX;
}
m_stopwatch.Stop();
var intBoxListPropertyTime = m_stopwatch.ElapsedMilliseconds;
m_stopwatch.Reset();

return String.Format("ForEach test List<int> = {0} \n List<IntBox> field = {1} \n List<IntBos> property = {2}", intListTime, intBoxListFieldTime, intBoxListPropertyTime);
}

private string ForTest()
{
m_stopwatch = new Stopwatch();
m_stopwatch.Start();
long temp = 0;
for (int i = 0; i < TEST_SIZE; ++i)
{
temp += m_intList[i];
}
m_stopwatch.Stop();
var intListTime = m_stopwatch.ElapsedMilliseconds;
m_stopwatch.Reset();


m_stopwatch.Start();
for (int i = 0; i < m_intList.Count; ++i)
{
temp += m_intBoxList[i].fieldX;
}
m_stopwatch.Stop();
var intBoxListFieldTime = m_stopwatch.ElapsedMilliseconds;
m_stopwatch.Reset();

m_stopwatch.Start();
for (int i = 0; i < m_intList.Count; ++i)
{
temp += m_intBoxList[i].PropertyX;
}
m_stopwatch.Stop();
var intBoxListPropertyTime = m_stopwatch.ElapsedMilliseconds;
m_stopwatch.Reset();

return String.Format("For loop test List<int> = {0} \n List<IntBox> field = {1} \n List<IntBos> property = {2}", intListTime, intBoxListFieldTime, intBoxListPropertyTime);
}
}
}

这里我很困惑

        m_stopwatch = new Stopwatch();
m_stopwatch.Start();
long temp = 0;
var result = from x in m_intList
select temp += x;
m_stopwatch.Stop();
var intListTime = m_stopwatch.ElapsedMilliseconds;
m_stopwatch.Reset();
result.ToList();

输出是:

For循环测试List = 93
列表字段 = 119//ref -> 字段
List property = 136//ref -> property -> field 属性只是 CF 的函数

ForEach 测试列表 = 88
列表字段 = 140
列表属性 = 152

Extensions test List = 176
//另一个函数被调用。列表字段 = 220
列表属性 = 239

LINQ 测试列表 = 0 为什么?
列表字段 = 163
列表属性 = 165

为什么 intListTime == 0?我究竟做错了什么?此外,字段和属性的最后两个值几乎相同(运行几次)。这是否意味着 LINQ 查询中的 PropertyX 是在线求值的?

最佳答案

第一次为零,因为表达式树是在编译时构建的,它会在您未包含在计时中的 ToList 调用上进行评估。

对于字段和属性访问时间,我不会太担心 - 实际上,在发布版本中,简单的属性访问器将被内联,提供与字段访问相同的性能。对于 linq 情况,您可能会看到相同的性能,因为 linq 在内部可能会将属性/字段访问转换为方法调用,并且会导致相同的时间(因为我相信与字段/prop 相比,方法调用开销可能会很大访问权限。

关于c# - Linq 性能和延迟执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4755223/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com