1
0
mirror of https://github.com/Seldaek/monolog.git synced 2025-09-01 17:12:41 +02:00

Simplify memoryIniValueToBytes, tweak code to use less memory overall

This commit is contained in:
Jordi Boggiano
2021-09-14 13:44:02 +02:00
parent 0b22036ab6
commit 70fe092867
4 changed files with 54 additions and 97 deletions

View File

@@ -26,9 +26,7 @@ use Monolog\Utils;
class StreamHandler extends AbstractProcessingHandler
{
/** @const int */
const SAFE_MEMORY_OFFSET = 1024;
/** @const int */
const MAX_CHUNK_SIZE = 2147483647;
protected const MAX_CHUNK_SIZE = 100 * 1024 * 1024;
/** @var int */
protected $streamChunkSize = self::MAX_CHUNK_SIZE;
/** @var resource|null */
@@ -55,25 +53,21 @@ class StreamHandler extends AbstractProcessingHandler
{
parent::__construct($level, $bubble);
if ($phpMemoryLimit = ini_get('memory_limit')) {
if (($memoryInByes = Utils::memoryIniValueToBytes($phpMemoryLimit))) {
$memoryUsage = memory_get_usage(true);
if (($memoryInByes - $memoryUsage) < $this->streamChunkSize) {
$this->streamChunkSize = $memoryInByes - $memoryUsage - self::SAFE_MEMORY_OFFSET;
}
if (($phpMemoryLimit = Utils::expandIniShorthandBytes(ini_get('memory_limit'))) !== false) {
if ($phpMemoryLimit > 0) {
// use max 10% of allowed memory for the chunk size
$this->streamChunkSize = max((int) ($phpMemoryLimit / 10), 10*1024);
}
// else memory is unlimited, keep the buffer to the default 100MB
} else {
// no memory limit information, use a conservative 10MB
$this->streamChunkSize = 10*10*1024;
}
if (is_resource($stream)) {
$this->stream = $stream;
try {
stream_set_chunk_size($this->stream, $this->streamChunkSize);
} catch (\Exception $exception) {
throw new \RuntimeException('Impossible to set the stream chunk size.'
.PHP_EOL.'Error: '.$exception->getMessage()
.PHP_EOL.'Trace: '.$exception->getTraceAsString());
}
stream_set_chunk_size($this->stream, $this->streamChunkSize);
} elseif (is_string($stream)) {
$this->url = Utils::canonicalizePath($stream);
} else {
@@ -119,7 +113,7 @@ class StreamHandler extends AbstractProcessingHandler
/**
* @return int
*/
public function getStreamChunkSize() : int
public function getStreamChunkSize(): int
{
return $this->streamChunkSize;
}

View File

@@ -229,41 +229,27 @@ final class Utils
/**
* Converts a string with a valid 'memory_limit' format, to bytes.
* Reference: Function code from https://www.php.net/manual/en/function.ini-get.php
* @param string|int $val
*
* @param string|false $val
* @return int|false Returns an integer representing bytes. Returns FALSE in case of error.
*/
public static function memoryIniValueToBytes($val)
public static function expandIniShorthandBytes($val)
{
if (!is_string($val) && !is_integer($val)) {
if (!is_string($val)) {
return false;
}
$val = trim((string)$val);
// support -1
if ((int) $val < 0) {
return (int) $val;
}
if (empty($val)) {
if (!preg_match('/^\s*(?<val>\d+)(?:\.\d+)?\s*(?<unit>[gmk]?)\s*$/i', $val, $match)) {
return false;
}
$valLen = strlen($val);
$last = strtolower($val[$valLen - 1]);
if (preg_match('/[a-zA-Z]/', $last)) {
if ($valLen == 1) {
return false;
}
$val = substr($val, 0, -1);
}
if (!is_numeric($val) || $val < 0) {
return false;
}
//Lets be explicit here
$val = (int)($val);
switch ($last) {
$val = (int) $match['val'];
switch (strtolower($match['unit'] ?? '')) {
case 'g':
$val *= 1024;
case 'm':