Skip to content

Commit e2bd863

Browse files
committed
perf: add O(1) lookup caching for ProjectNode document entries
- Cache root document entry on add for O(1) getRootDocumentEntry() - Use direct hash lookup for getDocumentEntry() instead of iteration - Properly invalidate cache on setDocumentEntries() and reset()
1 parent 44a9023 commit e2bd863

File tree

1 file changed

+19
-4
lines changed

1 file changed

+19
-4
lines changed

packages/guides/src/Nodes/ProjectNode.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ final class ProjectNode extends CompoundNode
4747
/** @var array<string, array<string, InternalTarget>> */
4848
private array $internalLinkTargets = [];
4949

50+
/** Cached root document entry for O(1) lookup */
51+
private DocumentEntryNode|null $rootDocumentEntry = null;
52+
5053
/** @var DocumentEntryNode[] */
5154
private array $documentEntries = [];
5255
private DateTimeImmutable $lastRendered;
@@ -182,6 +185,11 @@ public function getAllInternalTargets(): array
182185

183186
public function addDocumentEntry(DocumentEntryNode $documentEntry): void
184187
{
188+
// Cache root document entry for O(1) lookup
189+
if ($documentEntry->isRoot()) {
190+
$this->rootDocumentEntry = $documentEntry;
191+
}
192+
185193
$this->documentEntries[$documentEntry->getFile()] = $documentEntry;
186194
}
187195

@@ -193,8 +201,15 @@ public function getAllDocumentEntries(): array
193201

194202
public function getRootDocumentEntry(): DocumentEntryNode
195203
{
204+
if ($this->rootDocumentEntry !== null) {
205+
return $this->rootDocumentEntry;
206+
}
207+
208+
// Fallback: scan and cache if set via setDocumentEntries()
196209
foreach ($this->documentEntries as $documentEntry) {
197210
if ($documentEntry->isRoot()) {
211+
$this->rootDocumentEntry = $documentEntry;
212+
198213
return $documentEntry;
199214
}
200215
}
@@ -205,10 +220,8 @@ public function getRootDocumentEntry(): DocumentEntryNode
205220
/** @throws DocumentEntryNotFound */
206221
public function getDocumentEntry(string $file): DocumentEntryNode
207222
{
208-
foreach ($this->documentEntries as $documentEntry) {
209-
if ($documentEntry->getFile() === $file) {
210-
return $documentEntry;
211-
}
223+
if (isset($this->documentEntries[$file])) {
224+
return $this->documentEntries[$file];
212225
}
213226

214227
throw new DocumentEntryNotFound('No document Entry found for file ' . $file);
@@ -218,6 +231,7 @@ public function getDocumentEntry(string $file): DocumentEntryNode
218231
public function setDocumentEntries(array $documentEntries): void
219232
{
220233
$this->documentEntries = $documentEntries;
234+
$this->rootDocumentEntry = null;
221235
}
222236

223237
public function findDocumentEntry(string $filePath): DocumentEntryNode|null
@@ -228,6 +242,7 @@ public function findDocumentEntry(string $filePath): DocumentEntryNode|null
228242
public function reset(): void
229243
{
230244
$this->documentEntries = [];
245+
$this->rootDocumentEntry = null;
231246
}
232247

233248
public function getLastRendered(): DateTimeImmutable

0 commit comments

Comments
 (0)