为什么当我重用 Linq 查询变量时会发生微小的性能提升
本文关键字:性能 Linq 变量 查询 为什么 | 更新日期: 2023-09-27 18:35:25
环境:
SQL CE
Windows Phone 7.5 及更高版本
Visual Studio 2012 更新 3
示例:所有任务30个,今天任务10个,明天任务10个,过期任务
10
要求:
一个待办事项应用程序,需要在首页显示3个数字,所有任务,今天任务,明天任务。
原始代码:
private Stopwatch sw=new Stopwatch();
using (TasksDataContext db = new TasksDataContext(TasksDataContext.DBConnectionString))
{
sw.Start();
var allTask = db.TasksItems.Where(t => t.Title != null && t.IsCompleted != true);
System.Diagnostics.Debug.WriteLine( "allTask:"+sw.ElapsedMilliseconds.ToString());
Taskamount = allTask.Count();
var todayTask = db.TasksItems.Where(t => t.DueDate != null & t.DueDate.Value.Date == DateTime.Now.Date & t.IsCompleted == false);
System.Diagnostics.Debug.WriteLine("todayTask:" + sw.ElapsedMilliseconds.ToString());
todayNumber = todayTask.Count();
var tomorrowTask = db.TasksItems.Where(t => t.DueDate != null & t.DueDate.Value.Date == DateTime.Now.Date.AddDays(1) & t.IsCompleted == false);
System.Diagnostics.Debug.WriteLine("tomorrowTask:" + sw.ElapsedMilliseconds.ToString());
sw.Stop();
tomorrowNumber = tomorrowTask.Count();
}
最新代码:
private Stopwatch sw=new Stopwatch();
using (TasksDataContext db = new TasksDataContext(TasksDataContext.DBConnectionString))
{
sw.Start();
var allTask = db.TasksItems.Where(t => t.Title != null && t.IsCompleted != true);
System.Diagnostics.Debug.WriteLine( "allTask:"+sw.ElapsedMilliseconds.ToString());
Taskamount = allTask.Count();
var todayTask = allTask.Where(t => t.DueDate != null & t.DueDate.Value.Date == DateTime.Now.Date & t.IsCompleted == false);
System.Diagnostics.Debug.WriteLine("todayTask:" + sw.ElapsedMilliseconds.ToString());
todayNumber = todayTask.Count();
var tomorrowTask = allTask.Where(t => t.DueDate != null & t.DueDate.Value.Date == DateTime.Now.Date.AddDays(1) & t.IsCompleted == false);
System.Diagnostics.Debug.WriteLine("tomorrowTask:" + sw.ElapsedMilliseconds.ToString());
sw.Stop();
tomorrowNumber = tomorrowTask.Count();
}
调试输出
源语言:
第一次:
全部任务:9
今天任务:165
明天任务:221
第二次:
全部任务:10
今天任务:179
明天任务:233
第三次:
全部任务:14
今天任务:168
明天任务:225
第四次:
全部任务:8
今日任务:181
明天任务:236
第五次:
全部任务:8
今天任务:166
明天任务:221
最近的:
第一次:
全部任务:9
今天任务:157
明天任务:216
第二次:
全部任务:8
今天任务:163
明天任务:219
第三次:
全部任务:8
今天任务:161
明天任务:216
第四次:
全部任务:8
今天任务:164
明天任务:222
第五次:
全部任务:9
今天任务:153
明天任务:210
为什么我修改代码:
由于今天任务和明天任务是所有任务的子集。我认为重用 linq 查询变量将提高性能。结果显示出微小的提升。
是什么让我感到困惑:
我读了MSDN中的linq部分,它说:
在 LINQ 中,查询的执行与查询本身不同; 换句话说,您没有通过创建 查询变量。
这让我想到了一个问题:为什么它会快一点?根据MSDN的说法:linq查询的重用不会提高性能,但会损害性能。
当编译器运行以下代码时:
var todayTask = allTask.Where(t => t.DueDate != null & t.DueDate.Value.Date == DateTime.Now.Date & t.IsCompleted == false);
它将执行 2 个操作,一个用于所有任务,一个用于 todayTask。但是当使用"db.taskitems.Where()"时,它只执行一次操作。
我的问题
1. 为什么它更快?(编译器是否在编译时优化了我的代码?
2.有没有更好的方法来提高速度?
速度可能是由于查询(t => t.Title != null
)中的额外条件allTask
而发生的。这不包括在todayTask
和tomorrowTask
中。
为了加快速度,您可以尝试将Count
与谓词一起使用并删除冗余条件:
var allTask = [...];
Taskamount = allTask.Count();
todayNumber = allTask.Count(t => t.DueDate != null && t.DueDate.Value.Date == DateTime.Now.Date);
tomorrowNumber = allTask.Count(t => t.DueDate != null && t.DueDate.Value.Date == DateTime.Now.Date.AddDays(1));
您也可以尝试GroupBy
:
var result = allTask.GroupBy(x => 1, x => x, (key, g) => new
{
All = g.Count(),
Today = g.Count(t => t.DueDate != null && t.DueDate.Value.Date == DateTime.Now.Date),
Tomorrow = g.Count(t => t.DueDate != null && t.DueDate.Value.Date == DateTime.Now.Date.AddDays(1))
}).Single();
这应该对所有聚合执行一个查询,但我不知道所有 linq 驱动程序是否都支持它。