Skip to content

Implementing C++ and Rust wrappers packages for native bindings with parsing and reading - #85

Merged
GabrielMarquezMatte merged 58 commits into
masterfrom
develop
Aug 20, 2026
Merged

Implementing C++ and Rust wrappers packages for native bindings with parsing and reading#85
GabrielMarquezMatte merged 58 commits into
masterfrom
develop

Conversation

@GabrielMarquezMatte

Copy link
Copy Markdown
Owner

No description provided.

GabrielMarquezMatte and others added 30 commits August 17, 2026 17:59
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The checked-in excelreader-phase1.def has no LIBRARY statement, so lib.exe
and dlltool had no way to know what DLL name to record in the generated
import lib's import descriptors. lib.exe fell back to the .def's own
basename (excelreader-phase1.dll, which never exists); dlltool was told a
fixed release-asset name via -D that doesn't match a locally-built
EXCELREADER_NATIVE_LIB override.

Generate a temporary .def with an explicit LIBRARY line naming the actual
basename of the file at _lib_path (download or override alike), and feed
that to both lib.exe /def: and dlltool -d, dropping dlltool's now-redundant
-D flag.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The C++ package's include/ symlinked straight to
src/ExcelReader.Native/include, so headers landed at the top level
(include/excelreader.hpp) instead of under an xl/ prefix - but both the
package README and every consumer (per the wrapper's own doc comments)
use #include <xl/excelreader.hpp>. Re-point the symlink one level
deeper (include/xl -> ../../src/ExcelReader.Native/include) so that
path actually resolves, and update FetchNativeLib.cmake's reference to
the phase-1 .def file to match.

Also add xl_open_file to excelreader-phase1.def: xl::Workbook::open
calls xl_open_file (not just the _ex variant), but the DLL only
exported the _ex symbol via the def, so the C++ smoke test failed to
link with 'undefined reference to xl_open_file'.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Exercises xl::Workbook::open and xl::parse_sheet<Row> end to end
against the RealExcel.xlsb fixture at the repo root, asserting the
same known-stable values tests/ExcelReader.NativeSmoke/smoke.c already
checks: 100 data rows, first row's Coluna1 == "Valor1" and
Coluna3 == 1.

Verified locally:
  dotnet publish src/ExcelReader.Native -c Release -r win-x64 -f net10.0
  cmake -S cpp -B build/cpp -G "MinGW Makefiles" -DEXCELREADER_BUILD_TESTS=ON
    (EXCELREADER_NATIVE_LIB pointing at the published DLL)
  cmake --build build/cpp --config Release
  ctest --test-dir build/cpp --output-on-failure -C Release
    -> 1/1 Test #1: excelreader_cpp_smoke ... Passed, prints
       'OK: C++ smoke test passed'

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…import lib

Applies the fix Task 4 discovered for the equivalent CMake problem: the
shared excelreader-phase1.def has no LIBRARY statement, so lib.exe/dlltool
would otherwise bake the wrong DLL name (the .def's own basename) into the
generated import lib. build.rs now writes a temporary copy of the .def with
an explicit LIBRARY line naming the real DLL - discovered by scanning
EXCELREADER_NATIVE_LIB_DIR for its one *.dll when that override is set,
since it may not be named like the downloaded release asset.

Also works around a dlltool quirk found while verifying under MinGW: it
mangles the -l output path into a temporary file name and fails to open it
when that path is a long absolute path (a real Cargo OUT_DIR nested several
directories deep). Runs dlltool with OUT_DIR as its working directory and a
bare relative -l filename instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
cargo:rustc-link-lib=dylib=excelreader_native was unconditional, so on
macOS/Linux it always searched for libexcelreader_native.{so,dylib} - a name
that never matches the real file (excelreader-native-<os>-<arch>.<ext> on the
download path, or whatever find_native_lib discovers on the
EXCELREADER_NATIVE_LIB_DIR override path). Same 'wrong name baked in' bug
class as the Windows .def fix, just missing the platform gate.

Windows keeps the fixed-name link (correct: the generated import library is
always named excelreader_native.lib regardless of the real DLL's name).
macOS/Linux now link via dylib:+verbatim=<real filename> instead, since there
is no import-library indirection to hide the real name behind on those
platforms.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Verified a real compile succeeds now that workbook.rs fills in the
previously-declared-but-missing module: dotnet publish
src/ExcelReader.Native -c Release -r win-x64 -f net10.0, then
EXCELREADER_NATIVE_LIB_DIR=<publish dir with only the .dll>
cargo build --target x86_64-pc-windows-gnu from rust/excelreader.
Clean build (cargo clean first) succeeds with zero warnings.

Also adds rust/.gitignore for target/ and Cargo.lock, generated by
this verification build and previously untracked.
Also fixes build.rs: on windows it never added OUT_DIR (where the
generated excelreader_native.lib import library lives) to the linker
search path, only the DLL's own directory. cargo build hid this bug
because an rlib doesn't need real link-time symbol resolution; any
actual link step (cargo test) failed with an unhelpful, output-free
ld exit status 1.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…e Rust crate

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…Lib.cmake

cpp.yml's 'Locate published native library' step set a path relative to
github.workspace, unlike rust.yml's equivalent step. CMake's EXISTS check
on a relative path resolves against the process cwd (passes at configure
time), but the relative string is then baked verbatim into
IMPORTED_LOCATION/IMPORTED_IMPLIB and later resolved against the build
directory instead - breaking the link step on Linux/macOS and the test
binary's POST_BUILD DLL-copy step on Windows.

Prefix each matrix leg's output path with ${{ github.workspace }},
matching rust.yml. As defense in depth, also absolutize
EXCELREADER_NATIVE_LIB in FetchNativeLib.cmake right after it is read,
so any caller passing a relative path (e.g. the common cd-build-dir &&
cmake .. invocation style) gets a stable absolute path baked in.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The publish-rust job seds rust/excelreader/Cargo.toml's version in a git
checkout, then ran bare 'cargo publish', which refuses to publish with
uncommitted changes. --allow-dirty is the documented flag for exactly
this situation (verified via 'cargo publish --help').

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…f reading it from outside the crate

build.rs read ../../src/ExcelReader.Native/include/excelreader-phase1.def
via a CARGO_MANIFEST_DIR-relative path outside the crate directory.
'cargo package --list' confirms this path is not included in what gets
published, so a Windows user building the crate from crates.io hit a
build.rs panic ('failed to read ... excelreader-phase1.def').

include_str! resolves against build.rs's own source location, not
CARGO_MANIFEST_DIR at runtime - but since build.rs's SOURCE (not a
precompiled binary) ships in the package, cargo recompiles it, re-running
the include_str! at the consumer's build time too. An include_str! of a
path outside the crate directory therefore fails there exactly like the
fs::read_to_string it replaces would.

The fix is to keep a copy of the .def file inside the crate
(rust/excelreader/excelreader-phase1.def, added in a prior commit,
kept in sync with the canonical copy at
src/ExcelReader.Native/include/excelreader-phase1.def) and embed *that*
via include_str!. Verified: 'cargo package --list' now lists the .def
file; cargo build succeeds for both x86_64-pc-windows-gnu and
x86_64-pc-windows-msvc against a locally-built native lib; and the build
still succeeds with the external repo-root .def file renamed aside,
proving the packaged crate no longer depends on it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ers and cpp/README.md inaccuracies

I7: root README's 'Other languages' section never mentioned the new
cpp/ and rust/excelreader/ packages - add brief pointers matching the
existing Python entry's style.

M1: cpp/README.md's FetchContent example and rust/excelreader/README.md's
Cargo.toml example showed placeholder versions (v0.1.0 / "0.1") that
will never exist. Both packages version in lockstep with the main
release tag (latest v2.1.2), so update to v2.1.3 / "2.1" - the next
patch version these packages could actually ship in.

M2: cpp/README.md said 'this package's include/ is a symlink' - only
include/xl is the symlink (verified via ls -la); include/ itself is a
real directory. Also documented the previously-undocumented
EXCELREADER_NATIVE_LIB (env var, local binary override) and
EXCELREADER_VERSION (CMake cache var, release tag override, falls back
to v0.0.0 off-tag) variables, and corrected the opening prose's native
function name from xl_open_file_ex to xl_open_file (verified against
Workbook::open in excelreader.hpp).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…out .stderr) - error paths stay covered by unit tests
@codecov-commenter

codecov-commenter commented Aug 18, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 73.68421% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.56%. Comparing base (13df5e1) to head (fdad393).

Files with missing lines Patch % Lines
src/ExcelReader.Native/Exports.cs 0.00% 11 Missing ⚠️
src/ExcelReader.Native/NativeApi.Typed.cs 83.33% 0 Missing and 3 partials ⚠️
src/ExcelReader.Native/NativeApi.Arrow.cs 0.00% 0 Missing and 1 partial ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@            Coverage Diff             @@
##           master      #85      +/-   ##
==========================================
- Coverage   86.57%   86.56%   -0.02%     
==========================================
  Files         128      129       +1     
  Lines        9500     9533      +33     
  Branches     1781     1789       +8     
==========================================
+ Hits         8225     8252      +27     
- Misses        952      958       +6     
  Partials      323      323              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown

Benchmark Results

Measured on ubuntu-latest (GitHub Actions). Runner noise may affect absolute numbers; use these for relative comparisons within a PR.

ExcelReader.Benchmarks.ColdStartBenchmark


BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.70GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
  [Host]     : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v3
  Job-GOEFXF : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v3

InvocationCount=1  IterationCount=1  LaunchCount=16  
RunStrategy=ColdStart  UnrollFactor=1  WarmupCount=0  

Method Rows Mean Error StdDev Allocated
TypedParseFirstUse 200 39.72 ms 0.847 ms 0.831 ms 28.38 KB
RecordWriteFirstUse 200 28.04 ms 1.684 ms 1.654 ms 84.27 KB
FluentParseFirstUse 200 36.99 ms 0.717 ms 0.704 ms 30.75 KB
FluentParseWithAttributeFallbackFirstUse 200 43.64 ms 0.707 ms 0.694 ms 32.45 KB

ExcelReader.Benchmarks.CsvParseBenchmark


BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Intel Xeon 6973P-C 2.60GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
  [Host]     : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4
  Job-MEHJPP : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4

IterationCount=5  WarmupCount=1  

Method Rows Mean Error StdDev Ratio Gen0 Gen1 Allocated Alloc Ratio
ExcelParserSync 50000 5.200 ms 0.0243 ms 0.0063 ms 1.00 46.8750 - 3.86 MB 1.00
ExcelParserAsync 50000 5.192 ms 0.0265 ms 0.0069 ms 1.00 46.8750 - 3.86 MB 1.00
Sep 50000 8.339 ms 0.0632 ms 0.0164 ms 1.60 46.8750 - 3.87 MB 1.00
Sylvan 50000 10.924 ms 0.1270 ms 0.0196 ms 2.10 125.0000 15.6250 10.95 MB 2.84
CsvHelperLib 50000 21.129 ms 0.0829 ms 0.0128 ms 4.06 156.2500 - 14.41 MB 3.73

ExcelReader.Benchmarks.CsvReadBenchmark


BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
INTEL XEON PLATINUM 8573C 3.54GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
  [Host]     : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4
  Job-MEHJPP : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4

IterationCount=5  WarmupCount=1  

Method Rows Mean Error StdDev Ratio RatioSD Gen0 Allocated Alloc Ratio
ExcelReader 50000 3.562 ms 0.0024 ms 0.0004 ms 1.00 0.00 - 352 B 1.00
ExcelReaderWide 50000 9.023 ms 0.0601 ms 0.0156 ms 2.53 0.00 - 288 B 0.82
ExcelReaderAsync 50000 3.430 ms 0.2363 ms 0.0614 ms 0.96 0.02 - 424 B 1.20
Sep 50000 8.573 ms 0.0784 ms 0.0121 ms 2.41 0.00 - 4024 B 11.43
Sylvan 50000 4.577 ms 0.1005 ms 0.0261 ms 1.29 0.01 15.6250 1688685 B 4,797.40
CsvHelperLib 50000 25.209 ms 0.2030 ms 0.0314 ms 7.08 0.01 156.2500 15073424 B 42,822.23

ExcelReader.Benchmarks.CsvWriteBenchmark


BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Intel Xeon 6973P-C 3.63GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
  [Host]     : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4
  Job-MEHJPP : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4

IterationCount=5  WarmupCount=1  

Method Rows Mean Error StdDev Ratio RatioSD Gen0 Gen1 Gen2 Allocated Alloc Ratio
ExcelReaderWriter 50000 6.275 ms 0.4059 ms 0.1054 ms 1.00 0.02 500.0000 500.0000 500.0000 4 MB 1.00
Sep 50000 6.479 ms 0.1573 ms 0.0409 ms 1.03 0.02 500.0000 500.0000 500.0000 4.01 MB 1.00
SylvanWriter 50000 6.922 ms 0.3531 ms 0.0917 ms 1.10 0.02 500.0000 500.0000 500.0000 4.04 MB 1.01
CsvHelperLib 50000 17.604 ms 1.8208 ms 0.4729 ms 2.81 0.08 593.7500 500.0000 500.0000 13.78 MB 3.44

ExcelReader.Benchmarks.ParseBenchmark


BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Intel Xeon 6973P-C 2.60GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
  [Host]     : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4
  Job-MEHJPP : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4

IterationCount=5  WarmupCount=1  

Method Rows Mean Error StdDev Ratio RatioSD Gen0 Allocated Alloc Ratio
ExcelParserSync 50000 16.133 ms 0.0628 ms 0.0163 ms 1.00 0.00 31.2500 3966.75 KB 1.000
ExcelParserSyncSharedStrings 50000 12.336 ms 0.1310 ms 0.0203 ms 0.76 0.00 15.6250 2357.23 KB 0.594
ExcelParserStructSync 50000 13.751 ms 0.2242 ms 0.0347 ms 0.85 0.00 15.6250 1623.02 KB 0.409
RefParserParseNamedSync 50000 13.239 ms 2.0305 ms 0.5273 ms 0.82 0.03 - 11.63 KB 0.003
ExcelParserAsync 50000 14.115 ms 0.4597 ms 0.0711 ms 0.87 0.00 31.2500 3968.9 KB 1.001
ExcelParserXlsbSync 50000 7.443 ms 0.2329 ms 0.0360 ms 0.46 0.00 46.8750 3968.84 KB 1.001
ExcelParserXlsbAsync 50000 7.473 ms 0.0836 ms 0.0217 ms 0.46 0.00 46.8750 3971.41 KB 1.001
MiniExcel 50000 144.190 ms 33.9530 ms 8.8175 ms 8.94 0.50 2000.0000 202523.37 KB 51.055
Sylvan 50000 59.809 ms 3.5859 ms 0.9312 ms 3.71 0.05 100.0000 10726.41 KB 2.704
SylvanAsync 50000 56.840 ms 12.4535 ms 3.2341 ms 3.52 0.18 111.1111 10727.38 KB 2.704

ExcelReader.Benchmarks.ReadBenchmark


BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
INTEL XEON PLATINUM 8573C 3.54GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
  [Host]     : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4
  Job-MEHJPP : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4

IterationCount=5  WarmupCount=1  

Method Rows Mean Error StdDev Ratio RatioSD Gen0 Allocated Alloc Ratio
ExcelReader 50000 13.068 ms 0.0280 ms 0.0073 ms 1.00 0.00 - 11.13 KB 1.00
ExcelReaderAsync 50000 13.311 ms 0.0309 ms 0.0048 ms 1.02 0.00 - 13.26 KB 1.19
ExcelReaderXlsb 50000 5.383 ms 0.0468 ms 0.0122 ms 0.41 0.00 - 13.22 KB 1.19
ExcelReaderXlsbAsync 50000 5.338 ms 0.0190 ms 0.0029 ms 0.41 0.00 - 15.77 KB 1.42
ExcelReaderMaterialized 50000 14.407 ms 0.0314 ms 0.0049 ms 1.10 0.00 15.6250 1622.45 KB 145.84
MiniExcel 50000 166.825 ms 58.4747 ms 15.1857 ms 12.77 1.06 2000.0000 214003.38 KB 19,236.26
Sylvan 50000 40.825 ms 0.3782 ms 0.0585 ms 3.12 0.00 - 1939.48 KB 174.33

ExcelReader.Benchmarks.RealDataReadBenchmark


BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
  [Host]     : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v3
  Job-MEHJPP : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v3

IterationCount=5  WarmupCount=1  

Method Mean Error StdDev Ratio RatioSD Gen0 Gen1 Allocated Alloc Ratio
Xlsx_ExcelReader 96.076 ms 0.3974 ms 0.0615 ms 1.00 0.00 - - 18216 B 1.00
Xlsx_Sylvan 311.437 ms 2.0594 ms 0.3187 ms 3.24 0.00 - - 659568 B 36.21
Xlsx_ExcelReader_Materialized 97.466 ms 2.7164 ms 0.7054 ms 1.01 0.01 - - 27912 B 1.53
Xlsx_ExcelReader_Prefetch 73.535 ms 6.9898 ms 1.8152 ms 0.77 0.02 - - 38496 B 2.11
Xlsx_ExcelReader_Memory 94.837 ms 0.5335 ms 0.0826 ms 0.99 0.00 - - 7104 B 0.39
Xlsx_ExcelReader_Memory_Prefetch 70.044 ms 6.0175 ms 1.5627 ms 0.73 0.01 - - 27410 B 1.50
Xlsm_ExcelReader 96.917 ms 1.3337 ms 0.3463 ms 1.01 0.00 - - 18216 B 1.00
Xlsm_Sylvan 307.869 ms 1.8597 ms 0.2878 ms 3.20 0.00 - - 659648 B 36.21
Xlsm_ExcelReader_Materialized 98.075 ms 1.2857 ms 0.1990 ms 1.02 0.00 - - 27912 B 1.53
Xlsm_ExcelReader_Prefetch 74.570 ms 2.6312 ms 0.4072 ms 0.78 0.00 - - 38512 B 2.11
Xlsm_ExcelReader_Memory 96.553 ms 0.5014 ms 0.0776 ms 1.00 0.00 - - 7104 B 0.39
Xlsm_ExcelReader_Memory_Prefetch 71.040 ms 16.2312 ms 2.5118 ms 0.74 0.02 - - 27373 B 1.50
Xlsb_ExcelReader 33.857 ms 0.2906 ms 0.0755 ms 0.35 0.00 - - 19192 B 1.05
Xlsb_Sylvan 43.763 ms 0.2323 ms 0.0603 ms 0.46 0.00 - - 346673 B 19.03
Xlsb_ExcelReader_Materialized 37.731 ms 0.2800 ms 0.0727 ms 0.39 0.00 - - 28888 B 1.59
Xlsb_ExcelReader_Prefetch 21.288 ms 5.3064 ms 1.3781 ms 0.22 0.01 - - 30500 B 1.67
Xlsb_ExcelReader_Memory 35.440 ms 0.2163 ms 0.0562 ms 0.37 0.00 - - 8840 B 0.49
Xlsb_ExcelReader_Memory_Prefetch 20.397 ms 3.9342 ms 0.6088 ms 0.21 0.01 - - 14600 B 0.80
Xls_ExcelReader 20.580 ms 0.5011 ms 0.1301 ms 0.21 0.00 - - 12048 B 0.66
Xls_Sylvan 27.010 ms 0.2006 ms 0.0310 ms 0.28 0.00 - - 190366 B 10.45
Xls_ExcelReader_Materialized 22.986 ms 0.1486 ms 0.0386 ms 0.24 0.00 - - 21744 B 1.19
Xls_ExcelReader_Memory 15.249 ms 0.1793 ms 0.0466 ms 0.16 0.00 - - 12048 B 0.66
Csv_ExcelReader 8.415 ms 0.0824 ms 0.0128 ms 0.09 0.00 - - 288 B 0.02
Csv_Sylvan 17.439 ms 2.2823 ms 0.5927 ms 0.18 0.01 2218.7500 125.0000 37484040 B 2,057.75
Csv_ExcelReader_Materialized 30.091 ms 0.6300 ms 0.1636 ms 0.31 0.00 2218.7500 - 37442896 B 2,055.49
Csv_ExcelReader_Memory 8.084 ms 0.0606 ms 0.0094 ms 0.08 0.00 - - 224 B 0.01

ExcelReader.Benchmarks.RecordWriteBenchmark


BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Intel Xeon 6973P-C 3.63GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
  [Host]     : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4
  Job-MEHJPP : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4

IterationCount=5  WarmupCount=1  

Method Rows Mean Error StdDev Ratio Gen0 Gen1 Gen2 Allocated Alloc Ratio
Xlsx 50000 18.519 ms 0.4938 ms 0.1282 ms 1.00 500.0000 500.0000 500.0000 4.02 MB 1.00
Xlsb 50000 7.870 ms 0.3346 ms 0.0518 ms 0.42 500.0000 500.0000 500.0000 4.02 MB 1.00
Xls 50000 4.541 ms 0.2928 ms 0.0760 ms 0.25 273.4375 273.4375 273.4375 4.03 MB 1.00
Csv 50000 6.843 ms 0.2285 ms 0.0593 ms 0.37 500.0000 500.0000 500.0000 4 MB 1.00

ExcelReader.Benchmarks.WriteBenchmark


BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Intel Xeon 6973P-C 3.63GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
  [Host]     : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4
  Job-MEHJPP : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4

IterationCount=5  WarmupCount=1  

Method Rows Mean Error StdDev Ratio RatioSD Gen0 Gen1 Gen2 Allocated Alloc Ratio
ExcelReaderWriter 50000 16.385 ms 0.2885 ms 0.0749 ms 1.00 0.01 500.0000 500.0000 500.0000 4.02 MB 1.00
ExcelReaderWriterSharedStrings 50000 16.458 ms 0.6468 ms 0.1680 ms 1.00 0.01 500.0000 500.0000 500.0000 4.06 MB 1.01
ExcelReaderWriterPrefetch 50000 12.582 ms 1.9736 ms 0.3054 ms 0.77 0.02 484.3750 484.3750 484.3750 4.03 MB 1.00
ExcelReaderXlsbWriter 50000 7.989 ms 0.5508 ms 0.1430 ms 0.49 0.01 500.0000 500.0000 500.0000 4.02 MB 1.00
ExcelReaderXlsbWriterSharedStrings 50000 7.404 ms 0.1775 ms 0.0275 ms 0.45 0.00 500.0000 500.0000 500.0000 4.06 MB 1.01
ExcelReaderXlsbWriterPrefetch 50000 6.747 ms 0.2576 ms 0.0669 ms 0.41 0.00 492.1875 492.1875 492.1875 4.03 MB 1.00
MiniExcel 50000 73.276 ms 6.0454 ms 1.5700 ms 4.47 0.09 1428.5714 714.2857 714.2857 84.88 MB 21.11
SpreadCheetah 50000 18.768 ms 1.0026 ms 0.2604 ms 1.15 0.02 656.2500 531.2500 531.2500 15.84 MB 3.94

ExcelReader.Benchmarks.XlsReadBenchmark


BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
INTEL XEON PLATINUM 8573C 3.54GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
  [Host]     : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4
  Job-MEHJPP : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4

IterationCount=5  WarmupCount=1  

Method Rows Mean Error StdDev Ratio Gen0 Allocated Alloc Ratio
ExcelReader 50000 4.148 ms 0.0331 ms 0.0051 ms 1.00 - 2.91 KB 1.00
ExcelReaderAsync 50000 4.174 ms 0.0197 ms 0.0051 ms 1.01 - 2.98 KB 1.02
Sylvan 50000 5.823 ms 0.0573 ms 0.0149 ms 1.40 15.6250 1717.72 KB 589.46

ExcelReader.Benchmarks.XlsWriteBenchmark


BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Intel Xeon 6973P-C 3.63GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
  [Host]     : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4
  Job-MEHJPP : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4

IterationCount=5  WarmupCount=1  

Method Rows Mean Error StdDev Ratio RatioSD Gen0 Gen1 Gen2 Allocated Alloc Ratio
XlsWriter 50000 4.087 ms 0.0714 ms 0.0185 ms 1.00 0.01 492.1875 492.1875 492.1875 16.03 MB 1.00
XlsxWriter 50000 16.790 ms 1.9528 ms 0.5071 ms 4.11 0.11 500.0000 500.0000 500.0000 4.02 MB 0.25

GabrielMarquezMatte and others added 24 commits August 19, 2026 10:54
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 6 to 8.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v6...v8)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6 to 7.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](actions/setup-python@v6...v7)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2 to 3.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](softprops/action-gh-release@v2...v3)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
…dings

