Skip to content

Exponential analysis time with several int|float accumulators concatenated into a string in a loop (regression in 2.3.0) #15498

Closed
phpstan/phpstan-src
#6777

Description

@Miloslawsky

Bug report

Since 2.3.0, analysis time grows exponentially with the number of loop accumulators that start as int ($a = 0), have (float) added to them in an inner loop (so their type becomes int|float), and are then concatenated into a string with .= in the outer loop. On 2.2.17 the same file is analysed in a few seconds.

We hit this on a real 600-line view template with 26 such accumulators: 2.3.0 / 2.3.1 never finish (worker Child process timed out after 600 seconds), 2.2.17 analyses the whole project in ~80 s.

Reproduced with a bare PHAR, no config, no extensions: php phpstan.phar analyse -l max file.php.

┌──────────────┬────────┬─────────────────┐
│ accumulators │ 2.2.17 │      2.3.1      │
├──────────────┼────────┼─────────────────┤
│ 5            │ 5 s    │ 16 s            │
├──────────────┼────────┼─────────────────┤
│ 6            │ 6 s    │ 41 s            │
├──────────────┼────────┼─────────────────┤
│ 7            │ 6 s    │ > 90 s (killed) │
└──────────────┴────────┴─────────────────┘

Also slow on 2.3.x-dev@0b9a9d1 (2026-10-18): the 6-variable case takes ~30 s, and the real-world file still times out.

Things that make it fast again (7 variables, ~4 s):

  • initialising the accumulators as 0.0 instead of 0 (type stays float);
  • replacing $out .= "..." with a plain assignment $out = "...".

Replacing the interpolation with . concatenation ($out .= $a . ' ' . $b ...) is still slow, so it doesn't look specific to string interpolation.

Code snippet that reproduces the problem

<?php declare(strict_types = 1);

/** @param list<list<array<string, mixed>>> $pl */
function t(array $pl): string {
    $out = '';
    foreach ($pl as $rows) {
        $a = 0; $b = 0; $c = 0; $d = 0; $e = 0; $f = 0; $g = 0;
        foreach ($rows as $r) {
            $a = $a + (float) $r['a'];
            $b = $b + (float) $r['b'];
            $c = $c + (float) $r['c'];
            $d = $d + (float) $r['d'];
            $e = $e + (float) $r['e'];
            $f = $f + (float) $r['f'];
            $g = $g + (float) $r['g'];
        }
        $out .= "$a $b $c $d $e $f $g";
    }
    return $out;
}

(Remove variables to see the curve: 5 → 16 s, 6 → 41 s on 2.3.1.)

Code snippet that reproduces the problem

<?php declare(strict_types = 1);

/** @param list<list<array<string, mixed>>> $pl */
function t(array $pl): string {
    $out = '';
    foreach ($pl as $rows) {
        $a = 0; $b = 0; $c = 0; $d = 0; $e = 0; $f = 0; $g = 0;
        foreach ($rows as $r) {
            $a = $a + (float) $r['a'];
            $b = $b + (float) $r['b'];
            $c = $c + (float) $r['c'];
            $d = $d + (float) $r['d'];
            $e = $e + (float) $r['e'];
            $f = $f + (float) $r['f'];
            $g = $g + (float) $r['g'];
        }
        $out .= "$a $b $c $d $e $f $g";
    }
    return $out;
}

Expected output

Analysis finishes in roughly the same time as on 2.2.17 (a few seconds), regardless of the number of accumulators.

Did PHPStan help you today? Did it make you happy in any way?

Very much: level 10 across a 3000-file legacy Yii2 project, and 2.3.1 is ~2.8× faster than 2.2.17 on the full project once this pattern is worked around. Thank you!

Environment: PHP 8.5.11, Linux, PHPStan 2.3.1 PHAR.

Activity

  1. mergeable commented on Oct 18, 2026

    @mergeable

    This bug report is missing a link to reproduction at phpstan.org/try.

    It will most likely be closed after manual review.

  2. mariusTestcard commented on Oct 21, 2026

    @mariusTestcard

    I get performance issues as well

    Image
  3. ondrejmirtes commented on Oct 21, 2026

    @ondrejmirtes
    Member
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions