From e20b3df8eb106719fb9407d8a16dcae8c0219cb9 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 11 Mar 2024 12:40:07 +0100 Subject: [PATCH 1/2] perf: read larger chunks in logiterator Signed-off-by: Robin Appelman --- lib/Log/LogIterator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Log/LogIterator.php b/lib/Log/LogIterator.php index 8e4bbcca..ec7133b9 100644 --- a/lib/Log/LogIterator.php +++ b/lib/Log/LogIterator.php @@ -54,7 +54,7 @@ class LogIterator implements \Iterator { private $timezone; - public const CHUNK_SIZE = 100; // how many chars do we try at once to find a new line + public const CHUNK_SIZE = 8192; // how many chars do we try at once to find a new line /** * @param resource $handle From 32f93c28276564df9defa67469685092cb87f87f Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 12 Mar 2024 13:20:03 +0100 Subject: [PATCH 2/2] fix: rework log iterator logic this makes it work better with chunk size > line length Signed-off-by: Robin Appelman --- lib/Log/LogIterator.php | 72 +++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 46 deletions(-) diff --git a/lib/Log/LogIterator.php b/lib/Log/LogIterator.php index ec7133b9..27acf7e3 100644 --- a/lib/Log/LogIterator.php +++ b/lib/Log/LogIterator.php @@ -29,30 +29,13 @@ class LogIterator implements \Iterator { * @var resource */ private $handle; + private string $buffer = ''; + private int $position = 0; + private string $lastLine; - /** - * @var int - */ - private $position = 0; - - /** - * @var string - */ - private $lastLine; - - /** - * @var string - */ - private $currentLine = ''; - - private $currentKey = -1; - - /** - * @var string - */ - private $dateFormat; - - private $timezone; + private int $currentKey = -1; + private string $dateFormat; + private \DateTimeZone $timezone; public const CHUNK_SIZE = 8192; // how many chars do we try at once to find a new line @@ -61,7 +44,7 @@ class LogIterator implements \Iterator { * @param string $dateFormat * @param string $timezone */ - public function __construct($handle, $dateFormat, $timezone) { + public function __construct($handle, string $dateFormat, string $timezone) { $this->handle = $handle; $this->dateFormat = $dateFormat; $this->timezone = new \DateTimeZone($timezone); @@ -71,7 +54,7 @@ public function __construct($handle, $dateFormat, $timezone) { public function rewind(): void { fseek($this->handle, 0, SEEK_END); - $this->position = ftell($this->handle) - self::CHUNK_SIZE; + $this->position = ftell($this->handle); $this->currentKey = 0; } @@ -96,32 +79,29 @@ public function key(): int { return $this->currentKey; } - public function next(): void { - $this->currentLine = ''; + private function fillBuffer(): void { + $chunkSize = min($this->position, self::CHUNK_SIZE); + $this->position -= $chunkSize; + fseek($this->handle, $this->position); + $chunk = fread($this->handle, $chunkSize); + $this->buffer = $chunk . $this->buffer; + } + public function next(): void { // Loop through each character of the file looking for new lines - while ($this->position > 0) { - fseek($this->handle, $this->position); - $chars = fread($this->handle, self::CHUNK_SIZE); - $newlinePos = strrpos($chars, "\n"); + while ($this->position >= 0) { + $newlinePos = strrpos($this->buffer, "\n"); if ($newlinePos !== false) { - $this->currentLine = substr($chars, $newlinePos + 1) . $this->currentLine; - $this->lastLine = $this->currentLine; + $this->lastLine = substr($this->buffer, $newlinePos + 1); + $this->buffer = substr($this->buffer, 0, $newlinePos); $this->currentKey++; - $this->position -= (self::CHUNK_SIZE - $newlinePos); + return; + } elseif ($this->position === 0) { + $this->lastLine = $this->buffer; + $this->buffer = ''; return; } else { - $this->currentLine = $chars . $this->currentLine; - if ($this->position >= self::CHUNK_SIZE) { - $this->position -= self::CHUNK_SIZE; - } else { - $remaining = $this->position; - fseek($this->handle, 0); - $chars = fread($this->handle, $remaining); - $this->currentLine = $chars . $this->currentLine; - $this->lastLine = $this->currentLine; - $this->position = 0; - } + $this->fillBuffer(); } } } @@ -135,7 +115,7 @@ public function valid(): bool { return true; } - if ($this->currentLine === '') { + if ($this->lastLine === '') { return false; }