Skip to content

Let tally accept replace a preset complexity class that the growth no longer fits - #8

Merged
ondrejmirtes merged 2 commits into
1.xfrom
accept-complexity-presets
Nov 14, 2026
Merged

ondrejmirtes merged 2 commits into
1.xfrom
accept-complexity-presets

Conversation

@ondrejmirtes

@ondrejmirtes ondrejmirtes commented Nov 14, 2026 •

Copy link
Copy Markdown
Member

A benchmark compared by its growth had nothing for tally accept to write: a slower case meant editing the attribute by hand. Accept now fits the measured instructions of a method's data sets against the presets and writes the lowest one they grow within, as tally run compares them.

slower  App\PairsBench::benchPairs: O(n) to O(n^2)

Accepted the complexity class of 1 benchmark.
  • Up when the instructions grew more than the class allows, such as #[Constant] to #[Logarithmic], down when a lower preset bounds them too, such as #[Linear] to #[Logarithmic] (listed as faster).
  • Order: Constant, Logarithmic, Linear, Linearithmic, Quadratic, Polynomial 3, 4, …, Exponential. The size argument stays as written; the import of the replaced class goes when nothing else uses it.
  • The replacement is a set of CodeEdits in the file's AttributeIndex, like the expectations since 5ed6578, so a file with both is rewritten in one pass. The new import takes the place of the removed one when it sorts there.
  • Classes are compared at the measured sizes only, so #[Exponential] comes before a preset that allows more growth at the largest data set. Otherwise any growth would fit some high-degree polynomial.
  • A class that grows exactly like the current one keeps it (#[Polynomial(degree: 1)] stays). #[Complexity] with its own formula is left alone.
  • A method no preset bounds is reported: Cannot accept App\FooBench::benchFoo: no preset complexity class bounds how its instructions grow, write a #[Complexity] that does. The other changes are still written, and accept exits with 2.
  • The report now suggests accepting a slower growth case instead of loosening the class, and shows the accept command for it.

PresetFitTest covers each neighbouring pair of presets, up and down. CompareAndAcceptCommandTest runs accept end to end on a fixture.

Checks: lint, cs, PHPStan, tests, 100 % coverage, and Infection on the changed files at 100 % MSI pass locally. make bench was not run; ExpectationChanges::plan() changed, so the Benchmarks job may report new numbers.

Known limitation: accept with --filter fits the class to the selected data sets only.

… longer fits

A benchmark compared by its growth had nothing for tally accept to write, so a
slower case meant editing the attribute by hand and guessing the class. Accept
now fits the measured instructions of a method's data sets against the presets
and writes the lowest one they grow within, as tally run compares them: up when
they grew more than the class allows, such as #[Constant] to #[Logarithmic],
down when a lower preset bounds them too, such as #[Linear] to #[Logarithmic].
The size argument stays as written, and the import of the replaced class goes
when nothing else uses it.

Classes are compared at the measured sizes only, so #[Exponential] comes before
a preset that allows more growth at the largest data set; otherwise any growth
would fit some high-degree polynomial. A #[Complexity] with its own formula is
left alone, and a method no preset bounds is reported.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1d9f0-e845-746f-86dc-7977af8ab66d
@ondrejmirtes
ondrejmirtes force-pushed the accept-complexity-presets branch from b9c953a to 3c0a908 Compare November 14, 2026 21:13
…replacement

The Benchmarks job measured index() 44 % slower and planning 2.5 % slower with
68 % more memory: indexing counted every name of the file and read the size
argument of every attribute, and plan() built a closure per case. Now the index
only records where a method's other attributes are, accept tokenizes the one
complexity attribute it replaces and looks for other uses of its import then,
and complexity changes get a loop of their own. Locally under CodSpeed the
benchmarks are within 0.6 % of instructions and 1.1 % of memory of 1.x.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1d9f0-e845-746f-86dc-7977af8ab66d
@ondrejmirtes
ondrejmirtes merged commit cfe29ad into 1.x Nov 14, 2026
30 checks passed
@ondrejmirtes
ondrejmirtes deleted the accept-complexity-presets branch November 14, 2026 22:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant