Fix memory leaks when downloading files to callback. (#816)
This commit is contained in:
parent
83802fe944
commit
d5b2cbefd3
@ -22,12 +22,12 @@ namespace danog\MadelineProto;
|
||||
use Amp\Dns\Resolver;
|
||||
use Amp\File\StatCache;
|
||||
use Amp\Http\Client\HttpClient;
|
||||
use Amp\Loop;
|
||||
use danog\MadelineProto\Async\AsyncConstruct;
|
||||
use danog\MadelineProto\Loop\Generic\PeriodicLoop;
|
||||
use danog\MadelineProto\Loop\Update\FeedLoop;
|
||||
use danog\MadelineProto\Loop\Update\SeqLoop;
|
||||
use danog\MadelineProto\Loop\Update\UpdateLoop;
|
||||
use danog\MadelineProto\MTProtoTools\GarbageCollector;
|
||||
use danog\MadelineProto\MTProtoTools\CombinedUpdatesState;
|
||||
use danog\MadelineProto\MTProtoTools\MinDatabase;
|
||||
use danog\MadelineProto\MTProtoTools\ReferenceDatabase;
|
||||
@ -465,6 +465,8 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
yield from $this->getConfig([], ['datacenter' => $this->datacenter->curdc]);
|
||||
$this->startUpdateSystem(true);
|
||||
$this->v = self::V;
|
||||
|
||||
GarbageCollector::start();
|
||||
}
|
||||
/**
|
||||
* Sleep function.
|
||||
@ -921,6 +923,8 @@ class MTProto extends AsyncConstruct implements TLCallback
|
||||
yield $this->updaters[false]->resume();
|
||||
}
|
||||
$this->updaters[false]->start();
|
||||
|
||||
GarbageCollector::start();
|
||||
}
|
||||
/**
|
||||
* Unreference instance, allowing destruction.
|
||||
|
@ -499,7 +499,7 @@ trait Files
|
||||
$cb = [$bridge, 'callback'];
|
||||
$read = $this->uploadFromCallable($reader, $size, $mime, '', $cb, true, $encrypted);
|
||||
$write = $this->downloadToCallable($media, $writer, null, true, 0, -1, $chunk_size);
|
||||
list($res) = yield \danog\MadelineProto\Tools::all([$read, $write]);
|
||||
[$res] = yield \danog\MadelineProto\Tools::all([$read, $write]);
|
||||
return $res;
|
||||
}
|
||||
|
||||
@ -1038,7 +1038,7 @@ trait Files
|
||||
if (\count($range) == 1) {
|
||||
$range[1] = '';
|
||||
}
|
||||
list($size_unit, $range_orig) = $range;
|
||||
[$size_unit, $range_orig] = $range;
|
||||
if ($size_unit == 'bytes') {
|
||||
//multiple ranges could be specified at the same time, but for simplicity only serve the first range
|
||||
//http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt
|
||||
@ -1046,7 +1046,7 @@ trait Files
|
||||
if (\count($list) == 1) {
|
||||
$list[1] = '';
|
||||
}
|
||||
list($range, $extra_ranges) = $list;
|
||||
[$range, $extra_ranges] = $list;
|
||||
} else {
|
||||
return [
|
||||
'serve' => false,
|
||||
@ -1061,7 +1061,7 @@ trait Files
|
||||
if (\count($listseek) == 1) {
|
||||
$listseek[1] = '';
|
||||
}
|
||||
list($seek_start, $seek_end) = $listseek;
|
||||
[$seek_start, $seek_end] = $listseek;
|
||||
|
||||
$seek_end = empty($seek_end) ? ($messageMedia['size'] - 1) : \min(\abs(\intval($seek_end)), $messageMedia['size'] - 1);
|
||||
|
||||
@ -1274,7 +1274,7 @@ trait Files
|
||||
$time = 0;
|
||||
$speed = 0;
|
||||
$origCb = $cb;
|
||||
$cb = function () use ($cb, $count, &$time, &$speed) {
|
||||
$cb = static function () use ($cb, $count, &$time, &$speed) {
|
||||
static $cur = 0;
|
||||
$cur++;
|
||||
\danog\MadelineProto\Tools::callFork($cb($cur * 100 / $count, $time, $speed));
|
||||
|
59
src/danog/MadelineProto/MTProtoTools/GarbageCollector.php
Normal file
59
src/danog/MadelineProto/MTProtoTools/GarbageCollector.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?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::NOTICE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static function getMemoryConsumption(): int
|
||||
{
|
||||
$memory = round(memory_get_usage()/1024/1024, 1);
|
||||
Logger::log("Memory consumption: $memory Mb", Logger::VERBOSE);
|
||||
return (int) $memory;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user