Extends the single-name-per-field ABI (xl_column_spec) to an ordered
candidate list resolved first-match-wins, matching the C# core's
existing ExcelColumnAttribute(AllowMultiple) semantics, and threads it
through the native core, C++, Rust, and Python bindings.
Bumps xunit.runner.visualstudio from 3.1.5 to 4.0.0
Bumps xunit.v3.mtp-v2 from 3.2.2 to 4.0.0

---
updated-dependencies:
- dependency-name: xunit.runner.visualstudio
  dependency-version: 4.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: test
- dependency-name: xunit.v3.mtp-v2
  dependency-version: 4.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: test
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps Microsoft.CodeAnalysis.Analyzers from 5.6.0 to 5.9.0-1.26328.17
Bumps Microsoft.CodeAnalysis.CSharp from 5.6.0 to 5.9.0

---
updated-dependencies:
- dependency-name: Microsoft.CodeAnalysis.Analyzers
  dependency-version: 5.9.0-1.26328.17
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: Microsoft.CodeAnalysis.CSharp
  dependency-version: 5.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: Microsoft.CodeAnalysis.CSharp
  dependency-version: 5.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
updated-dependencies:
- dependency-name: Sep
  dependency-version: 0.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Six tasks covering the ABI struct change, the C# native core (read,
