NPOI 導出 excel 性能測試

来源:https://www.cnblogs.com/weihanli/archive/2019/11/08/npoi-export-perf-test.html
-Advertisement-
Play Games

網上看到很多人說 NPOI 的性能不行,自己寫了一個 NPOI 的擴展庫,於是想嘗試看看 NPOI 的性能究竟怎麼樣,道聽途說始終不如自己動手一試。 ...


NPOI 導出 excel 性能測試

Intro

網上看到很多人說 NPOI 的性能不行,自己寫了一個 NPOI 的擴展庫,於是想嘗試看看 NPOI 的性能究竟怎麼樣,道聽途說始終不如自己動手一試。

測試環境

測試工具:

  • BenchmarkDotNet v0.11.5
  • EPPlus.Core.Extensions v2.3.2
  • EPPlus v4.5.3.1
  • NPOI 2.4.1

測試代碼:(Github 源碼

[SimpleJob(launchCount: 1, warmupCount: 1, targetCount: 5)]
[MemoryDiagnoser]
[MinColumn, MaxColumn, MeanColumn, MedianColumn]
public class WorkbookBasicTest
{
    private const int ColsCount = 10;

    [Params(10000, 30000, 50000, 65535)]
    public int RowsCount;

    [Benchmark(Baseline = true)]
    public byte[] NpoiXlsWorkbookInit()
    {
        var workbook = ExcelHelper.PrepareWorkbook(ExcelFormat.Xls);

        var sheet = workbook.CreateSheet("tempSheet");

        for (var i = 0; i < RowsCount; i++)
        {
            var row = sheet.CreateRow(i);
            for (var j = 0; j < ColsCount; j++)
            {
                var cell = row.CreateCell(j);
                cell.SetCellValue($"as ({i}, {j}) sa");
            }
        }

        return workbook.ToExcelBytes();
    }

    [Benchmark]
    [MethodImpl(MethodImplOptions.NoInlining)]
    public byte[] NpoiXlsxWorkbookInit()
    {
        var workbook = ExcelHelper.PrepareWorkbook(ExcelFormat.Xlsx);

        var sheet = workbook.CreateSheet("tempSheet");

        for (var i = 0; i < RowsCount; i++)
        {
            var row = sheet.CreateRow(i);
            for (var j = 0; j < ColsCount; j++)
            {
                var cell = row.CreateCell(j);
                cell.SetCellValue($"as ({i}, {j}) sa");
            }
        }

        return workbook.ToExcelBytes();
    }

    [Benchmark]
    [MethodImpl(MethodImplOptions.NoInlining)]
    public byte[] EpplusWorkbookInit()
    {
        var excel = new ExcelPackage();

        var sheet = excel.Workbook.Worksheets.Add("tempSheet");

        for (var i = 1; i <= RowsCount; i++)
        {
            for (var j = 1; j <= ColsCount; j++)
            {
                sheet.Cells[i, j].Value = $"as ({i}, {j}) sa";
            }
        }

        return excel.GetAsByteArray();
    }
}

測試結果

在 Github 上查看結果 https://github.com/WeihanLi/WeihanLi.Npoi/blob/dev/perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.WorkbookBasicTest-report-github.md


BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i5-3470 CPU 3.20GHz (Ivy Bridge), 1 CPU, 4 logical and 4 physical cores
.NET Core SDK=3.0.100
  [Host]     : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
  Job-CBYTBY : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT

IterationCount=5  LaunchCount=1  WarmupCount=1  
Method RowsCount Mean Error StdDev Min Max Median Ratio RatioSD Gen 0 Gen 1 Gen 2 Allocated
NpoiXlsWorkbookInit 10000 324.7 ms 1.583 ms 0.4110 ms 324.3 ms 325.4 ms 324.6 ms 1.00 0.00 10000.0000 5000.0000 2000.0000 78.6 MB
NpoiXlsxWorkbookInit 10000 1,369.0 ms 73.747 ms 19.1517 ms 1,341.3 ms 1,384.4 ms 1,381.1 ms 4.22 0.06 57000.0000 14000.0000 4000.0000 306.45 MB
EpplusWorkbookInit 10000 552.9 ms 12.740 ms 3.3085 ms 549.7 ms 557.7 ms 552.4 ms 1.70 0.01 18000.0000 7000.0000 3000.0000 121.05 MB
NpoiXlsWorkbookInit 30000 1,222.4 ms 33.717 ms 8.7562 ms 1,209.0 ms 1,233.1 ms 1,222.5 ms 1.00 0.00 29000.0000 11000.0000 3000.0000 235.03 MB
NpoiXlsxWorkbookInit 30000 4,226.2 ms 299.833 ms 77.8658 ms 4,109.5 ms 4,308.6 ms 4,257.2 ms 3.46 0.08 174000.0000 34000.0000 6000.0000 913.9 MB
EpplusWorkbookInit 30000 1,695.4 ms 31.751 ms 8.2457 ms 1,686.3 ms 1,706.5 ms 1,694.2 ms 1.39 0.02 48000.0000 17000.0000 5000.0000 358.51 MB
NpoiXlsWorkbookInit 50000 2,323.5 ms 236.041 ms 61.2990 ms 2,286.0 ms 2,431.9 ms 2,294.2 ms 1.00 0.00 47000.0000 18000.0000 4000.0000 417.1 MB
NpoiXlsxWorkbookInit 50000 7,055.2 ms 279.256 ms 72.5218 ms 6,982.8 ms 7,150.2 ms 7,027.2 ms 3.04 0.10 288000.0000 51000.0000 6000.0000 1545.32 MB
EpplusWorkbookInit 50000 2,806.9 ms 56.266 ms 14.6121 ms 2,792.9 ms 2,829.1 ms 2,804.6 ms 1.21 0.03 79000.0000 27000.0000 7000.0000 578.46 MB
NpoiXlsWorkbookInit 65535 3,646.8 ms 131.129 ms 34.0537 ms 3,603.0 ms 3,696.3 ms 3,642.5 ms 1.00 0.00 61000.0000 21000.0000 4000.0000 504.46 MB
NpoiXlsxWorkbookInit 65535 9,295.6 ms 486.761 ms 126.4104 ms 9,163.3 ms 9,468.6 ms 9,330.5 ms 2.55 0.04 390000.0000 67000.0000 8000.0000 2048.14 MB
EpplusWorkbookInit 65535 3,721.6 ms 124.945 ms 32.4478 ms 3,680.7 ms 3,766.8 ms 3,714.1 ms 1.02 0.01 102000.0000 35000.0000 8000.0000 747.85 MB

從上面的測試結果來看,npoi 導出 xls 的性能還是相當好的,無論是所用時間還是記憶體都占優勢,只是 xls 一個 sheet 最多 65535 行數據,所以測試數據最多只有 65535,其次就是 epplus 導出 xlsx,最次是 npoi 導出 xlsx 了。

測試結論

如果使用 NPOI 導出建議導出 xls,如果要導出數據較多,可以導出 csv ,如果看了另外一個 csv 導出的測試,csv 導出性能要比 excel 好很多,如果實在是要導出 excel,導入 xls 的話就分多個 sheet 處理,如果一定要導出 xlsx 格式的 excel ,推薦用 epplus 來處理,相比 npoi 導出 xlsx 性能更好,記憶體占用更少

Reference


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Python實戰教程,用Python做列印日曆的小程式,使用者可以通過輸入年月信息,程式將會輸出這個月的日曆 ...
  • 首先來總結一下,ArrayList的一些特點: 1.arraylist本質上就是一個elementData數組,它允許對元素進行快速隨機訪問,可以存放null值; 2.arraylist區別於數組的地方在於能夠自動擴展大小,其中關鍵就是grow() 方法,每次擴充後數組為原來數組的1.5倍; 3.a ...
  • 前言 array,顧名思義,數組,就是存儲數字、處理數字的一種數據結構。今天在將list轉換為array時,遇到了一個問題,數據量比較大,剛開始怎麼都不知道問題出在哪裡。直到我用一個3 3的小數據測試時,才發現問題的本質所在。浪費了半天的時間,不過總算搞明白了。 學的不夠踏實,以此警戒所有的初學者: ...
  • Python 3最重要的新特性之一是對字元串和二進位數據流做了明確的區分。文本總是Unicode,由str類型表示,二進位數據則由bytes類型表示。Python 3不會以任意隱式的方式混用str和bytes,你不能拼接字元串和位元組流,也無法在位元組流里搜索字元串(反之亦然),也不能將字元串傳入參數為 ...
  • Python編寫類的時候,每個函數參數第一個參數都是self,一開始我不管它到底是幹嘛的,只知道必須要寫上。後來對Python漸漸熟悉了一點,再回頭看self的概念,似乎有點弄明白了。 首先明確的是self只有在類的方法中才會有,獨立的函數或方法是不必帶有self的。self在定義類的方法時是必須有 ...
  • php中有很多排序的函數,sort,rsort,ksort,krsort,asort,arsort,natcasesort,這些函數用來對數組的鍵或值進行這樣,或那樣的排序。 可以終究有時候還需要一些函數來隨機獲取數組的元素。 array_rand()函數 隨機獲取數組中的一個函數,可以通過第二個參 ...
  • 前言 最近在做智能家居平臺,考慮到家居的控制需要快速的響應於是打算使用redis緩存。一方面減少資料庫壓力另一方面又能提高響應速度。項目中使用的技術棧基本上都是大家熟悉的springboot全家桶,在springboot2.x以後操作redis的客戶端推薦使用lettuce(生菜)取代jedis。 ...
  • 2019年11月8日,近期做項目開始實行前後端分離的方式開發,前端使用vue的框架,打包發佈後,調用後端介面出現跨域的問題,網上搜索出來的都是以下的配置方式: 但是,在我的項目中,按這種方式配置沒有效果,還會出現跨域的問題,後來發現是前後端請求設置的在Headers裡面傳輸token來進行校驗,那麼 ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...