不过仔细看测试2.1的测试代码,发现循环体内包含了创建 DbContext 的代码,我在想会不会是因为多次创建 DbContext 而导致 EF 如此慢?如果把创建 DbContext 的代码放到循环体外 EF 会不会更好点?于是就有了测试2.2。
测试2.2:
LoopQueryTestWithNotCreateDbContext { static int takeCount = 1; static int queryCount = 20000; GCMemoryTest() { /* * 内存分配测试通过 vs 自带诊断与分析工具测,vs --> 分析 --> 性能与诊断 --> 内存使用率。 * 每次运行程序只能调用下面中的一个方法,不能同时调用 */ EFSqlQueryTest(takeCount, queryCount); } SpeedTest() { long useTime = 0; //预热 ChloeQueryTest(1, 1); useTime = SW.Do(() => { ChloeQueryTest(takeCount, queryCount); }); Console.WriteLine("ChloeQueryTest 执行{0}次查询总用时:{1}ms", queryCount, useTime); GC.Collect(); useTime = SW.Do(() => { ChloeSqlQueryTest(takeCount, queryCount); }); Console.WriteLine("ChloeSqlQueryTest 执行{0}次查询总用时:{1}ms", queryCount, useTime); GC.Collect(); //预热 DapperQueryTest(1, 1); useTime = SW.Do(() => { DapperQueryTest(takeCount, queryCount); }); Console.WriteLine("DapperQueryTest 执行{0}次查询总用时:{1}ms", queryCount, useTime); GC.Collect(); //预热 EFLinqQueryTest(1, 1); useTime = SW.Do(() => { EFLinqQueryTest(takeCount, queryCount); }); Console.WriteLine("EFLinqQueryTest 执行{0}次查询总用时:{1}ms", queryCount, useTime); GC.Collect(); //预热 EFSqlQueryTest(1, 1); useTime = SW.Do(() => { EFSqlQueryTest(takeCount, queryCount); }); Console.WriteLine("EFSqlQueryTest 执行{0}次查询总用时:{1}ms", queryCount, useTime); GC.Collect(); Console.WriteLine("GAME OVER"); Console.ReadKey(); } static void ChloeQueryTest(int takeCount, int loops) { using (MsSqlContext context = new MsSqlContext(DbHelper.ConnectionString)) { for (int i = 0; i < loops; i++) { int id = 0; var list = context.Query<TestEntity>().Where(a => a.Id > id).Take(takeCount).ToList(); } } } static void ChloeSqlQueryTest(int takeCount, int loops) { using (MsSqlContext context = new MsSqlContext(DbHelper.ConnectionString)) { for (int i = 0; i < loops; i++) { int id = 0; var list = context.SqlQuery<TestEntity>(string.Format("select top {0} * from TestEntity where Id>@Id", takeCount.ToString()), DbParam.Create("@Id", id)).ToList(); } } } static void DapperQueryTest(int takeCount, int loops) { using (IDbConnection conn = DbHelper.CreateConnection()) { for (int i = 0; i < loops; i++) { int id = 0; var list = conn.Query<TestEntity>(string.Format("select top {0} * from TestEntity where Id>@Id", takeCount.ToString()), new { Id = id }).ToList(); } } } static void EFLinqQueryTest(int takeCount, int loops) { using (EFContext efContext = new EFContext()) { for (int i = 0; i < loops; i++) { int id = 0; var list = efContext.TestEntity.AsNoTracking().Where(a => a.Id > id).Take(takeCount).ToList(); } } } static void EFSqlQueryTest(int takeCount, int loops) { using (EFContext efContext = new EFContext()) { for (int i = 0; i < loops; i++) { int id = 0; var list = efContext.Database.SqlQuery<TestEntity>(string.Format("select top {0} * from TestEntity where Id>@Id", takeCount.ToString()), new SqlParameter("@Id", id)).ToList(); } } } }
View Code运行5次,得到以下结果:
ChloeQueryTest(ms)
ChloeSqlQueryTest(ms)
DapperQueryTest(ms)
EFLinqQueryTest(ms)
EFSqlQueryTest(ms)
第1轮
15281
11858
11981
31394
19309
第2轮
15194
12177
12314
31464
18161
第3轮
15967
12348
12366
31082
18030
第4轮
15371
11793
12479
32314
18356
第5轮
15350
11921
11937
35023
18356
平均
15411
12019
12215
32255
18442
GC 情况:
ChloeQueryTest
ChloeSqlQueryTest
DapperQueryTest
EFLinqQueryTest
EFSqlQueryTest
GC回收次数
111
41
47
368
205