Skip to content

Commit c9ae116

Browse files
committed
FNSR - Fiber pool
1 parent 32e29e0 commit c9ae116

3 files changed

Lines changed: 34 additions & 7 deletions

File tree

src/Analyser/ExpressionResultStorage.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
namespace PHPStan\Analyser;
44

55
use Fiber;
6+
use PhpParser\Node;
67
use PhpParser\Node\Expr;
78
use PHPStan\Analyser\Fiber\BeforeScopeForExprRequest;
9+
use PHPStan\Analyser\Fiber\ParkFiberRequest;
810
use SplObjectStorage;
911

1012
final class ExpressionResultStorage
@@ -13,9 +15,12 @@ final class ExpressionResultStorage
1315
/** @var SplObjectStorage<Expr, Scope> */
1416
private SplObjectStorage $scopes;
1517

16-
/** @var array<array{fiber: Fiber<mixed, Scope, null, BeforeScopeForExprRequest>, request: BeforeScopeForExprRequest}> */
18+
/** @var array<array{fiber: Fiber<mixed, Scope|array{callable(Node $node, Scope $scope): void, Node, Scope}, null, BeforeScopeForExprRequest|ParkFiberRequest>, request: BeforeScopeForExprRequest}> */
1719
public array $pendingFibers = [];
1820

21+
/** @var list<Fiber<mixed, Scope|array{callable(Node $node, Scope $scope): void, Node, Scope}, null, BeforeScopeForExprRequest|ParkFiberRequest>> */
22+
public array $parkedFibers = [];
23+
1924
public function __construct()
2025
{
2126
$this->scopes = new SplObjectStorage();

src/Analyser/Fiber/FiberNodeScopeResolver.php

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
use PHPStan\Analyser\Scope;
1212
use PHPStan\DependencyInjection\AutowiredService;
1313
use PHPStan\ShouldNotHappenException;
14+
use function array_pop;
15+
use function count;
1416
use function get_debug_type;
1517

1618
#[AutowiredService(as: FiberNodeScopeResolver::class)]
@@ -31,20 +33,28 @@ protected function callNodeCallback(
3133
$nodeCallback($node, $scope->toFiberScope());
3234
return;
3335
}
34-
$fiber = new Fiber(static function () use ($node, $scope, $nodeCallback) {
35-
$nodeCallback($node, $scope->toFiberScope());
36-
});
37-
$request = $fiber->start();
36+
if (count($storage->parkedFibers) > 0) {
37+
$fiber = array_pop($storage->parkedFibers);
38+
$request = $fiber->resume([$nodeCallback, $node, $scope]);
39+
} else {
40+
$fiber = new Fiber(static function () use ($node, $scope, $nodeCallback) {
41+
while (true) { // @phpstan-ignore while.alwaysTrue
42+
$nodeCallback($node, $scope->toFiberScope());
43+
[$nodeCallback, $node, $scope] = Fiber::suspend(new ParkFiberRequest());
44+
}
45+
});
46+
$request = $fiber->start();
47+
}
3848
$this->runFiberForNodeCallback($storage, $fiber, $request);
3949
}
4050

4151
/**
42-
* @param Fiber<mixed, Scope, null, BeforeScopeForExprRequest> $fiber
52+
* @param Fiber<mixed, Scope|array{callable(Node $node, Scope $scope): void, Node, Scope}, null, BeforeScopeForExprRequest|ParkFiberRequest> $fiber
4353
*/
4454
private function runFiberForNodeCallback(
4555
ExpressionResultStorage $storage,
4656
Fiber $fiber,
47-
?BeforeScopeForExprRequest $request,
57+
BeforeScopeForExprRequest|ParkFiberRequest|null $request,
4858
): void
4959
{
5060
while (!$fiber->isTerminated()) {
@@ -61,6 +71,10 @@ private function runFiberForNodeCallback(
6171
];
6272
return;
6373
}
74+
if ($request instanceof ParkFiberRequest) {
75+
$storage->parkedFibers[] = $fiber;
76+
return;
77+
}
6478

6579
throw new ShouldNotHappenException(
6680
'Unknown fiber suspension: ' . get_debug_type($request),
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser\Fiber;
4+
5+
final class ParkFiberRequest
6+
{
7+
8+
}

0 commit comments

Comments
 (0)