-
Notifications
You must be signed in to change notification settings - Fork 302
Description
EPPlus usage
Commercial use (I have a commercial license)
Environment
OSX
Epplus version
8.4.1
Spreadsheet application
excel
Description
Performance regression: cell.Calculate() with FollowDependencyChain=false is ~3.5x slower in 8.4.1 vs 8.4.0
Description
ExcelRange.Calculate() with FollowDependencyChain = false is significantly slower in EPPlus 8.4.1 compared to 8.4.0. The regression is most pronounced on workbooks with cross-sheet INDEX/MATCH formulas and iterative calculation enabled (circular references).
In our production workload, real world spreadsheets went from ~1s to calculate to ~10s. We can't share those so we've reproduced an approximation of the issue here.
Reproduction
The attached standalone project programmatically builds a financial model with:
- 5 sheets (Assumptions, Revenue, Costs, CashFlow, Summary)
- Cross-sheet INDEX/MATCH lookups
- Circular references in the CashFlow sheet (interest-on-balance pattern)
- Iterative calculation enabled
- ~2,400 formula cells total
It then benchmarks calling cell.Calculate() with FollowDependencyChain = false on every formula cell, twice (simulating an iterative convergence check).
Steps
epplus-841-perf-repro.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<!-- Change to 8.4.0 vs 8.4.1 to compare -->
<PackageReference Include="EPPlus" Version="8.4.1" />
</ItemGroup>
</Project>- Copy the repro project (two files:
Program.csandepplus-841-perf-repro.csproj) - Set EPPlus version to 8.4.0 in the
.csproj:<PackageReference Include="EPPlus" Version="8.4.0" />
- Run:
dotnet run -c Release - Note the total time
- Change to 8.4.1:
<PackageReference Include="EPPlus" Version="8.4.1" />
- Run again:
dotnet run -c Release - Compare total times
Results (Apple M1 Pro)
| EPPlus Version | Total Time | Per-cell |
|---|---|---|
| 8.4.0 | ~480 ms | ~100 us |
| 8.4.1 | ~1,700 ms | ~350 us |
| Ratio | ~3.5x slower |
NOTE this repro shows 3.5x slower but our clients are experiencing closer to 10X slower on their workbooks.
Possible Cause
The 8.4.1 changelog mentions:
- "Changing cell dependencies were not taken into account when recalculating dirty cells from dynamic array formulas"
- "Cells containing formulas with the INDIRECT function are now always treated as dynamic"
These changes may have added overhead to the per-cell calculation path that is exercised heavily when calling cell.Calculate() individually with FollowDependencyChain = false. The full workbook.Calculate() path is not affected — only per-cell Calculate with FDC=false.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status