Performance
The rust_xlsxwriter
library has sister libraries written in C
(libxlsxwriter), Python (XlsxWriter) and Perl (Excel::Writer::XLSX).
A hyperfine performance comparison between the C, Rust and Python versions is shown below. The Perl performance is similar to the Python library.
$ hyperfine ./app_perf_test ./c_perf_test "python py_perf_test.py" --warmup 3
Benchmark 1: ./app_perf_test
Time (mean ± σ): 233.6 ms ± 1.6 ms [User: 216.0 ms, System: 15.7 ms]
Range (min … max): 230.7 ms … 235.7 ms 12 runs
Benchmark 2: ./c_perf_test
Time (mean ± σ): 197.2 ms ± 2.0 ms [User: 163.1 ms, System: 28.4 ms]
Range (min … max): 194.5 ms … 201.0 ms 14 runs
Benchmark 3: python py_perf_test.py
Time (mean ± σ): 1.099 s ± 0.011 s [User: 1.051 s, System: 0.041 s]
Range (min … max): 1.085 s … 1.125 s 10 runs
Summary
'./c_perf_test' ran
1.18 ± 0.01 times faster than './app_perf_test'
5.57 ± 0.08 times faster than 'python py_perf_test.py'
Or in other words, the C version is the fastest and if we take that as 1 then the rust version is 1.18x (or 18%) slower and the Python version is 5.5x slower.
The rust_xlsxwriter
library also has an optional compilation "feature" called
zlib
which will allow it (via ZipWriter) to use compression from a native C
library. This improves the performance on large files significantly and even
beats the C/libxlsxwriter version:
$ hyperfine ./app_perf_test ./app_perf_test_zlib ./c_perf_test --warmup 3
Benchmark 1: ./app_perf_test
Time (mean ± σ): 244.3 ms ± 10.5 ms [User: 221.5 ms, System: 18.1 ms]
Range (min … max): 231.8 ms … 259.8 ms 11 runs
Benchmark 2: ./app_perf_test_zlib
Time (mean ± σ): 149.4 ms ± 10.5 ms [User: 129.5 ms, System: 16.1 ms]
Range (min … max): 140.7 ms … 178.5 ms 18 runs
Benchmark 3: ./c_perf_test
Time (mean ± σ): 197.7 ms ± 2.3 ms [User: 163.4 ms, System: 28.4 ms]
Range (min … max): 195.4 ms … 204.5 ms 14 runs
Summary
'./app_perf_test_zlib' ran
1.32 ± 0.09 times faster than './c_perf_test'
1.63 ± 0.13 times faster than './app_perf_test'
As with any performance test there are a lot of factors that may affect the results, however these results are indicative of the relative performance.
The programs used to generate these results are shown below.
Rust
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright 2022-2024, John McNamara, jmcnamara@cpan.org
//! Simple performance test for rust_xlsxwriter.
use rust_xlsxwriter::{Workbook, XlsxError};
fn main() -> Result<(), XlsxError> {
let mut workbook = Workbook::new();
let worksheet = workbook.add_worksheet();
let row_max = 4000;
let col_max = 50;
for row in 0..row_max {
for col in 0..col_max {
if col % 2 == 1 {
worksheet.write_string(row, col, "Foo")?;
} else {
worksheet.write_number(row, col, 12345.0)?;
}
}
}
workbook.save("rust_perf_test.xlsx")?;
Ok(())
}
C
#include "xlsxwriter.h"
int main() {
int max_row = 4000;
int max_col = 50;
lxw_workbook *workbook = workbook_new("c_perf_test.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
for (int row_num = 0; row_num < max_row; row_num++) {
for (int col_num = 0; col_num < max_col; col_num++) {
if (col_num % 2)
worksheet_write_string(worksheet, row_num, col_num, "Foo", NULL);
else
worksheet_write_number(worksheet, row_num, col_num, 12345.0, NULL);
}
}
workbook_close(workbook);
return 0;
}
Python
import xlsxwriter
row_max = 4000
col_max = 50
workbook = xlsxwriter.Workbook('py_perf_test.xlsx')
worksheet = workbook.add_worksheet()
for row in range(0, row_max):
for col in range(0, col_max):
if col % 2:
worksheet.write_string(row, col, "Foo")
else:
worksheet.write_number(row, col, 12345)
workbook.close()