1010 * Reports the median wall-clock time and peak memory for the main
1111 * export/import paths. Memory numbers are stable across runs; time on
1212 * shared CI runners is noisy, so deltas under ~10% should be ignored.
13+ *
14+ * Peak memory is read with memory_get_peak_usage(false) — PHP's own
15+ * allocator, which is released back between cases. The real (true) figure
16+ * reports the process high-water mark from the OS allocator, which never
17+ * shrinks, so a 4 MB streaming case measured after a 30 MB collection case
18+ * would wrongly report ~30 MB. Using the PHP figure keeps every case honest
19+ * in a single process.
1320 */
1421
1522use OpenSpout \Common \Entity \Style \Style ;
2936$ dir = sys_get_temp_dir ().'/fastexcel-bench- ' .getmypid ();
3037mkdir ($ dir );
3138
39+ $ style = (new Style ())->setFontBold ();
40+
41+ $ results = [];
42+
43+ // The collection cases share one materialized collection (15 MB+ at 30k rows).
44+ // It is freed before the streaming cases so their peak memory reflects the
45+ // streaming path alone, not a leftover collection still held in scope.
3246$ collection = collect (array_map (fn ($ i ) => [
3347 'id ' => $ i ,
3448 'name ' => 'name_ ' .$ i ,
3549 'email ' => 'user ' .$ i .'@example.com ' ,
3650 'amount ' => $ i * 1.5 ,
3751], range (1 , $ rows )));
3852
39- $ style = (new Style ())->setFontBold ();
40-
41- $ results = [
42- 'export_plain ' => bench ($ runs , function () use ($ collection , $ dir ) {
43- (new FastExcel ($ collection ))->export ($ dir .'/plain.xlsx ' );
44- }),
45- 'export_styled ' => bench ($ runs , function () use ($ collection , $ dir , $ style ) {
46- (new FastExcel ($ collection ))->headerStyle ($ style )->rowsStyle ($ style )->export ($ dir .'/styled.xlsx ' );
47- }),
48- 'import ' => bench ($ runs , function () use ($ dir ) {
49- (new FastExcel ())->import ($ dir .'/plain.xlsx ' );
50- }),
51- 'import_transposed ' => bench ($ runs , function () use ($ dir ) {
52- (new FastExcel ())->transpose ()->import ($ dir .'/plain.xlsx ' );
53- }),
54- ];
53+ $ results ['export_plain ' ] = bench ($ runs , function () use ($ collection , $ dir ) {
54+ (new FastExcel ($ collection ))->export ($ dir .'/plain.xlsx ' );
55+ });
56+ $ results ['export_styled ' ] = bench ($ runs , function () use ($ collection , $ dir , $ style ) {
57+ (new FastExcel ($ collection ))->headerStyle ($ style )->rowsStyle ($ style )->export ($ dir .'/styled.xlsx ' );
58+ });
59+
60+ unset($ collection );
61+ gc_collect_cycles ();
62+
63+ // Streaming export: a generator never materializes the full dataset, so peak
64+ // memory stays flat no matter how many rows are written.
65+ $ results ['export_generator ' ] = bench ($ runs , function () use ($ rows , $ dir ) {
66+ (new FastExcel (rowGenerator ($ rows )))->export ($ dir .'/gen.xlsx ' );
67+ });
68+
69+ // Import cases read the file written by export_plain above.
70+ $ results ['import ' ] = bench ($ runs , function () use ($ dir ) {
71+ (new FastExcel ())->import ($ dir .'/plain.xlsx ' );
72+ });
73+ // Streaming import: importLazy() yields rows one at a time instead of
74+ // accumulating them into a Collection.
75+ $ results ['import_lazy ' ] = bench ($ runs , function () use ($ dir ) {
76+ (new FastExcel ())->importLazy ($ dir .'/plain.xlsx ' )->each (fn ($ row ) => $ row );
77+ });
78+ $ results ['import_transposed ' ] = bench ($ runs , function () use ($ dir ) {
79+ (new FastExcel ())->transpose ()->import ($ dir .'/plain.xlsx ' );
80+ });
5581
5682array_map ('unlink ' , glob ($ dir .'/* ' ));
5783rmdir ($ dir );
6591 }
6692}
6793
94+ /**
95+ * A fresh generator over the benchmark row shape. Generators are single-use,
96+ * so each timed run needs a new one.
97+ */
98+ function rowGenerator (int $ rows ): Generator
99+ {
100+ for ($ i = 1 ; $ i <= $ rows ; $ i ++) {
101+ yield [
102+ 'id ' => $ i ,
103+ 'name ' => 'name_ ' .$ i ,
104+ 'email ' => 'user ' .$ i .'@example.com ' ,
105+ 'amount ' => $ i * 1.5 ,
106+ ];
107+ }
108+ }
109+
68110function bench (int $ runs , callable $ callback ): array
69111{
70112 $ times = [];
@@ -78,7 +120,7 @@ function bench(int $runs, callable $callback): array
78120 $ start = hrtime (true );
79121 $ callback ();
80122 $ times [] = (hrtime (true ) - $ start ) / 1e9 ;
81- $ peak = max ($ peak , memory_get_peak_usage (true ));
123+ $ peak = max ($ peak , memory_get_peak_usage (false ));
82124 }
83125
84126 sort ($ times );
0 commit comments