Skip to content

Commit 7a5932a

Browse files
committed
add WorkerMemoryUsageSubscriber
1 parent 2be9595 commit 7a5932a

2 files changed

Lines changed: 98 additions & 0 deletions

File tree

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WonderNetwork\SlimKernel\Messenger;
6+
7+
use Psr\Log\LoggerInterface;
8+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
9+
use Symfony\Component\Messenger\Event\WorkerRunningEvent;
10+
11+
final class WorkerMemoryUsageSubscriber implements EventSubscriberInterface {
12+
private int $memoryUsage;
13+
14+
/**
15+
* @return iterable<string,string>
16+
*/
17+
public static function getSubscribedEvents(): iterable {
18+
return [
19+
WorkerRunningEvent::class => 'onWorkerRunning',
20+
];
21+
}
22+
23+
public function __construct(
24+
private readonly LoggerInterface $logger,
25+
private readonly int $cutoff = 1024,
26+
) {
27+
$this->memoryUsage = memory_get_usage();
28+
}
29+
30+
public function onWorkerRunning(): void {
31+
$currentUsage = memory_get_usage();
32+
33+
$difference = abs($this->memoryUsage - $currentUsage);
34+
if ($difference < $this->cutoff) {
35+
return;
36+
}
37+
38+
$this->logger->debug(
39+
"Memory usage changed: {current} ({sign}{difference})",
40+
[
41+
'current' => $this->formatBytes($currentUsage),
42+
'sign' => ($this->memoryUsage > $currentUsage) ? "-" : "+",
43+
'difference' => $this->formatBytes($difference),
44+
],
45+
);
46+
47+
$this->memoryUsage = $currentUsage;
48+
}
49+
50+
private function formatBytes(int $bytes): string {
51+
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
52+
53+
$bytes = max($bytes, 0);
54+
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
55+
$pow = (int) min($pow, count($units) - 1);
56+
57+
$bytes /= 1024 ** $pow;
58+
59+
return sprintf("%s %s", round($bytes, 2), $units[$pow]);
60+
}
61+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WonderNetwork\SlimKernel\Messenger;
6+
7+
use Monolog\Handler\TestHandler;
8+
use Monolog\Logger;
9+
use PHPUnit\Framework\TestCase;
10+
11+
final class WorkerMemoryUsageSubscriberTest extends TestCase {
12+
public function testReportsAboveCutoff(): void {
13+
$buffer = new TestHandler();
14+
$logger = new Logger('some');
15+
$logger->pushHandler($buffer);
16+
$memoryLeak = [];
17+
18+
$sut = new WorkerMemoryUsageSubscriber($logger, cutoff: 10 * 1024);
19+
$sut->onWorkerRunning();
20+
self::assertEmpty($buffer->getRecords());
21+
22+
$memoryLeak[] = str_repeat(' ', 10 * 1024);
23+
// triggers the first log
24+
$sut->onWorkerRunning();
25+
self::assertCount(1, $buffer->getRecords());
26+
// the logs themselves take memory, so:
27+
$sut->onWorkerRunning();
28+
self::assertCount(2, $buffer->getRecords());
29+
// no more logs:
30+
$sut->onWorkerRunning();
31+
$sut->onWorkerRunning();
32+
$sut->onWorkerRunning();
33+
self::assertCount(2, $buffer->getRecords());
34+
35+
unset($memoryLeak);
36+
}
37+
}

0 commit comments

Comments
 (0)