From b0a615ae423a4ce6ed940f5704f0995c01d2944f Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 6 Oct 2026 19:26:53 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9A=A1=20Bolt:=20Optimize=20KernelDirect?= =?UTF-8?q?MemoryQuery=20direct=20allocations=20LINQ=20query?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced an O(N log N) LINQ-based sorting and filtering allocation chain inside `KernelDirectMemoryQuery` with a single-pass O(N) allocation-free manual search loop. This change reduces algorithmic complexity and eliminates delegate/enumerator allocations in the lock hot path. Co-authored-by: manupawickramasinghe <73810867+manupawickramasinghe@users.noreply.github.com> --- .jules/bolt.md | 5 ++++ .../Kernel/KernelMemoryCompatExports.cs | 26 +++++++++++-------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index c5df166956..bead324d0e 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -48,3 +48,8 @@ **Context:** Guest MMU / `VirtualMemory.cs` (`CopyFromRegions`, `CopyToRegions`) **Learning:** Sequential tracking over Spans with an external `copied` counter and range indexer (`span[copied..]`) introduces local bounds check validation overhead. Reassigning the span reference in place via `span = span.Slice(chunkLength)` eliminates this and simplifies hot loops into `!span.IsEmpty` checks. **Action:** Use idiomatic slice-reassignment (`span = span.Slice(length)`) instead of external integer trackers in loop conditions over `Span` sequential memory operations to reduce arithmetic overhead. + +## 2026-10-06 - Zero-Allocation Search in KernelMemoryCompatExports +**Context:** src/SharpEmu.Libs/Kernel/KernelMemoryCompatExports.cs +**Learning:** Found an O(N log N) LINQ-based sorting/filtering bottleneck (`.Values.Where(...).OrderBy(...)`) inside the `KernelDirectMemoryQuery` lock. This was causing GC pressure due to enumerator and delegate allocations on a hot path during kernel HLE queries. +**Action:** Replaced it with an O(N) allocation-free manual search loop using standard variables (`matchStart`, `matchEnd`) to natively handle uniqueness and prioritization. diff --git a/src/SharpEmu.Libs/Kernel/KernelMemoryCompatExports.cs b/src/SharpEmu.Libs/Kernel/KernelMemoryCompatExports.cs index 15ee4bcd7e..14c62fb0fe 100644 --- a/src/SharpEmu.Libs/Kernel/KernelMemoryCompatExports.cs +++ b/src/SharpEmu.Libs/Kernel/KernelMemoryCompatExports.cs @@ -3706,19 +3706,23 @@ public static int KernelDirectMemoryQuery(CpuContext ctx) lock (_memoryGate) { - var candidates = _directAllocations.Values - .Where(block => findNext + // Performance optimization: Replaced O(N log N) LINQ sorting and allocating Where/OrderBy chain with a single-pass O(N) allocation-free manual search loop. + foreach (var block in _directAllocations.Values) + { + var isMatch = findNext ? block.Start + block.Length > offset - : offset >= block.Start && offset < block.Start + block.Length) - .OrderBy(block => block.Start); + : offset >= block.Start && offset < block.Start + block.Length; - foreach (var block in candidates) - { - found = true; - matchStart = block.Start; - matchEnd = block.Start + block.Length; - matchMemoryType = block.MemoryType; - break; + if (isMatch) + { + if (!found || block.Start < matchStart) + { + found = true; + matchStart = block.Start; + matchEnd = block.Start + block.Length; + matchMemoryType = block.MemoryType; + } + } } } From 43a799b3b5918d417c119b7ce626089728672731 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 6 Oct 2026 19:33:37 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9A=A1=20Bolt:=20Optimize=20KernelDirect?= =?UTF-8?q?MemoryQuery=20direct=20allocations=20LINQ=20query?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced an O(N log N) LINQ-based sorting and filtering allocation chain inside `KernelDirectMemoryQuery` with a single-pass O(N) allocation-free manual search loop. This change reduces algorithmic complexity and eliminates delegate/enumerator allocations in the lock hot path. Co-authored-by: manupawickramasinghe <73810867+manupawickramasinghe@users.noreply.github.com>