调试时Epplus Save()、SaveAs()等方法运行非常慢

Very slow operation of Epplus Save(), SaveAs(), etc. methods when debugging

环境 - Windows 10,Visual Studio 2017,netcore2.0,调试版本。

在调试时使用 Epplus 4.1.1 保存 Excel 文件时,保存操作花费的时间比我预期的要长得多。

这是 运行 使用调试 -> 开始调试的一些时间

Saving 100 rows in 2065ms.
Saving 200 rows in 2050ms.
Saving 400 rows in 4003ms.
Saving 800 rows in 11360ms.
Saving 1600 rows in 18377ms.
Saving 3200 rows in 34139ms.

当 运行 使用调试 -> 不调试启动时也是如此

Saving 100 rows in 401ms.
Saving 200 rows in 49ms.
Saving 400 rows in 28ms.
Saving 800 rows in 58ms.
Saving 1600 rows in 94ms.
Saving 3200 rows in 198ms.

针对 .NET Framework 4.6.1 时,调试结果要好得多 -

Saving 100 rows in 215ms.
Saving 200 rows in 26ms.
Saving 400 rows in 42ms.
Saving 800 rows in 78ms.
Saving 1600 rows in 146ms.
Saving 3200 rows in 279ms.

我显然知道调试是糖蜜慢,但这是一个微不足道的数据量。在针对 .NET Core 2.0 进行调试时,我可以做些什么来加快速度?

--

这是产生上述输出的程序 -

namespace ConsoleApp9
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Linq;
    using System.Diagnostics;

    using OfficeOpenXml;

    public class Foo
    {
        public string Name { get; set; }
        public int Number { get; set; }
        public char? Character { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

            IEnumerable<Foo> RandomFoo()
            {
                var random = new Random();
                const string chars = "ABCDEFGHIJKLH";
                while (true)
                {
                    yield return new Foo
                    {
                        Character = random.NextDouble() < .1 ? null : (char?) 'A',
                        Number = random.Next(0, 10),
                        Name = new string(Enumerable.Repeat(chars, 8)
                            .Select(x => x[random.Next(x.Length)])
                            .ToArray()
                        )
                    };
                }
            }

            for (var i = 100; i <= 1000000; i *= 2)
            {
                var sw = Stopwatch.StartNew();

                var stream = new MemoryStream();
                using (var package = new ExcelPackage(stream))
                {
                    var sheet = package.Workbook.Worksheets.Add("Sheet");
                    var foos = RandomFoo().Take(i);
                    sheet.Cells["A1"].LoadFromCollection(foos);

                    package.Save(); // very long operation here
                    stream.Seek(0, SeekOrigin.Begin);
                }

                var file = new FileInfo("test.xlsx");
                using (var fileStream = file.Create())
                {
                    stream.CopyTo(fileStream);
                }

                Console.WriteLine($"Saving {i} rows in {sw.ElapsedMilliseconds}ms.");
            }
        }
    }
}

EPPLUS v4.4.1 不完全兼容 .net core 2,我得到的数字仍然与你的不同(逻辑上的)。

Saving 100 rows in 360ms.
Saving 200 rows in 23ms.
Saving 400 rows in 48ms.
Saving 800 rows in 84ms.
Saving 1600 rows in 183ms.
Saving 3200 rows in 317ms.
Saving 6400 rows in 592ms.
Saving 12800 rows in 1157ms.
Saving 25600 rows in 2352ms.
Saving 51200 rows in 4848ms.
Saving 102400 rows in 9613ms.
Saving 204800 rows in 18917ms.

我建议你使用.net core 2 compatible pre-release 环境

这是我在 Windows 10,Visual Studio 2017,netcore2.0,调试版本中使用 EPPLUS v4.5.0.1-beta 获得的数字。

Saving 100 rows in 585ms.
Saving 200 rows in 114ms.
Saving 400 rows in 125ms.
Saving 800 rows in 159ms.
Saving 1600 rows in 233ms.
Saving 3200 rows in 360ms.
Saving 6400 rows in 655ms.
Saving 12800 rows in 1251ms.
Saving 25600 rows in 2422ms.
Saving 51200 rows in 4840ms.
Saving 102400 rows in 9789ms.
Saving 204800 rows in 19094ms.
Saving 409600 rows in 38093ms.

我遇到了同样的问题,那是因为我在单元格中存储了字符值: worksheet.Cells[i,j].值='A'; 它正在工作,但是在保存它时会产生一个转换强制转换异常,这会大大降低 VS 调试器的速度。 只需存储一个字符串! worksheet.Cells[i,j].值 = "A";