【问题标题】:Why is C# List<T> Add method very slow?为什么 C# List<T> Add 方法很慢?
【发布时间】:2020-02-19 02:22:09
【问题描述】:

我有一个 ASP.NET MVC 项目,使用 Dapper 从数据库中读取数据,我需要导出到 Excel。

Dapper 速度很快! ExecuteReader 只需 35 秒。

但是list.Add(InStock); 花了太多时间!超过 1020 秒!

你知道这是为什么吗?

public List<InStock> GetList(string stSeId, string edSeId, string stSeDay, string edSeDay, string qDate)
{
    List<InStock> list = new List<InStock>();
    InStock InStock = null;

    IDataReader reader;

    using (var conn = _connection.GetConnection())
    {
        try
        {
            conn.Open();
            //******************Only 35 seconds*****
            reader = conn.ExecuteReader(fileHelper.GetScriptFromFile("GetInStock"),
                 new { STSeId = stSeId, EDSeId = edSeId, STSeDay = stSeDay, EDSeDay = edSeDay, qDate = qDate });
            //*************************************

            //******************Over 1020 seconds**********
            while (reader.Read())
            {
                InStock = new InStock();

                InStock.ColA = reader.GetString(reader.GetOrdinal("ColA"));
                InStock.ColB = reader.GetString(reader.GetOrdinal("ColB"));
                InStock.ColC = reader.GetString(reader.GetOrdinal("ColC"));

                list.Add(InStock);
            }
            //*********************************************
            return list;
        }
        catch (Exception err)
        {
            throw err;
        }
    }
}

【问题讨论】:

  • Add前面有5条指令,你确定是Add方法耗时吗?
  • 关于你的基准假设的一件事 - 你有一个涉及数据库的操作和一个由内存数组支持的操作,并且你指向 List&lt;InStock&gt;.Add() 作为你的性能罪魁祸首。除非InStock ctor 特别密集,否则就是数据库。
  • 这个问题说实话没有意义。您要返回多少条记录?
  • 根据您的代码 cmets 和图像,听起来您实际上并不是在测量 .Add(),而是在测量所有 7351409 行的整个处理过程。此外,对conn.ExecuteReader 的调用可能不会立即加载所有结果,而是依赖reader.Read() 来执行此操作。这可以解释两者之间的差异。
  • 在调试器下不是你想首先计时你的代码,我不熟悉 Dapper 但我同意对 ExecuteReader() 的调用实际上不应该读取任何内容所以这不是一个公平的比较。你甚至需要返回一个完整的List&lt;&gt;,而不是yield return,而不是IEnumerable&lt;&gt;?顺便提一下,catch (Exception err) { throw err; } 会掩盖err 的来源;要么将其更改为 throw;,要么完全删除 catch。现在,关于那个 Comic Sans...

标签: c# .net ado.net dapper generic-list


【解决方案1】:

这是数据库。

来自Retrieve data using a DataReader,

当您检索大量数据时,DataReader 是一个不错的选择,因为数据没有缓存在内存中。

性能问题的关键线索是“因为数据没有缓存在内存中”。虽然严格来说是一个实现细节,但对 Read() 的每次调用都会从数据库中获取新数据,而 List&lt;InStock&gt;.Add() 调用只是将新的 InStock 添加到列表中。

与 RAM 相比,磁盘访问(甚至 SSD)之间的处理时间存在数量级的差异。网络请求和磁盘访问之间存在数量级的差异。没有一种真正可以想象的方式,除了数据库访问之外的任何事情都是导致大部分运行时间的原因。

--

附带说明,您将超出 Excel 工作表中的 maximum number of rows。

【讨论】:

  • 先生,我非常感谢!但是用大数据创建报告的最佳方法是什么?
  • 多年来我很幸运能够随时使用真实的报告工具。根据短代码 sn-p 你真的很难说(事实上,你只是将所有行转储到报告中)。如何制作报告真的是一个单独的问题。
猜你喜欢
  • 1970-01-01
  • 2011-05-01
  • 2013-04-24
  • 2010-10-09
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 1970-01-01
  • 2015-04-21
相关资源
最近更新 更多