Sheetz Benchmarks

June 17, 2026 ยท View on GitHub

Build Java 11+ License JMH GitHub stars

๐Ÿ“š Full Documentation | ๐Ÿ”„ Migration from POI | ๐Ÿ“Š Benchmarks

How does Sheetz compare to Apache POI, EasyExcel, FastExcel, and Poiji? This project answers that question with side-by-side code comparisons and reproducible JMH performance benchmarks across 1K, 10K, and 100K rows.

TL;DR

  • Sheetz needs 1 line to read or write Excel. Apache POI needs 25+. EasyExcel needs 12+ (with listener).
  • At 100K rows, Sheetz writes are 5.8x faster than Apache POI thanks to automatic SXSSF streaming.
  • FastExcel and EasyExcel have faster raw throughput, but require significantly more code and lack features like validation, multi-format support, and automatic type conversion.

New to Sheetz? See the main repo for docs and API reference, or browse 8 runnable examples.


Libraries Compared

LibraryVersionAPI StyleReadWriteAnnotationsValidation
Sheetz1.1.0One-liner, annotation-basedYesYes@ColumnBuilt-in
Apache POI5.2.5Manual cell-level APIYesYesNoneNone
EasyExcel4.0.3Annotation + listener patternYesYes@ExcelPropertyNone
FastExcel0.19.0Lightweight cell-level APIYesYesNoneNone
Poiji5.2.0Annotation-based (read-only)YesNo@ExcelCellNameNone

Code Comparison

The question: How many lines does it take to write 10 products to Excel and read them back?

LibraryWriteReadTotal LinesNotes
Sheetz11~15One-liner read & write
Apache POI~25~20~60Manual workbook/sheet/row/cell
EasyExcel~3~12~30Separate model + listener pattern
FastExcel~18~15~45Cell-by-cell positional API
Poijiโ€”~1~15Read-only library

Sheetz โ€” 1 line write, 1 line read

Sheetz.write(products, "products.xlsx");
List<Product> result = Sheetz.read("products.xlsx", Product.class);

That's the entire implementation. No workbook objects, no cell iteration, no type casting.

Apache POI โ€” ~25 lines write, ~20 lines read

// Write โ€” manual workbook creation
try (Workbook workbook = new XSSFWorkbook()) {
    Sheet sheet = workbook.createSheet("Products");
    Row headerRow = sheet.createRow(0);
    headerRow.createCell(0).setCellValue("Product Name");
    headerRow.createCell(1).setCellValue("Price");
    // ... create each header cell manually

    for (int i = 0; i < products.size(); i++) {
        Row row = sheet.createRow(i + 1);
        row.createCell(0).setCellValue(products.get(i).name);
        row.createCell(1).setCellValue(products.get(i).price);
        // ... set each cell manually
    }
    workbook.write(new FileOutputStream("products.xlsx"));
}

// Read โ€” manual row/cell iteration
try (Workbook workbook = new XSSFWorkbook(new FileInputStream("products.xlsx"))) {
    Sheet sheet = workbook.getSheetAt(0);
    for (int i = 1; i <= sheet.getLastRowNum(); i++) {
        Row row = sheet.getRow(i);
        Product p = new Product();
        p.name = row.getCell(0).getStringCellValue();
        p.price = row.getCell(1).getNumericCellValue();
        // ... extract each field manually
    }
}

EasyExcel โ€” 3 lines write, ~12 lines read (listener pattern)

// Write
EasyExcel.write("products.xlsx", ProductEasyExcel.class)
        .sheet("Products").doWrite(data);

// Read โ€” requires listener pattern
List<ProductEasyExcel> result = new ArrayList<>();
EasyExcel.read("products.xlsx", ProductEasyExcel.class,
    new ReadListener<ProductEasyExcel>() {
        public void invoke(ProductEasyExcel data, AnalysisContext ctx) {
            result.add(data);
        }
        public void doAfterAllAnalysed(AnalysisContext ctx) {}
    }).sheet().doRead();

FastExcel โ€” ~18 lines write, ~15 lines read

