Skip to content

Commit a6b6474

Browse files
JonasHaouziskafandri
authored andcommitted
Shift of 5MB not really applied when setting a memory limit (#417)
* Creating a MemoryConsumptionChecker saying if the RAM is almost overloaded * Using the MemoryConsumptionChecker to stop consuming messages when the RAM is almost overloaded * Adding new line at the end of new files (for future coding review ease) * Fixing the way to retrieve class name for backward compatibilities
1 parent 0bb11ed commit a6b6474

File tree

4 files changed

+131
-5
lines changed

4 files changed

+131
-5
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
namespace OldSound\RabbitMqBundle\MemoryChecker;
4+
5+
/**
6+
* Help handling memory limits .
7+
*
8+
* @author Jonas Haouzi <jonas@viscaweb.com>
9+
*/
10+
class MemoryConsumptionChecker
11+
{
12+
/** @var NativeMemoryUsageProvider */
13+
private $memoryUsageProvider;
14+
15+
/**
16+
* MemoryManager constructor.
17+
*
18+
* @param NativeMemoryUsageProvider $memoryUsageProvider
19+
*/
20+
public function __construct(NativeMemoryUsageProvider $memoryUsageProvider) {
21+
$this->memoryUsageProvider = $memoryUsageProvider;
22+
}
23+
24+
/**
25+
* @param int|string $allowedConsumptionUntil
26+
* @param int|string $maxConsumptionAllowed
27+
*
28+
* @return bool
29+
*/
30+
public function isRamAlmostOverloaded($allowedConsumptionUntil, $maxConsumptionAllowed)
31+
{
32+
$allowedConsumptionUntil = $this->convertHumanUnitToNumerical($allowedConsumptionUntil);
33+
$maxConsumptionAllowed = $this->convertHumanUnitToNumerical($maxConsumptionAllowed);
34+
$currentUsage = $this->convertHumanUnitToNumerical($this->memoryUsageProvider->getMemoryUsage());
35+
36+
return $currentUsage > ($maxConsumptionAllowed - $allowedConsumptionUntil);
37+
}
38+
39+
/**
40+
* @param int|string $humanUnit
41+
*
42+
* @return int
43+
*/
44+
private function convertHumanUnitToNumerical($humanUnit)
45+
{
46+
$numerical = $humanUnit;
47+
if (!is_numeric($humanUnit)) {
48+
$numerical = substr($numerical, 0, -1);
49+
switch (substr($humanUnit, -1)) {
50+
case 'G':
51+
$numerical *= pow(1024, 3);
52+
break;
53+
case 'M':
54+
$numerical *= pow(1024, 2);
55+
break;
56+
case 'K':
57+
$numerical *= 1024;
58+
break;
59+
}
60+
}
61+
62+
return (int)$numerical;
63+
}
64+
65+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace OldSound\RabbitMqBundle\MemoryChecker;
4+
5+
/**
6+
* Returns the current memory PHP is using (mainly used to allow mocking).
7+
*
8+
* @author Jonas Haouzi <jonas@viscaweb.com>
9+
*/
10+
class NativeMemoryUsageProvider
11+
{
12+
/**
13+
* @return int
14+
*/
15+
public function getMemoryUsage()
16+
{
17+
return memory_get_usage(true);
18+
}
19+
}

RabbitMq/Consumer.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
use OldSound\RabbitMqBundle\Event\AfterProcessingMessageEvent;
66
use OldSound\RabbitMqBundle\Event\BeforeProcessingMessageEvent;
77
use OldSound\RabbitMqBundle\Event\OnConsumeEvent;
8+
use OldSound\RabbitMqBundle\MemoryChecker\MemoryConsumptionChecker;
9+
use OldSound\RabbitMqBundle\MemoryChecker\NativeMemoryUsageProvider;
810
use PhpAmqpLib\Exception\AMQPTimeoutException;
911
use PhpAmqpLib\Message\AMQPMessage;
1012

@@ -164,10 +166,8 @@ protected function handleProcessMessage(AMQPMessage $msg, $processFlag)
164166
*/
165167
protected function isRamAlmostOverloaded()
166168
{
167-
if (memory_get_usage(true) >= ($this->getMemoryLimit() * 1024 * 1024)) {
168-
return true;
169-
} else {
170-
return false;
171-
}
169+
$memoryManager = new MemoryConsumptionChecker(new NativeMemoryUsageProvider());
170+
171+
return $memoryManager->isRamAlmostOverloaded($this->getMemoryLimit(), '5M');
172172
}
173173
}

Tests/Manager/MemoryCheckerTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace OldSound\RabbitMqBundle\Tests\Event;
4+
5+
use OldSound\RabbitMqBundle\MemoryChecker\MemoryConsumptionChecker;
6+
use OldSound\RabbitMqBundle\MemoryChecker\NativeMemoryUsageProvider;
7+
8+
/**
9+
* Class MemoryManagerTest
10+
*
11+
* @package OldSound\RabbitMqBundle\Tests\Manager
12+
*/
13+
class MemoryConsumptionCheckerTest extends \PHPUnit_Framework_TestCase
14+
{
15+
public function testMemoryIsNotAlmostOverloaded()
16+
{
17+
$currentMemoryUsage = '7M';
18+
$allowedConsumptionUntil = '2M';
19+
$maxConsumptionAllowed = '10M';
20+
21+
$memoryUsageProvider = $this->getMockBuilder('OldSound\\RabbitMqBundle\\MemoryChecker\\NativeMemoryUsageProvider')->getMock();
22+
$memoryUsageProvider->expects($this->any())->method('getMemoryUsage')->willReturn($currentMemoryUsage);
23+
24+
$memoryManager = new MemoryConsumptionChecker($memoryUsageProvider);
25+
26+
$this->assertFalse($memoryManager->isRamAlmostOverloaded($allowedConsumptionUntil, $maxConsumptionAllowed));
27+
}
28+
29+
public function testMemoryIsAlmostOverloaded()
30+
{
31+
$currentMemoryUsage = '9M';
32+
$allowedConsumptionUntil = '2M';
33+
$maxConsumptionAllowed = '10M';
34+
35+
$memoryUsageProvider = $this->getMockBuilder('OldSound\\RabbitMqBundle\\MemoryChecker\\NativeMemoryUsageProvider')->getMock();
36+
$memoryUsageProvider->expects($this->any())->method('getMemoryUsage')->willReturn($currentMemoryUsage);
37+
38+
$memoryManager = new MemoryConsumptionChecker($memoryUsageProvider);
39+
40+
$this->assertTrue($memoryManager->isRamAlmostOverloaded($allowedConsumptionUntil, $maxConsumptionAllowed));
41+
}
42+
}

0 commit comments

Comments
 (0)