Dapper/EF - 为什么当变量不在使用范围内时性能会提高

Dapper/EF - why is there a performance increase when variable is outside of using

我 运行 以下两个查询使用相同的参数和存储过程。示例 A 耗时超过一分钟,而示例 B 耗时不到 20 秒。如果我使用 EF 调用同一个过程,那么我将减少到大约 10 秒(返回的记录刚好超过 50000 条)。所以同样令人费解的是为什么 EF 更快。

示例 A:

            List<resultObj> result;

            using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["string"].ConnectionString))
            {
                    result = conn.Query<resultObj>("spProc", param: new { /*params here*/ }, 
                    commandType: CommandType.StoredProcedure, commandTimeout: 300).ToList();
            }

示例 B:

            using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["string"].ConnectionString))
            {
                var result = conn.Query<resultObj>("spProc", param: new { /*params here*/ }, 
                    commandType: CommandType.StoredProcedure, commandTimeout: 300).ToList();
            }

为什么将 result 变量移出 using 的范围会导致如此大的性能提升?

您发布的两段代码在编译时将生成几乎相同的 IL 代码。唯一的区别是使用哪些寄存器来表示哪个变量,这不会对程序的运行方式产生任何影响。

您看到的结果是此代码外部因素的结果。有很多因素会影响性能,并且无法确定是什么导致了您的问题。也许数据库 re-thought 自您第一次 运行 代码以来其索引计划。也许您更改了对数据库连接产生意外影响的其他代码。也许远程系统有一段时间负载较重。但我可以自信地说,区别不在于您在此处提供的代码更改。

没有理由这样。在这种情况下,我怀疑任何差异是由于数据库服务器瓶颈造成的——也许你第一次有效地将数据加载到内存中(速度慢,它必须访问磁盘)——或者可能是服务器争用或网络吞吐量问题。您在两个示例中描述的只能由底层数据源引起-而不是变量声明位置之间的差异。

作为一个小提示:AsList()ToList() 更可取,但这也是:只会为您节省一小部分时间(可能不到一毫秒)。

分析时,您应该:

  • 在没有附加 IDE 的发布模式下工作
  • 首先执行 JIT 并启动所有外部源,通常是在开始计时之前至少执行一次
  • 多次测量所有内容(在快速操作的情况下,执行数千次以获得平均值是很常见的 - 如果每次迭代需要 30 秒,显然不那么适用,显然)
  • 提前强制 GC 等,这样任何额外的 GC 都完全是被测试的问题
  • 尽量避免在测试机/服务器/网络上竞争