PHP-ETL - Cook Books
Benchmark - Large CSV
Benchmark - Large CSV
The scripts in examples/20-Benchmark/ measure how long a simple chain takes on a large CSV file,
compared with a plain PHP loop doing the same work.
Every script reads the file, keeps the rows where keep is 1 (5% of them) and writes them to a new CSV.
| Script | What it runs |
|---|---|
00-RawFgetcsv.php |
Plain fgetcsv loop with no ETL. This is the baseline. |
01-ExtractFilterWrite.php |
CsvExtractConfig β FilterDataConfig β CsvFileWriterConfig |
02-GzipExtract.php |
Same chain, reading bench.csv.gz with compression: 'gzip' |
03-ProjectionExtract.php |
Same chain, keeping only 3 of the 30 columns with columns |
04-XanExtract.php |
CommandCsvExtractConfig running xan filter on the local .gz file |
05-XanExtractRemote.php |
Same with a remote-like file system: the file is streamed into gzip -dc \| xan filter |
The chain scripts print the time spent in each operation using the chain observer (the third argument of process()).
Running it
cd examples/20-Benchmark
php generate.php 1000000 # 1M rows, 30 columns: data/bench.csv (424 MB) and data/bench.csv.gz (66 MB)
php 00-RawFgetcsv.php
php 01-ExtractFilterWrite.php
php 02-GzipExtract.php
php 03-ProjectionExtract.php
php 04-XanExtract.php # requires xan
php 05-XanExtractRemote.php # requires xan
The scripts must be run from the 20-Benchmark directory, since paths are relative to it.
Results
1M rows, PHP 8.5, Apple Silicon:
| Script | Total | Peak memory |
|---|---|---|
00-RawFgetcsv.php |
5.2s | 2 MB |
01-ExtractFilterWrite.php |
12.6s | 4 MB |
02-GzipExtract.php |
12.8s | 4 MB |
03-ProjectionExtract.php |
12.3s | 4 MB |
04-XanExtract.php |
0.5s | 4 MB |
05-XanExtractRemote.php |
0.55s | 4 MB |
Observer output for 01-ExtractFilterWrite.php:
Operation Processed Returned Time (ms)
extract 1 1 0
filter 1000001 50001 5522
write 50001 50001 290
What this shows:
- The chain is about 2.4Γ slower than the plain loop. The filterβs expression (Symfony Expression Language) accounts for 5.5s of that, which is where to look first on large files.
extractshows 0ms because rows are read lazily: parsing happens while the chain pulls rows, so it isnβt counted against the extract operation.- Reading the gzip file directly costs about 0.2s more and saves 358 MB of disk.
columnsonly saves a little, becausefgetcsvstill parses every field. It helps more when later operations work on the whole row.- Letting xan filter the rows (CommandCsvExtractConfig) is about 25Γ faster: PHP only handles the 50k rows that are kept.