getActiveSheet(); $sheet->setTitle('Benchmark'); // Header row with styling for ($col = 1; $col <= $columnCount; ++$col) { $sheet->setCellValue([$col, 1], "Column{$col}"); $sheet->getStyle([$col, 1])->getFont()->setBold(true); } // Repeating strings exercise the shared string table (SST) $labels = ['Alpha', 'Bravo', 'Charlie', 'Delta', 'Echo', 'Foxtrot']; $labelCount = count($labels); for ($row = 2; $row <= $rowCount + 1; ++$row) { // Columns 1-4: numeric (RK / NUMBER records) $sheet->setCellValue([1, $row], $row); $sheet->setCellValue([2, $row], $row * 3.14159); $sheet->setCellValue([3, $row], $row % 100); $sheet->setCellValue([4, $row], round($row * 1.37, 2)); // Columns 5-8: strings (LABELSST records) $sheet->setCellValue([5, $row], $labels[$row % $labelCount]); $sheet->setCellValue([6, $row], "Item {$row}"); $sheet->setCellValue([7, $row], $labels[($row + 3) % $labelCount] . ' ' . ($row % 50)); $sheet->setCellValue([8, $row], 'Ref-' . str_pad((string) $row, 8, '0', STR_PAD_LEFT)); // Columns 9-10: formulas (FORMULA records) $sheet->setCellValue([9, $row], "=B{$row}*D{$row}"); $sheet->setCellValue([10, $row], "=A{$row}+C{$row}"); } // Number formats so cells carry non-default XF indexes $sheet->getStyle("B2:B{$rowCount}")->getNumberFormat()->setFormatCode('#,##0.00'); $sheet->getStyle("D2:D{$rowCount}")->getNumberFormat()->setFormatCode('0.00'); $tempFile = tempnam(sys_get_temp_dir(), 'xls_bench_'); if ($tempFile === false) { throw new RuntimeException('Unable to create temporary file'); } $writer = new XlsWriter($spreadsheet); $writer->save($tempFile); $spreadsheet->disconnectWorksheets(); return $tempFile; } /** @param float[] $values */ function median(array $values): float { sort($values); $count = count($values); $middle = intdiv($count, 2); if ($count % 2 === 0) { return ($values[$middle - 1] + $values[$middle]) / 2; } return $values[$middle]; } $results = []; foreach ($cellCounts as $cellCount) { echo "--- {$cellCount} cells ---\n"; echo "Generating test file...\n"; $tempFile = createXlsFile($cellCount, $columnCount); $fileSize = filesize($tempFile); echo sprintf("File size: %.1fKB\n", ($fileSize ?: 0) / 1024); $reader = new XlsReader(); // Warm up (autoloading, opcache) $warmup = $reader->load($tempFile); $warmup->disconnectWorksheets(); unset($warmup); gc_collect_cycles(); $times = []; for ($i = 0; $i < $iterations; ++$i) { $start = hrtime(true); $spreadsheet = $reader->load($tempFile); $elapsedMs = (hrtime(true) - $start) / 1e6; $times[] = $elapsedMs; echo sprintf("Iteration %d: %.1fms\n", $i + 1, $elapsedMs); $spreadsheet->disconnectWorksheets(); unset($spreadsheet); gc_collect_cycles(); } $medianMs = median($times); $peakMb = memory_get_peak_usage(true) / 1048576; echo sprintf("Median: %.1fms, Peak memory: %.1fMB\n\n", $medianMs, $peakMb); $results[] = [ 'cells' => $cellCount, 'median' => $medianMs, 'peak' => $peakMb, ]; unlink($tempFile); } echo "--- Results ---\n"; echo sprintf("%10s | %12s | %12s\n", 'Cells', 'Median (ms)', 'Peak (MB)'); foreach ($results as $result) { echo sprintf("%10d | %12.1f | %12.1f\n", $result['cells'], $result['median'], $result['peak']); }