// Write โ€” cell by cell
Workbook wb = new Workbook(outputStream, "App", "1.0");
Worksheet ws = wb.newWorksheet("Products");
ws.value(0, 0, "Product Name");
ws.value(0, 1, "Price");
// ... set each header and data cell by position

// Read โ€” cell by cell
ReadableWorkbook wb = new ReadableWorkbook(inputStream);
Sheet sheet = wb.getFirstSheet();
sheet.openStream().skip(1).forEach(row -> {
    Product p = new Product();
    p.name = row.getCellText(0);
    p.price = Double.parseDouble(row.getCellText(1));
    // ... parse each cell manually
});

View all comparison source code


Performance Benchmarks (JMH)

All benchmarks measure average time per operation (lower is better) using JMH 1.37.

Environment: JDK 11.0.30 (OpenJDK), Apple Silicon (macOS), 2 forks, 3 warmup iterations, 5 measurement iterations

๐Ÿ“Š Visual Summary

The charts below are generated from the JMH results in results/results.txt.

Write Performance โ€” 100K rows (ms/op, lower is better)

FastExcel   โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘  309ms
EasyExcel   โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘  542ms
Sheetz      โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘  423ms  โ† auto SXSSF streaming
Apache POI  โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ  2453ms โ† no streaming, loads to memory

Read Performance โ€” 100K rows (ms/op, lower is better)

FastExcel   โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘  210ms
EasyExcel   โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘  334ms
Apache POI  โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘  1097ms
Poiji       โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘  1042ms
Sheetz      โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ  1285ms  โ† with type conversion & mapping

Generate PNG charts: paste results/results.txt into https://jmh.morethan.io

Write Performance (ms/op โ€” lower is better)

Library1K rows10K rows100K rows
FastExcel6.48 ยฑ 1.4731.95 ยฑ 1.00309.70 ยฑ 17.59
EasyExcel11.44 ยฑ 0.5058.60 ยฑ 1.54542.84 ยฑ 33.32
Sheetz23.15 ยฑ 0.62232.51 ยฑ 18.70423.75 ยฑ 20.14
Apache POI22.46 ยฑ 0.53217.17 ยฑ 9.592,453.35 ยฑ 112.24

At small file sizes, Sheetz and Apache POI are comparable. At 100K rows, Sheetz is 5.8x faster than POI because it automatically switches to SXSSF streaming โ€” something POI requires you to configure manually.

Read Performance (ms/op โ€” lower is better)

Library1K rows10K rows100K rows
FastExcel2.43 ยฑ 0.1224.88 ยฑ 1.75210.17 ยฑ 4.10
EasyExcel4.91 ยฑ 0.5542.66 ยฑ 6.87334.17 ยฑ 15.53
Apache POI10.86 ยฑ 0.46106.02 ยฑ 9.111,097.20 ยฑ 79.91
Poiji12.26 ยฑ 0.40114.92 ยฑ 1.971,042.16 ยฑ 50.28
Sheetz13.18 ยฑ 0.58128.35 ยฑ 12.951,285.89 ยฑ 64.96

For reads, FastExcel and EasyExcel are faster at raw throughput. Sheetz performs comparably to Apache POI and Poiji while offering annotation-based mapping, automatic type conversion, and built-in validation that those libraries don't provide.

๐ŸŽฏ When to Choose Each Library

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    DECISION GUIDE                       โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                         โ”‚
โ”‚  Need maximum raw throughput?                           โ”‚
โ”‚  โ†’ FastExcel (fastest reads & writes)                   โ”‚
โ”‚                                                         โ”‚
โ”‚  Need minimal code + all features?                      โ”‚
โ”‚  โ†’ Sheetz (1-line API, validation, 19 converters)       โ”‚
โ”‚                                                         โ”‚
โ”‚  Already using POI everywhere?                          โ”‚
โ”‚  โ†’ Sheetz (wraps POI, drop-in for new code)             โ”‚
โ”‚                                                         โ”‚
โ”‚  Processing 1M+ rows, memory is critical?               โ”‚
โ”‚  โ†’ Sheetz.stream() or FastExcel                         โ”‚
โ”‚                                                         โ”‚
โ”‚  Need annotation-based mapping + read speed?            โ”‚
โ”‚  โ†’ EasyExcel (but requires listener pattern)            โ”‚
โ”‚                                                         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Sheetz's read speed is comparable to Apache POI and Poiji. The difference from FastExcel/EasyExcel is the overhead of automatic type conversion, annotation processing, and validation โ€” features those libraries don't provide. If you need those features, Sheetz gives them at no extra code cost.

