gpt4 book ai didi

c# - 为什么一个循环在内存和性能方面比其他循环表现更好?

转载 作者:行者123 更新时间:2023-11-30 22:27:26 25 4
gpt4 key购买 nike

我在 C# 中有以下两个循环,我正在为一个集合运行这些循环,该集合包含 10,000 条记录,使用“yield return”进行分页下载

首先

foreach(var k in collection) {
repo.Save(k);
}

第二个

 var collectionEnum = collection.GetEnumerator();
while (collectionEnum.MoveNext()) {
var k = collectionEnum.Current;
repo.Save(k);
k = null;
}

似乎第二个循环消耗的内存更少,而且比第一个循环更快。我理解的内存可能是因为 k 被设置为 null(尽管我不确定)。但是怎么会比for each快呢。

下面是实际代码

  [Test]
public void BechmarkForEach_Test() {
bool isFirstTimeSync = true;
Func<Contact, bool> afterProcessing = contactItem => {
return true;
};

var contactService = CreateSerivce("/administrator/components/com_civicrm");
var contactRepo = new ContactRepository(new Mock<ILogger>().Object);
contactRepo.Drop();
contactRepo = new ContactRepository(new Mock<ILogger>().Object);

Profile("For Each Profiling",1,()=>{
var localenumertaor=contactService.Download();
foreach (var item in localenumertaor) {

if (isFirstTimeSync)
item.StateFlag = 1;

item.ClientTimeStamp = DateTime.UtcNow;

if (item.StateFlag == 1)
contactRepo.Insert(item);
else
contactRepo.Update(item);

afterProcessing(item);


}
contactRepo.DeleteAll();
});

}


[Test]
public void BechmarkWhile_Test() {
bool isFirstTimeSync = true;
Func<Contact, bool> afterProcessing = contactItem => {
return true;
};

var contactService = CreateSerivce("/administrator/components/com_civicrm");
var contactRepo = new ContactRepository(new Mock<ILogger>().Object);
contactRepo.Drop();
contactRepo = new ContactRepository(new Mock<ILogger>().Object);

var itemsCollection = contactService.Download().GetEnumerator();

Profile("While Profiling", 1, () =>
{
while (itemsCollection.MoveNext()) {

var item = itemsCollection.Current;
//if First time sync then ignore and overwrite the stateflag
if (isFirstTimeSync)
item.StateFlag = 1;

item.ClientTimeStamp = DateTime.UtcNow;

if (item.StateFlag == 1)
contactRepo.Insert(item);
else
contactRepo.Update(item);

afterProcessing(item);

item = null;
}
contactRepo.DeleteAll();

});
}

static void Profile(string description, int iterations, Action func) {

// clean up
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

// warm up
func();

var watch = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++) {
func();
}
watch.Stop();
Console.Write(description);
Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
}

我正在使用微基准测试,来自一个 stackoverflow 问题本身 benchmarking-small-code

花费的时间是

  • 对于经过的每个分析时间 5249 毫秒
  • 分析时间过去 116 毫秒

最佳答案

你的 foreach版本调用 var localenumertaor = contactService.Download();在配置文件操作中,而枚举器版本在 Profile 之外调用它打电话。

最重要的是,迭代器版本的第一次执行将耗尽枚举器中的项目,并在后续迭代中 itemsCollection.MoveNext()将返回 false 并完全跳过内部循环。

关于c# - 为什么一个循环在内存和性能方面比其他循环表现更好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11279786/

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