Lab / Open methodology

PHP report optimization: one-pass aggregation

200,000 orders summarized: 1.27 s → 8.49 ms. Synthetic lab; median of 10 runs. Open code and raw data.

CompletedSMBEnterprisePartners

Rescan for every customertoAggregate in one pass

PHP 8.4 LAB MEASUREMENT

Stop reading the same orders again and again.

Order totals by customer. Same PHP version, same data, same output; a different way to compute it.

Business effect

Repeated reports consume less CPU. The task spends less time running while the team waits for its result.

BEFORERescan for every customer
MODERNIZEDAggregate in one pass
Order records200,000
1,000Recorded loads only200,000
Actual time scale
SAME TASK · SAME DATA10 runs · median
01

Rescan for every customer

Read the order list again for each customer.

1.265 s
CPU time
1.265 s
02

Aggregate in one pass

Read orders once and accumulate totals by customer key.

8.487 ms
CPU time
8.495 ms

Bars start at zero and share the same time scale across implementations.

Completion time reduced99.3%Time difference: 1.257 sOriginal → modernized implementation
What changed?

Replace a full scan per customer with totals indexed by customer key. Business rules and integer-cent amounts remain identical.

All load points and measurements
1,000 · Order records
ImplementationMedian durationCPU time
Rescan for every customer2.93 ms2.916 ms
Aggregate in one pass0.04 ms0.041 ms
3,000 · Order records
ImplementationMedian durationCPU time
Rescan for every customer8.362 ms8.363 ms
Aggregate in one pass0.114 ms0.114 ms
10,000 · Order records
ImplementationMedian durationCPU time
Rescan for every customer28.426 ms28.429 ms
Aggregate in one pass0.371 ms0.373 ms
30,000 · Order records
ImplementationMedian durationCPU time
Rescan for every customer83.354 ms83.352 ms
Aggregate in one pass0.898 ms0.902 ms
60,000 · Order records
ImplementationMedian durationCPU time
Rescan for every customer190.504 ms190.479 ms
Aggregate in one pass2.059 ms2.065 ms
100,000 · Order records
ImplementationMedian durationCPU time
Rescan for every customer436.716 ms436.251 ms
Aggregate in one pass4.175 ms4.183 ms
200,000 · Order records
ImplementationMedian durationCPU time
Rescan for every customer1.265 s1.265 s
Aggregate in one pass8.487 ms8.495 ms
CPU cost at your workload

Compare the recorded CPU time at your own monthly volume.

One batch run = 200,000 Order records.

CPU time reduced / month3.49 hours

Processing cost difference / month—Calculated after you enter a unit price.

Lab CPU time × your volume and unit price. This is not a hosting bill forecast; idle capacity, networking, storage, licences and migration are excluded.

Fix the query and tenant access together.
  • Normal order

    Before

    Passed

    ✓ After

    Passed

  • Missing order

    Before

    Passed

    ✓ After

    Passed

  • Apostrophe in order reference

    Before

    Query error

    ✓ After

    Passed

  • SQL input bypass

    Before

    6 unauthorized rows

    ✓ After

    Passed

  • SQL input targeting another tenant

    Before

    6 unauthorized rows

    ✓ After

    Passed

  • Direct cross-tenant reference

    Before

    1 unauthorized rows

    ✓ After

    Passed

Security test and evidence ↗

Try it yourself

Replay the recorded lab results side by side.

As the workload grows

Duration by workload

  • Before
  • After

Duration by workload (ms)

05001,0001,5001,00060,000100,000200,0001,265.12 ms8.49 ms

Select a data point

05001,0001,5001,00060,000200,0008.49 ms

Select a data point

Order recordsMarkers: measured points
Show as a table
Duration by workload
Order recordsBeforeAfter
1,0002.93 ms0.04 ms
3,0008.36 ms0.11 ms
10,00028.43 ms0.37 ms
30,00083.35 ms0.9 ms
60,000190.5 ms2.06 ms
100,000436.72 ms4.18 ms
200,0001,265.12 ms8.49 ms

How we measured

Environment, protocol and technical analysis

Environment and data

Environment
Apple M3; Docker Linux arm64, 2-CPU quota, 1 GiB memory. PHP 8.4.26 / SQLite 3.46.1.
Dataset
200 customers; 1,000–200,000 deterministic orders. All result rows and cent totals match across implementations.
Tools
PHP 8.4.26 · SQLite 3.46.1 · hrtime / getrusage · OPcache / JIT off · native arm64 Docker
Repetitions
7 loads × 5 implementations × 10 repeats, plus 70 warmup observations. Every sample retained; rotating arm order.
Open raw measurement data ↗

Stop reading the same orders again and again.

Order totals by customer. Same PHP version, same data, same output; a different way to compute it.

Identical PHP/SQLite versions, synthetic records and 200 customers. Two warmups then 10 runs per arm/size; every complete output matches an independent oracle. PHP lookup totals rebuilt each run. SQL timings are warm in-memory reads excluding loading/index creation. Index bytes and the single construction observation are separate. Primary 200,000-record point selected before measurement.

Inspect the measurement script ↗

What changes for the business?

Repeated reports consume less CPU. The task spends less time running while the team waits for its result.

Change and scope

Replace a full scan per customer with totals indexed by customer key. Business rules and integer-cent amounts remain identical.

PHP 8.4.26 CLI; synthetic in-memory data, 200 customers. OPcache/JIT off. This measures a code improvement, not a PHP 7 → 8 speedup.

Bind values and enforce access

This separate synthetic order-lookup test is independent of the performance results. All six checks are published.

Implementation Passing checks Remaining issue
Input concatenated into SQL 2 / 6 Apostrophe handling, SQL injection and cross-tenant access
Prepared statement only 5 / 6 A direct reference still reaches another tenant’s order
Prepared + tenant-scoped 6 / 6 No issue in these six checks

Inspect every input and returned record. A PHP version upgrade does not replace these controls.

Where to start in your system

Identify the slow operation, data volume and peak workload. Establish its baseline, change the code and access pattern, then compare the same result.

What we did

  1. Business rule and data

    AIPrepared the synthetic workflow, tests and measurement automation.

    VerificationPublished code and raw outputs are available for review; this is not a client project.

  2. Implementation change

    AIReplace a full scan per customer with totals indexed by customer key. Business rules and integer-cent amounts remain identical.

    VerificationOutput equivalence was independently checked; every repetition is retained.