我正在尝试加速循环,该循环正在克隆 2_500_000 对象。 克隆本身整个循环要花费 800毫秒,但是当我将它们添加到列表中时,它要花费 3秒。.
List<T> list = new List<T>();
Stopwatch sw = new Stopwatch();
sw.Start();
foreach(T entity in listSource)
{
T entityCloned = GetEntityClone(entity); // Taking 800ms totally
if (entityCloned != null)
list.Add(entityCloned);
}
sw.Stop();
您能帮我找出为什么这些Add
花费这么多时间吗?
答案 0 :(得分:2)
不幸的是,循环遍历许多事物并进行深度复制需要花费时间。我认为3秒钟不一定是花费不合理的时间。
但是您可以潜在地提高速度。
首先,如果您事先知道结果列表需要保留多少个项目,则可以set the internal capacity beforehand以防止调整列表大小。调整大小是一项昂贵的活动,必要时可以避免。可以通过手动更改列表的容量属性或通过将容量作为constructor argument for the list传递来实现。
一旦分配了容量,应将the complexity添加到列表中O(1)
,而无需重新分配(这是O(n)
复杂性任务see this answer) 。在这种情况下,添加到列表中不太可能成为瓶颈。
您还可以从要复制的初始列表中删除空值,从而无需每次都要评估的if语句。使用linq:
var noNulls = listSource.where(o => o != null)
答案 1 :(得分:0)
我使用数组而不是列表节省了一些时间(大约33%):
MyObject类修饰:
public class MyObject
{
public int Id { get; set; }
public bool Flag { get; set; }
public static MyObject GetEntityClone(MyObject obj)
{
if (obj == null) return null;
var newObj = new MyObject()
{
Id = obj.Id,
Flag = obj.Flag
};
return newObj;
}
}
代码:
var sourceList = new List<MyObject>();
// let's mock the source data, every 27th element will be null
for (int i = 0; i < 2500000; ++i)
{
if (i % 27 != 0)
sourceList.Add(new MyObject { Id = i, Flag = (i % 2 == 0) });
}
var destArray = new MyObject[2500000];
Stopwatch sw = new Stopwatch();
sw.Start();
Console.WriteLine(sw.ElapsedMilliseconds);
var currentElement = 0;
for (int i = 0; i < sourceList.Count; ++i)
{
MyObject entityCloned = MyObject.GetEntityClone(sourceList[i]);
if (entityCloned != null)
destArray[currentElement++] = entityCloned;
}
var result = new MyObject[currentElement];
Array.Copy(destArray, 0, result, 0, currentElement);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
答案 2 :(得分:0)
尝试以下操作并行进行:
var message = new MimeMessage ();
message.From.Add (new MailboxAddress ("Joey", "joey@friends.com"));
message.To.Add (new MailboxAddress ("Alice", "alice@wonderland.com"));
message.Subject = "How you doin?";
var builder = new BodyBuilder ();
// Set the plain-text version of the message text
builder.TextBody = @"Hey Alice,... ";
// We may also want to attach a calendar event for Monica's party...
builder.Attachments.Add (@"C:\Users\Joey\Documents\party.ics");
// Now we just need to set the message body and we're done
message.Body = builder.ToMessageBody ();