write, schema-inference), and the C, C++, Rust, and Python bindings,
each with TDD steps grounded in the actual existing test files/helpers.
… list

Bumps XL_ABI_VERSION to 2. xl_column_spec.name/name_len become
names/name_lens/name_count; the read path (xl_parse_typed/xl_parse_arrow)
tries each candidate in order and binds the first one present in the
header row.
…location

Adds NativeLimits.MaxNamesPerSpec and IsValidNameCount, mirroring the
existing spec-count/name-length guards, and checks it first in
TryDecodeColumnSpecs before any candidate-name pointer is read.

Addresses code review finding on the multi-name column binding task.
FieldBinding<Class, T, N> stores N candidate names (default N=1, source-
compatible with the existing single-name make_field); build_specs marshals
them into xl_column_spec's names/name_lens/name_count.
…esolution

ColumnBinding.names replaces .name (a &'static [&'static str] instead of
a single &'static str); the derive macro collects name plus every alias
in declared order. Bumps XL_ABI_VERSION to 2.
ColumnSpec.name widens to str | Sequence[str] | None; _native gains
column_spec_by_names alongside the existing single-name helper. Bumps
XL_ABI_VERSION to 2 to match the native library.
…s/ExcelReader.Benchmarks/develop/Sep-0.17.0

Bump Sep from 0.15.2 to 0.17.0
…lop/multi-f1e6270e1a

Bump Microsoft.CodeAnalysis.Analyzers and Microsoft.CodeAnalysis.CSharp
…s/ExcelReader.Tests/develop/test-0a3d55c981

Bump the test group with 2 updates
…ions/develop/softprops/action-gh-release-3

build(deps): bump softprops/action-gh-release from 2 to 3
…ions/develop/actions/setup-python-7

build(deps): bump actions/setup-python from 6 to 7
…ions/develop/actions/download-artifact-8

build(deps): bump actions/download-artifact from 6 to 8
@GabrielMarquezMatte
GabrielMarquezMatte merged commit 9a244f1 into master Aug 20, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants