Repository: read the blobs of a pack from one open stream

Restores and deep verifies requested every blob separately: a new file handle and a seek on
the location each time. They read the blobs of a snapshot in the order they were written, so
the stream of the pack read last now stays open and is read on; a jump backwards, to another
pack, or more than 8 MiB ahead opens the pack again at the offset, as before. On a Hetzner
Storage Box over SMB, restoring 86 MB in 202 files went from 0.78 MB/s to 4.2 MB/s.
This commit is contained in:
2026-10-08 22:17:53 +02:00
parent 4fa7cbf6ef
commit 5f8d5faee7
4 changed files with 223 additions and 4 deletions
+9 -2
View File
@@ -129,7 +129,7 @@ class VerifyTest extends TestCase {
}
}
/** Delegates to a real backend, but getRange() throws for the first $failures calls. */
/** Delegates to a real backend, but reading a pack throws for the first $failures reads. */
final class FlakyRangeBackend implements IBackend {
public function __construct(
private IBackend $inner,
@@ -143,15 +143,22 @@ final class FlakyRangeBackend implements IBackend {
}
public function get(string $path) {
if (str_starts_with($path, 'packs/')) {
$this->fail();
}
return $this->inner->get($path);
}
public function getRange(string $path, int $offset, int $length): string {
$this->fail();
return $this->inner->getRange($path, $offset, $length);
}
private function fail(): void {
if ($this->failures > 0) {
$this->failures--;
throw $this->error ?? new BackendException('connection reset');
}
return $this->inner->getRange($path, $offset, $length);
}
public function exists(string $path): bool {