我有一个通过一些扩展方法修改数据的类。为了调试性能,我创建了一些粗略的调试代码,使用相同的数据多次调用相同的方法。我发现第一次通过循环执行计算所需的时间比后续调用要长得多。
例如,对于一小组数据,进行计算似乎需要大约5秒钟,而每次后续调用都是一秒左右。
谢谢, WTS
代码看起来像这样:
测试代码
void TestCode()
{
for (int i = 0; i < iterationsPerLoop; i++)
{
DateTime startTime = DateTime.Now;
// The test is actually being done in a BackgroundWorker
dispatcher.Invoke(DispatcherPriority.Normal,
(Action)(() => this.PropertyCausingCodeToRun = "Run";
while (this.WaitForSomeCondition)
Thread.Sleep(125);
DateTime endTime = DateTime.Now;
double result = endTime.Subtract(startTime).TotalSeconds;
}
}
扩展方法称为
的方法private static List<ObservableItem> GetAvailableItems(MyObject myObject)
{
var items = new List<ObservableItem>(myObject.Items.ToList());
var selectedItems = items.OrderByDescending(item => item.ASortableProperty)
.SetItemIsAvailable(false)
.SetItemPriority()
.OrderByDescending(item => item.Priority)
.Where(item => item.Priority > 0)
.SetItemIsAvailable(true)
.OrderBy(item => item.Date);
return selectedItems.ToList();
}
扩展方法(ObservableItems全部在不同的线程上创建)
static class MyExtensionMethods
{
public static IEnumerable<T> SetItemIsAvailable<T>(this IEnumerable<T> sourceList,
Boolean isAvailable) where T : ObservableItem
{
Action<T> setAvailable = i => i.IsAvailable = isAvailable;
List<DispatcherOperation> invokeResults = new List<DispatcherOperation>();
foreach (var item in sourceList)
{
invokeResults.Add(
item.ItemDispatcher.BeginInvoke(setAvailable , new object[] { item }));
}
invokeResults.ForEach(ir => ir.Wait());
return sourceList;
}
public static IEnumerable<T> SetItemPriority<T>(this IEnumerable<T> sourceList) where T : ObservableItem
{
Action<T, double> setPriority = new Action<T, double>((item, priority) =>
{
item.Priority = priority;
});
List<DispatcherOperation> invokeResults = new List<DispatcherOperation>();
foreach (var item in sourceList)
{
double priority = ......; // Some set of calculations
invokeResults.Add(
item.ItemDispatcher.BeginInvoke(setPriority,
new object[] { asset, priority }));
}
invokeResults.ForEach(ir => ir.Wait());
return sourceList;
}
}
答案 0 :(得分:4)
大多数情况下,第一次调用方法时,会有一些与JIT编译时间相关的开销。这会产生影响(尽管很可能没那么多)。
但是,查看代码时,您需要花费大量时间等待通过调度程序对UI进行编组的异步调用。这将对您的整体表现造成很大影响,并且放慢速度。
我建议在一个调度调用中执行所有操作,并使用Invoke而不是BeginInvoke。而不是每个项目编组一条消息,而只是封送包含foreach循环项目的单个代理。
这将明显加快。
答案 1 :(得分:0)
正如我所知,真正的问题是由最初被调用的属性对项目进行排序(甚至在调用扩展方法之前)。
该属性的格式为:
public Double ASortableProperty
{
get
{
if (mASortableProperty.HasValue)
{
return mASortableProperty.Value;
}
mASortableProperty = this.TryGetDoubleValue(...);
return (mASortableProperty.HasValue ? mASortableProperty.Value : 0);
}
}
因此,第一次通过循环时,值没有从数据库初始化,并且成本是在排序之前检索这些值。