Full raw JMH output is available in results/results.txt.


How to Run

Prerequisites

  • Java 11+
  • Maven 3.6+

Code Comparison Demos

Each comparison class has a main() that writes products to Excel and reads them back, showing the actual code needed for each library.

# Clone and compile
git clone https://github.com/chitralabs/sheetz-benchmarks.git
cd sheetz-benchmarks
mvn compile

# Run any comparison
mvn exec:java -Dexec.mainClass="io.github.chitralabs.sheetz.benchmarks.comparison.SheetzComparison"
mvn exec:java -Dexec.mainClass="io.github.chitralabs.sheetz.benchmarks.comparison.ApachePoiComparison"
mvn exec:java -Dexec.mainClass="io.github.chitralabs.sheetz.benchmarks.comparison.EasyExcelComparison"
mvn exec:java -Dexec.mainClass="io.github.chitralabs.sheetz.benchmarks.comparison.FastExcelComparison"
mvn exec:java -Dexec.mainClass="io.github.chitralabs.sheetz.benchmarks.comparison.PoijiComparison"

JMH Performance Benchmarks

# Build the benchmark JAR
mvn clean package

# Run all benchmarks (full run โ€” takes ~30 minutes)
java -jar target/benchmarks.jar

# Quick smoke test (~2 minutes)
java -jar target/benchmarks.jar -f 1 -wi 1 -i 1

# Run only read or write benchmarks
java -jar target/benchmarks.jar ReadBenchmark
java -jar target/benchmarks.jar WriteBenchmark

# Run with a specific row count
java -jar target/benchmarks.jar -p rowCount=10000

Methodology

SettingValue
FrameworkJMH 1.37 (OpenJDK Microbenchmark Harness)
ModeAverage time per operation (Mode.AverageTime)
Forks2 (separate JVM processes)
Warmup3 iterations, 1 second each
Measurement5 iterations, 1 second each
Row counts1,000 / 10,000 / 100,000 (via @Param)
DataFixed random seed for reproducibility
File format.xlsx (OOXML) for all libraries
FairnessAll libraries read/write identical data; test files generated once in @Setup

Results will vary by JVM version, OS, and hardware. Run the benchmarks yourself to get numbers for your environment.


Project Structure

src/main/java/io/github/chitralabs/sheetz/benchmarks/
โ”œโ”€โ”€ comparison/          โ€” Side-by-side code demos (each has main())
โ”‚   โ”œโ”€โ”€ SheetzComparison.java
โ”‚   โ”œโ”€โ”€ ApachePoiComparison.java
โ”‚   โ”œโ”€โ”€ EasyExcelComparison.java
โ”‚   โ”œโ”€โ”€ FastExcelComparison.java
โ”‚   โ””โ”€โ”€ PoijiComparison.java
โ”œโ”€โ”€ jmh/                 โ€” JMH performance benchmarks
โ”‚   โ”œโ”€โ”€ ReadBenchmark.java
โ”‚   โ”œโ”€โ”€ WriteBenchmark.java
โ”‚   โ””โ”€โ”€ DataGenerator.java
โ””โ”€โ”€ model/               โ€” Shared data models
    โ”œโ”€โ”€ Product.java            (Sheetz + Poiji annotations)
    โ”œโ”€โ”€ ProductEasyExcel.java   (EasyExcel annotations)
    โ””โ”€โ”€ ProductPoi.java         (Plain POJO for manual APIs)

License

Apache License 2.0 โ€” free for commercial and personal use.


If these benchmarks helped you evaluate Sheetz, consider giving the main repo a star. It helps other developers discover the project.

Star Sheetz