Runtime cost and optimization¶
This page answers a practical question: given that kits peak higher than element-plugin wrappers while a form is being built, is Form Factory Kits a reasonable choice at runtime, and can it be made cheaper? The measurements it relies on are on the Benchmarks page; read that page's Limits section first, because the same limits apply here.
What the numbers say¶
From the Benchmarks runs (28 October 2026, PHP 8.3.30, 500-field and 5,000-field forms):
| Form size | Option | Peak | Retained | Median build time |
|---|---|---|---|---|
| 500 fields | A bare arrays | 464.2 KiB | 455.8 KiB | 0.33–0.36 ms |
| 500 fields | B wrappers | 884.4 KiB | 883.7 KiB | 2.87–4.54 ms |
| 500 fields | C kits | 1,040.2 KiB | 549.7 KiB | 1.03–1.96 ms |
| 5,000 fields | A bare arrays | 4,382.7 KiB | 4,342.3 KiB | 1.86 ms |
| 5,000 fields | B wrappers | 8,651.0 KiB | 8,650.3 KiB | 26.29 ms |
| 5,000 fields | C kits | 10,111.9 KiB | 5,336.0 KiB | 28.67 ms |
Reading them for C against B:
- Peak memory is higher for kits (about 1.18× at 500 fields). The peak occurs while the kit objects and the finished array exist at the same time.
- Retained memory is lower for kits (about 0.62×). Once the build ends, the form is a plain array with no objects left in it. The wrapper form keeps its element objects.
- Build time on 500 fields is lower for kits (about 0.3–0.4× B in the three 28 October repeats). On 5,000 fields that run was within noise.
- Serialized size is lower for kits. The wrapper form serializes to 414.8 KiB against 147.4 KiB for A and C (details). This matters wherever a built form is stored, such as the form cache.
Is it suitable for runtime?¶
For ordinary forms, the measured cost is small in absolute terms: about 1 MB of transient peak and about 1–2 ms for a 500-field form (28 October 2026 C median 1.03–1.96 ms). The peak is released when the build finishes, and what stays resident (the plain array) is smaller than the wrapper alternative. On these measurements, memory at build time is not a reason to avoid kits for typical forms.
Two cautions apply, and neither can be resolved from the current data:
- The pipeline was not run. The benchmark ran on a partly booted core. FormBuilder, AJAX and the form cache were not exercised for any option, so the figures describe building the array, not serving a form request.
- Very large forms. At 5,000 fields kits peak at about 10 MB. That is unusual for a single form, but a site that builds forms of that size should measure its own case.
Kits also cannot wrap or alter an existing array in place, which options A and B can. That is a capability difference, not a cost one; see the Comparison.
Can it be optimized?¶
Probably, but nothing below has been tried. The benchmark shows that kits peak higher than wrappers, not why. These are hypotheses to test, in the order the evidence points to them.
- Key construction.
FormFactoryKit::getArray()builds each key by string concatenation ('#' . $parameter). A micro-test supported this as a cause of the larger final array, but it was not confirmed with a profiler. Storing parameters already prefixed would remove the concatenation. - Intermediate arrays.
getArray()creates a fresh array at each nesting level and merges children into it. Building the array in a single pass might reduce the intermediate copies that coexist at the peak. This is an untested guess about where the peak comes from. - Reusing built subtrees. A kit whose parameters have not changed could reuse its built array instead of rebuilding it.
- Releasing kit objects early. A kit could drop its children once its array is built. This would change how kits behave after building, so it is a last resort and would need to be treated as an API change.
How an optimization should be judged¶
Any change should be accepted only if all of the following hold:
- It is measured first, by splitting peak memory and time by build phase, so the work targets what the profile shows rather than a guess.
- The array it produces is byte-identical to today's output. The kit unit tests
and the A/C equality check in
docs/benchmarks/memory.phpguard this. - The benchmark is re-run with the same method and environment, and the new numbers are published on the Benchmarks page even if the gain is small or absent.
Until that work is done, the figures above are the module's current behavior.