Skip to main content Skip to footer

NPOI Alternative Spreadsheet API Performance Test in C# .NET

Document Solutions for Excel (DsExcel), previously GrapeCity Documents for Excel (GcExcel), is a fast, high-performance spreadsheet API that requires no dependencies on Excel. With full .NET 6 support, you can generate, load, modify, and convert Excel .xlsx spreadsheets in a .NET Framework, .NET Core, Mono, and Xamarin.

We have continually been monitoring the performance of DsExcel with every release. We recorded the performance time and memory consumed for load, save, and calculation operations of DsExcel in comparison with other competitors on Windows, macOS, and Linux platforms. From our rigorous performance tests, we are confident DsExcel will be an excellent replacement for those looking for an alternative to NPOI or similar other APIs to enhance their current applications' performance.

Performance Metrics and Data

Test Machine Configurations

  • Windows: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz 3.19 GHz, x64-based processor, Windows 10 Pro 20H2 Build 19042.1052
  • MacOS: Intel i9 @ 2.3 GHz / MacOS Catalina v10.15.6
  • Linux: CPU: 4 core Intel(R) Xeon(R) CPU E5-2683 v3 @ 2.00GHz, 4GB

Builds Used for Comparison

This comparison references the following build version of DsExcel and competitor:

Test Data

The first three tests populate 100,000 rows x 30 columns (3,000,000 cells) with type double, string, and date values, measuring the performance for Set ValuesGet Values, and Save to XLSX. The total Memory Used (which is difficult to measure accurately since garbage collection can happen at any time).

These tests look like this (the string test uses the hard-coded string value "ABCDEFGHIJKLMNOPQRSTUVWXYZ" and the date test creates a new Date() object but are otherwise the same):

 

GcExcel Double Performance Test

public static void TestSetRangeValues_Double(int rowCount, int columnCount, ref double setTime, ref double getTime, ref double saveTime, ref double usedMem)
{
 
            Console.WriteLine();    
            Console.WriteLine(string.Format("GcExcel benchmark for double values with {0} rows and {1} columns", rowCount, columnCount));
 
            IWorkbook workbook = new Workbook();
            IWorksheet worksheet = workbook.Worksheets[0];
 
            Stopwatch watch = new Stopwatch();
            watch.Start();
 
            double[,] values = new double[rowCount, columnCount];
 
            for (int i = 0; i < rowCount; i++)
            {
                for (int j = 0; j < columnCount; j++)
                {
                    values[i, j] = i + j;
                }
            }
 
            worksheet.Range[0, 0, rowCount, columnCount].Value = values;
            watch.Stop();
 
            setTime = watch.ElapsedMilliseconds / 1000d;
            Console.WriteLine(string.Format("GcExcel set double values: {0:N3} s", setTime));
 
            watch.Start();
            object tmpValues = worksheet.Range[0, 0, rowCount, columnCount].Value;
            watch.Stop();
 
            getTime = watch.ElapsedMilliseconds / 1000d; ;
            Console.WriteLine(string.Format("GcExcel get double values: {0:N3} s", getTime));
 
            watch.Start();
            workbook.Save("../../output/gcexcel-saved-doubles.xlsx");
            watch.Stop();
            saveTime = watch.ElapsedMilliseconds / 1000d; ;
            Console.WriteLine(string.Format("GcExcel save doubles to Excel: {0:N3} s", saveTime)); }

The last two tests focus more on calculation performance.

In the following test, the workbook loads a large XLSX, which contains many formulas using volatile functions that require recalculation each time the worksheet is calculated and measures the performance for Open FileCalculateSave to XLSX, and the total Memory Used.

This test looks like this:

DsExcel Open Large XLSX Performance Test

public static void TestBigExcelFile(int rowCount, int columnCount, ref double openTime, ref double calcTime, ref double saveTime, ref double usedMem)
{
 
            Console.WriteLine();    
               Console.WriteLine(string.Format("GcExcel benchmark for test-performance.xlsx which is 20.5MB with a lot of values, formulas and styles"));
 
            IWorkbook workbook = new Workbook();
 
            Stopwatch watch = new Stopwatch();
            watch.Start();
            workbook.Open("../../files/test-performance.xlsx");
            watch.Stop();
 
            openTime = watch.ElapsedMilliseconds / 1000d; ;
            Console.WriteLine(string.Format("GcExcel open big Excel: {0:N3} s", openTime));
 
            watch.Start();
            workbook.Dirty();
            workbook.Calculate();
            watch.Stop();
 
            calcTime = watch.ElapsedMilliseconds / 1000d; ;
            Console.WriteLine(string.Format("GcExcel calculate formulas for big Excel: {0:N3} s", calcTime));
 
            watch.Start();
            workbook.Save("../../output/gcexcel-saved-test-performance.xlsx");
            watch.Stop();
            saveTime = watch.ElapsedMilliseconds / 1000d; ;
            Console.WriteLine(string.Format("GcExcel save back to big Excel: {0:N3} s", saveTime));
}

The following test populates 100,000 rows x 2 columns of double values, then sets formulas to a range of 100,000 rows x 30 columns adjacent to and referencing those double values in the first 2 columns, measuring the performance for Set FormulasCalculateSave to XLSX, and the total Memory Used.

This test looks like this:

DsExcel Formulas Performance Test

public static void TestSetRangeFormulas(int rowCount, int columnCount, ref double setTime, ref double calcTime, ref double saveTime, ref double usedMem)
{             
            Console.WriteLine();
            Console.WriteLine(string.Format("GcExcel benchmark for double values with {0} rows and {1} columns", rowCount, columnCount));
 
            IWorkbook workbook = new Workbook();
            workbook.ReferenceStyle = ReferenceStyle.R1C1;
            IWorksheet worksheet = workbook.Worksheets[0];
 
            double[,] values = new double[rowCount, 2];
 
            for (int i = 0; i < rowCount; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    values[i, j] = i + j;
                }
            }
            worksheet.Range[0, 0, rowCount, 2].Value = values;
 
            Stopwatch watch = new Stopwatch();
            watch.Start();
            worksheet.Range[0, 2, rowCount - 2, columnCount].Formula = "=SUM(RC[-2],RC[-1])";
            watch.Stop();
 
            setTime = watch.ElapsedMilliseconds / 1000d; ;
            Console.WriteLine(string.Format("GcExcel set formulas: {0:N3} s", setTime));
 
            watch.Start();
            workbook.Calculate();
            watch.Stop();
 
            calcTime = watch.ElapsedMilliseconds / 1000d; ;
            Console.WriteLine(string.Format("GcExcel calculates formula: {0:N3} s", calcTime));
 
            workbook.ReferenceStyle = ReferenceStyle.A1;
 
            watch.Start();
            workbook.Save("../../output/gcexcel-saved-formulas.xlsx");
            watch.Stop();
            saveTime = watch.ElapsedMilliseconds / 1000d; ;
            Console.WriteLine(string.Format("GcExcel save formulas to Excel: {0:N3} s", saveTime));
}

Performance Results

Following are the PerformanceTestResults.xlsx:

DsExcel performs better than other competitors in various operations on loading, modifying, and saving the Excel file. Have a look at the numbers below.

Results

Note: The results were taken on particular machine configurations. If you are running at a different configuration, the values may not match our collected results exactly. If you observe any discrepancies in the overall performance, please leave your comments below.

Also, check out the Performance Comparison of older builds and Feature comparison with NPOI.

 

comments powered by Disqus