ããã«ã¡ã¯ãHabrïŒã«ã«ãã¯ãããªããŒã®èšäºã®äžã§ã®äžæ³šæãªã³ã¡ã³ãã®ããã«ææ°ŽãããŸãããã€ãŸããè峿·±ãïŒç§ã¯é¡ã£ãŠããŸãïŒæçš¿ãæžããŠãèªåèªèº«ããªãããªããå¿ èŠããããŸãã
ç§ã¯æ°å¹Žéãphpã§ãã¬ã°ã©ã ãµãŒããŒã¯ã©ã€ã¢ã³ãã䜿çšããŠããŸãããããŠãå€ãã®ãŠãŒã¶ãŒã®ããã«ãã¡ã¢ãªæ¶è²»éã®çµ¶ãéãªãå¢å ã«ããããããŠããŸããäžéšã®ã»ãã·ã§ã³ã§ã¯ã1ã8ã®ã¬ãã€ãã®RAMãå¿ èŠã«ãªãå ŽåããããŸããããŒã¿ããŒã¹ã®ãµããŒãã¯é·ãéçŽæãããŠããŸãããããã®æ¹åãžã®é²å±ã¯ãããŸããã§ãããç§ã¯èªåã§åé¡ã解決ããªããã°ãªããŸããã§ãã:)ãªãŒãã³ãœãŒã¹ãããžã§ã¯ãã®äººæ°ã¯ãã«ãªã¯ãšã¹ãã«è峿·±ãèŠä»¶ã課ããŸããïŒ
- åŸæ¹äºææ§ãæ¢åã®ãã¹ãŠã®ã»ãã·ã§ã³ã¯ãæ°ããããŒãžã§ã³ã§ãåŒãç¶ãæ©èœããå¿ èŠããããŸãïŒã»ãã·ã§ã³ã¯ããã¡ã€ã«å ã®ã¢ããªã±ãŒã·ã§ã³ã®ã·ãªã¢ã«åãããã€ã³ã¹ã¿ã³ã¹ã§ãïŒã
- ããŒã¿ããŒã¹ã®éžæã®èªç±ããŠãŒã¶ãŒã¯ç°å¢ã®æ§æãç°ãªããããããŒã¿ã倱ãããšãªãããã€ã§ãã¹ãã¬ãŒãžã¿ã€ãã倿Žããæ©èœã
- æ¡åŒµæ§ãæ°ããã¿ã€ãã®ããŒã¿ããŒã¹ã®è¿œå ã®ããããã
- ã€ã³ã¿ãŒãã§ã€ã¹ãä¿åããŸããããŒã¿ãæäœããã¢ããªã±ãŒã·ã§ã³ã³ãŒãã¯å€æŽããªãã§ãã ããã
- éåæããããžã§ã¯ãã¯amphpã䜿çšããããããã¹ãŠã®ããŒã¿ããŒã¹æäœã¯éããããã³ã°ã§ããå¿ èŠããããŸãã
詳ããã¯ç«ã®äžã®ã¿ããªãæåŸ ããŸãã
äœã転éããŸãã
MadelineProtoã®ã¡ã¢ãªã®ã»ãšãã©ã¯ããã£ããããŠãŒã¶ãŒãããã³ãã¡ã€ã«ã«ãã£ãŠå ããããŠããŸããããšãã°ããã¢ãã£ãã·ã¥ã«ã¯ã2äžãè¶ ãããšã³ããªããããŸãããããã¯ãã¢ã«ãŠã³ãããããŸã§ã«èŠããã¹ãŠã®ãŠãŒã¶ãŒïŒãã¹ãŠã®ã°ã«ãŒãã®ã¡ã³ããŒãå«ãïŒãããã³ãã£ãã«ãããããã°ã«ãŒãã§ããã¢ã«ãŠã³ããå€ããã¢ã¯ãã£ãã§ããã»ã©ãããå€ãã®ããŒã¿ãã¡ã¢ãªã«ä¿åãããŸãããããã¯æ°åã¡ã¬ãã€ããšæ°çŸã¡ã¬ãã€ãã§ããããããã®ã»ãšãã©ã¯äœ¿çšãããŠããŸããããã ããåãããŒã¿ãè€æ°ååä¿¡ããããšãããšããã¬ã°ã©ã ã«ãã£ãŠã¢ã«ãŠã³ããããã«å³ããå¶éãããããããã£ãã·ã¥å šäœãã¯ãªã¢ããããšã¯ã§ããŸãããããšãã°ããããªãã¯ãã¢ãµãŒããŒã§ã»ãã·ã§ã³ãåäœæããåŸã1é±é以å ã®é»å ±ã¯ãã»ãšãã©ã®ãªã¯ãšã¹ãã«FLOOD_WAITãšã©ãŒã§å¿çããå®éã«ã¯äœãæ©èœããŸããã§ããããã£ãã·ã¥ããŠã©ãŒã ã¢ããããåŸããã¹ãŠãæ£åžžã«æ»ããŸããã
ã³ãŒãã®èгç¹ããããã®ããŒã¿ã¯ã¯ã©ã¹ã®ãã¢ã®ããããã£ã«é åãšããŠæ ŒçŽãããŸãã
建ç¯
èŠä»¶ã«åºã¥ããŠãã¹ããŒã ãçãŸããŸããã
- ãã¹ãŠã®ãéããé åã¯ãArrayAccessãå®è£ ãããªããžã§ã¯ãã«çœ®ãæããããŸãã
- ããŒã¿ããŒã¹ã®çš®é¡ããšã«ãåºæ¬ã¯ã©ã¹ãç¶æ¿ããç¬èªã®ã¯ã©ã¹ãäœæããŸãã
- ãªããžã§ã¯ãã¯ã__ consrtuctããã³__awakeäžã«äœæãããããããã£ã«æžã蟌ãŸããŸãã
- æœè±¡ãã¡ã¯ããªã¯ãã¢ããªã±ãŒã·ã§ã³èšå®ã§éžæãããããŒã¿ããŒã¹ã«å¿ããŠããªããžã§ã¯ãã«å¿ èŠãªã¯ã©ã¹ãéžæããŸãã
- ã¢ããªã±ãŒã·ã§ã³ã«ãã§ã«å¥ã®ã¿ã€ãã®ã¹ãã¬ãŒãžãããå Žåã¯ããããããã¹ãŠã®ããŒã¿ãèªã¿åããã¢ã¬ã€ãæ°ããã¹ãã¬ãŒãžã«æžã蟌ã¿ãŸãã
éåæã®äžçã®åé¡
ç§ãæåã«ããããšã¯ãã¡ã¢ãªã«é åãæ ŒçŽããããã®ã€ã³ã¿ãŒãã§ã€ã¹ãšã¯ã©ã¹ãäœæããããšã§ãããããã¯ããã©ã«ãã§ãããåäœã¯å€ãããŒãžã§ã³ã®ããã°ã©ã ãšåãã§ããæåã®å€ãç§ã¯ãããã¿ã€ãã®æåã«éåžžã«è奮ããŸãããã³ãŒãã¯çŽ æŽããããã·ã³ãã«ã§ããããããŸã§ã®ãšãããIteratorã€ã³ã¿ãŒãã§ãŒã¹ã®ã¡ãœããå ãããã³unsetãšissetãæ åœããã¡ãœããå ã§ãžã§ãã¬ãŒã¿ãŒã䜿çšã§ããªãããšã¯çºèŠãããŠããŸããã
ããã§ãamphpããžã§ãã¬ãŒã¿ãŒæ§æã䜿çšããŠphpã«éåæãå®è£ ããããšãæç¢ºã«ããå¿ èŠããããŸããæ©çãŸãã¯éåæã«é¡äŒŒããããã«ãªããŸã... jsããåŸ ã¡ãŸããã¡ãœãããéåæã䜿çšããå Žåããã®ã¡ãœããããçµæãååŸããã«ã¯ãyieldã䜿çšããŠã³ãŒãã§ãã®çµæãåŸ ã€å¿ èŠããããŸããäŸãã°ïŒ
<?php
include 'vendor/autoload.php';
$MadelineProto = new \danog\MadelineProto\API('session.madeline');
$MadelineProto->async(true);
$MadelineProto->loop(function() use($MadelineProto) {
$myAsyncFunction = function() use($MadelineProto): \Generator {
$me = yield $MadelineProto->start();
yield $MadelineProto->echo(json_encode($me, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE));
};
yield $myAsyncFunction();
});
æååããã®å Žå
yield $myAsyncFunction();ã€ãŒã«ããåé€ãããšããã®ã³ãŒããå®è¡ãããåã«ã¢ããªã±ãŒã·ã§ã³ãçµäºããŸããçµæã¯åŸãããŸããã
ã¡ãœããã颿°ãåŒã³åºãåã«yieldã远å ããããšã¯ããã»ã©é£ãããããŸããããã ããArrayAccessã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããããããã¡ãœããã¯çŽæ¥åŒã³åºãããŸãããããšãã°ãunsetïŒïŒã¯offsetUnsetïŒïŒãåŒã³åºããissetïŒïŒã¯offsetIssetïŒïŒãåŒã³åºããŸãã Iteratorã€ã³ã¿ãŒãã§ãŒã¹ã䜿çšããå Žåãforeachã€ãã¬ãŒã¿ãŒã®å Žåãç¶æ³ã¯äŒŒãŠããŸãã
çµã¿èŸŒã¿ã¡ãœããã®åã«yieldã远å ãããšããããã®ã¡ãœããã¯ãžã§ãã¬ãŒã¿ãŒã§åäœããããã«èšèšãããŠããªãããããšã©ãŒãçºçããŸããã³ã¡ã³ãã§ããå°ãïŒãããšããã
èªåã®ã¡ãœããã䜿çšããã«ã¯ãã³ãŒãã劥åããŠæžãçŽãå¿ èŠããããŸããã幞ããªããšã«ããã®ãããªå Žæã¯ã»ãšãã©ãããŸããã§ãããã»ãšãã©ã®å ŽåãããŒã«ããèªã¿åããŸãã¯æžã蟌ã¿ã«ã¯é åã䜿çšãããŠããŸããããã®æ©èœã¯ããžã§ãã¬ãŒã¿ãŒãšçŽ æŽãããåéã«ãªããŸããã
çµæã®ã€ã³ã¿ãŒãã§ã€ã¹ã¯æ¬¡ã®ãšããã§ãã
<?php
use Amp\Producer;
use Amp\Promise;
interface DbArray extends DbType, \ArrayAccess, \Countable
{
public function getArrayCopy(): Promise;
public function isset($key): Promise;
public function offsetGet($offset): Promise;
public function offsetSet($offset, $value);
public function offsetUnset($offset): Promise;
public function count(): Promise;
public function getIterator(): Producer;
/**
* @deprecated
* @internal
* @see DbArray::isset();
*
* @param mixed $offset
*
* @return bool
*/
public function offsetExists($offset);
}
ããŒã¿ã®æäœäŸ
<?php
...
//
$existingChat = yield $this->chats[$user['id']];
//.
yield $this->chats[$user['id']] = $user;
// yield, .
$this->chats[$user['id']] = $user;
//unset
yield $this->chats->offsetUnset($id);
//foreach
$iterator = $this->chats->getIterator();
while (yield $iterator->advance()) {
[$key, $value] = $iterator->getCurrent();
//
}
ããŒã¿ã¹ãã¬ãŒãž
ããŒã¿ãä¿åããæãç°¡åãªæ¹æ³ã¯ã·ãªã¢ã«åãããŠããŸãããªããžã§ã¯ãããµããŒãããããã«ãjsonã®äœ¿çšãæå¿µããªããã°ãªããŸããã§ããããã®ããŒãã«ã«ã¯ãããŒãšå€ã®2ã€ã®äž»èŠãªåããããŸãã
ããŒãã«ãäœæããããã®sqlã¯ãšãªã®äŸïŒ
CREATE TABLE IF NOT EXISTS `{$this->table}`
(
`key` VARCHAR(255) NOT NULL,
`value` MEDIUMBLOB NULL,
`ts` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`key`)
)
ENGINE = InnoDB
CHARACTER SET 'utf8mb4'
COLLATE 'utf8mb4_general_ci'
ã¢ããªã±ãŒã·ã§ã³ãèµ·åãããã³ã«ãããããã£ããšã«ããŒãã«ãäœæããããšããŸãããã¬ã°ã©ã ã¯ã©ã€ã¢ã³ãã¯ãæ°æéã«1å以äžåèµ·åããããšã¯ãå§ãããŸããããã®ããã1ç§ãããã«ããŒãã«ãäœæããããã®è€æ°ã®ãªã¯ãšã¹ãã¯ãããŸãã:)
ãã©ã€ããªããŒã¯èªåã€ã³ã¯ãªã¡ã³ããããªããããããŒã¿ã®æ¿å ¥ãšæŽæ°ã¯ãéåžžã®é åã®ããã«1ã€ã®ã¯ãšãªã§å®è¡ã§ããŸãã
INSERT INTO `{$this->table}`
SET `key` = :index, `value` = :value
ON DUPLICATE KEY UPDATE `value` = :value
ïŒ account_idïŒ _ïŒ classïŒ _ïŒ variable_nameïŒ ã®åœ¢åŒã®ååãæã€ããŒãã«ã倿°ããšã«äœæãããŸãããã ããæåã«ã¢ããªã±ãŒã·ã§ã³ãèµ·åãããšãã¯ããŸã ã¢ã«ãŠã³ãããããŸããããã®å Žåãtmpãã¬ãã£ãã¯ã¹ã䜿çšããŠã©ã³ãã ãªäžæIDãçæããå¿ èŠããããŸããèµ·åãããã³ã«ãå倿°ã®ã¯ã©ã¹ã¯ã¢ã«ãŠã³ãIDã衚瀺ãããŠãããã©ããã確èªããŸããidãååšããå ŽåãããŒãã«ã®ååã倿ŽãããŸãã
ã€ã³ããã¯ã¹
ããŒã¿ããŒã¹ã®æ§é ã¯å¯èœãªéãåçŽã§ãããããå°æ¥ãæ°ããããããã£ãèªåçã«è¿œå ãããŸããæ¥ç¶ã¯ãããŸãããPRIMARYããŒã€ã³ããã¯ã¹ã®ã¿ã䜿çšãããŸãããã ããä»ã®ãã£ãŒã«ãã§æ€çŽ¢ããå¿ èŠãããå ŽåããããŸãã
ããšãã°ãé å/ããŒãã«ãã£ããããããŸãããã®äžã®éµã¯ãã£ããIDã§ããããããå€ãã®å ŽåããŠãŒã¶ãŒåã§æ€çŽ¢ããå¿ èŠããããŸããã¢ããªã±ãŒã·ã§ã³ãããŒã¿ãé åã«æ ŒçŽããŠãããšãããŠãŒã¶ãŒåã«ããæ€çŽ¢ã¯ãforeachã§é åãå埩ããããšã«ãã£ãŠéåžžã©ããå®è¡ãããŸããããã®æ€çŽ¢ã¯ãã¡ã¢ãªã§ã¯èš±å®¹å¯èœãªéåºŠã§æ©èœããŸããããããŒã¿ããŒã¹ã§ã¯æ©èœããŸããã§ããããããã£ãŠãå¥ã®ããŒãã«/é åãäœæãããã¯ã©ã¹å ã®å¯Ÿå¿ããããããã£ãäœæãããŸãããããŒã¯ãŠãŒã¶ãŒåãå€ã¯ãã£ããIDã§ãããã®ã¢ãããŒãã®å¯äžã®æ¬ ç¹ã¯ã2ã€ã®ããŒãã«ãåæããããã«è¿œå ã®ã³ãŒããäœæããå¿ èŠãããããšã§ãã
ãã£ãã·ã³ã°
ããŒã«ã«mysqlã¯é«éã§ãããå°ãã®ãã£ãã·ã¥ã§åé¡ãçºçããããšã¯ãããŸãããç¹ã«ãåãå€ãé£ç¶ããŠè€æ°å䜿çšãããå Žåãããšãã°ãæåã«ããŒã¿ããŒã¹å ã®ãã£ããã®ååšã確èªããŠãããããããããŒã¿ãååŸããŸãã
ç°¡åãª
<?php
namespace danog\MadelineProto\Db;
use Amp\Loop;
use danog\MadelineProto\Logger;
trait ArrayCacheTrait
{
/**
* Values stored in this format:
* [
* [
* 'value' => mixed,
* 'ttl' => int
* ],
* ...
* ].
* @var array
*/
protected array $cache = [];
protected string $ttl = '+5 minutes';
private string $ttlCheckInterval = '+1 minute';
protected function getCache(string $key, $default = null)
{
$cacheItem = $this->cache[$key] ?? null;
$result = $default;
if (\is_array($cacheItem)) {
$result = $cacheItem['value'];
$this->cache[$key]['ttl'] = \strtotime($this->ttl);
}
return $result;
}
/**
* Save item in cache.
*
* @param string $key
* @param $value
*/
protected function setCache(string $key, $value): void
{
$this->cache[$key] = [
'value' => $value,
'ttl' => \strtotime($this->ttl),
];
}
/**
* Remove key from cache.
*
* @param string $key
*/
protected function unsetCache(string $key): void
{
unset($this->cache[$key]);
}
protected function startCacheCleanupLoop(): void
{
Loop::repeat(\strtotime($this->ttlCheckInterval, 0) * 1000, fn () => $this->cleanupCache());
}
/**
* Remove all keys from cache.
*/
protected function cleanupCache(): void
{
$now = \time();
$oldKeys = [];
foreach ($this->cache as $cacheKey => $cacheValue) {
if ($cacheValue['ttl'] < $now) {
$oldKeys[] = $cacheKey;
}
}
foreach ($oldKeys as $oldKey) {
$this->unsetCache($oldKey);
}
Logger::log(
\sprintf(
"cache for table:%s; keys left: %s; keys removed: %s",
$this->table,
\count($this->cache),
\count($oldKeys)
),
Logger::VERBOSE
);
}
}
startCacheCleanupLoopã«ç¹ã«æ³šæãæããããšæããŸãã amphpã®éæ³ã®ãããã§ããã£ãã·ã¥ã®ç¡å¹åã¯å¯èœãªéãç°¡åã§ããã³ãŒã«ããã¯ã¯æå®ãããééã§éå§ãããã¹ãŠã®å€ãã«ãŒãããŠããã®èŠçŽ ãžã®æåŸã®åŒã³åºãã®ã¿ã€ã ã¹ã¿ã³ããæ ŒçŽããtsãã£ãŒã«ãã調ã¹ãŸããåŒã³åºãã5å以äžåïŒèšå®ã§æ§æå¯èœïŒã§ãã£ãå ŽåãèŠçŽ ã¯åé€ãããŸãã amphpã䜿çšããŠredisãŸãã¯memcacheããttlã¢ããã°ãå®è£ ããã®ã¯éåžžã«ç°¡åã§ããããã¯ãã¹ãŠããã¯ã°ã©ãŠã³ãã§çºçããã¡ã€ã³ã¹ã¬ããããããã¯ããŸããã
ãã£ãã·ã¥ãšéåææ§ã®å©ããåããŠãèªã¿åãã ãã§ãªãæžã蟌ã¿ãé«éåãããŸãã
ããŒã¿ããŒã¹ã«ããŒã¿ãæžã蟌ãã¡ãœããã®ãœãŒã¹ã³ãŒãã¯æ¬¡ã®ãšããã§ãã
/**
* Set value for an offset.
*
* @link https://php.net/manual/en/arrayiterator.offsetset.php
*
* @param string $index <p>
* The index to set for.
* </p>
* @param $value
*
* @throws \Throwable
*/
public function offsetSet($index, $value): Promise
{
if ($this->getCache($index) === $value) {
return call(fn () =>null);
}
$this->setCache($index, $value);
$request = $this->request(
"
INSERT INTO `{$this->table}`
SET `key` = :index, `value` = :value
ON DUPLICATE KEY UPDATE `value` = :value
",
[
'index' => $index,
'value' => \serialize($value),
]
);
//Ensure that cache is synced with latest insert in case of concurrent requests.
$request->onResolve(fn () => $this->setCache($index, $value));
return $request;
}
$ this->ãªã¯ãšã¹ãã¯ãããŒã¿ãéåæã«æžã蟌ãPromiseãäœæããŸãããŸãããã£ãã·ã¥ã䜿çšããæäœã¯åæããŠè¡ãããŸããã€ãŸããããŒã¿ããŒã¹ãžã®æžã蟌ã¿ãåŸ ã€ããšã¯ã§ããŸãããåæã«ãèªã¿åãæäœãããã«æ°ããããŒã¿ãè¿ãå§ããããšã確èªããŠãã ããã
amphpã®onResolveã¡ãœããã¯éåžžã«äŸ¿å©ã§ããããšãããããŸãããæ¿å ¥ãå®äºãããšãããŒã¿ã¯åã³ãã£ãã·ã¥ã«æžã蟌ãŸããŸããäžéšã®æžãèŸŒã¿æäœãé ãããã£ãã·ã¥ãšããŒã¹ãç°ãªãå§ããå Žåããã£ãã·ã¥ã¯æåŸã«ããŒã¹ã«æžã蟌ãŸããå€ã§æŽæ°ãããŸãããããããã£ãã·ã¥ã¯åã³ããŒã¹ãšäžèŽããããã«ãªããŸãã
ãœãŒã¹
âãã«ãªã¯ãšã¹ããžã®ãªã³ã¯
ãããŠããã®ããã«å¥ã®ãŠãŒã¶ãŒãpostgreã®ãµããŒãã远å ããŸããããã®ããã®æç€ºãæžãã®ã«ãã£ã5åããããããŸããã§ããã
éè€ããã¡ãœãããäžè¬çãªæœè±¡ã¯ã©ã¹SqlArrayã«ç§»åããããšã§ãã³ãŒãã®éãæžããããšãã§ããŸãã
ããäžã€
ãã¬ã°ã©ã ããã¡ãã£ã¢ãã¡ã€ã«ãããŠã³ããŒãããŠããéãæšæºã®ã¬ããŒãžã³ã¬ã¯ã¿ãŒphpã¯äœæ¥ã«å¯Ÿå¿ããããã¡ã€ã«ã®äžéšãã¡ã¢ãªã«æ®ã£ãŠããããšã«æ°ã¥ããŸãããéåžžããªãŒã¯ã¯ãã¡ã€ã«ãšåããµã€ãºã§ãããèããããåå ïŒ10,000åã®ãªã³ã¯ãèç©ããããšãã¬ããŒãžã³ã¬ã¯ã¿ãŒãèªåçã«ããªã¬ãŒãããŸããç§ãã¡ã®å Žåããªã³ã¯ã¯æ°ïŒæ°åïŒã§ãããããããããã¡ã¢ãªå ã®ã¡ã¬ãã€ãã®ããŒã¿ãåç §ããå¯èœæ§ããããŸãã mtprotoã®å®è£ ã§æ°åè¡ã®ã³ãŒããç ç©¶ããã®ã¯éåžžã«æ æ°ã§ãããæåã«\ gc_collect_cyclesïŒïŒ;ã§ãšã¬ã¬ã³ããªã¯ã©ããã詊ããŠã¿ãŸãããïŒ
é©ããããšã«ãããã¯åé¡ã解決ããŸãããããã¯ã宿çãªã¯ãªãŒãã³ã°ã®éå§ãæ§æããã ãã§ååã§ããããšãæå³ããŸãã幞ããamphpã¯ãæå®ãããééã§ããã¯ã°ã©ãŠã³ãã§å®è¡ããããã®ã·ã³ãã«ãªããŒã«ãæäŸããŸãã
æ¯ç§ã¡ã¢ãªãã¯ãªã¢ããã®ã¯ç°¡åãããŠããŸã广çã§ã¯ãªãããã«èŠããŸãããååã®ã¯ãªãŒã³ã¢ãã以éã®ã¡ã¢ãªã²ã€ã³ããã§ãã¯ããã¢ã«ãŽãªãºã ã«èœã¡çããŸãããã²ã€ã³ããããå€ããã倧ããå Žåãã¯ãªã¢ãçºçããŸãã
<?php
namespace danog\MadelineProto\MTProtoTools;
use Amp\Loop;
use danog\MadelineProto\Logger;
class GarbageCollector
{
/**
* Ensure only one instance of GarbageCollector
* when multiple instances of MadelineProto running.
* @var bool
*/
public static bool $lock = false;
/**
* How often will check memory.
* @var int
*/
public static int $checkIntervalMs = 1000;
/**
* Next cleanup will be triggered when memory consumption will increase by this amount.
* @var int
*/
public static int $memoryDiffMb = 1;
/**
* Memory consumption after last cleanup.
* @var int
*/
private static int $memoryConsumption = 0;
public static function start(): void
{
if (static::$lock) {
return;
}
static::$lock = true;
Loop::repeat(static::$checkIntervalMs, static function () {
$currentMemory = static::getMemoryConsumption();
if ($currentMemory > static::$memoryConsumption + static::$memoryDiffMb) {
\gc_collect_cycles();
static::$memoryConsumption = static::getMemoryConsumption();
$cleanedMemory = $currentMemory - static::$memoryConsumption;
Logger::log("gc_collect_cycles done. Cleaned memory: $cleanedMemory Mb", Logger::VERBOSE);
}
});
}
private static function getMemoryConsumption(): int
{
$memory = \round(\memory_get_usage()/1024/1024, 1);
Logger::log("Memory consumption: $memory Mb", Logger::ULTRA_VERBOSE);
return (int) $memory;
}
}