diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 00000000..b7b48382 --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2024-05-24 - WslPathResolver string splitting +**Learning:** `WslPathResolver.TryParseUncRemainder` used `string.Split()`, `string.Join()`, and `Enumerable.Skip()` which leads to unnecessary GC pressure and multiple string/array allocations for hot path code. +**Action:** Replace `string.Split` with `ReadOnlySpan.Split` and use `StringBuilder` to append portions sequentially when parsing and reconstructing path parts. This saves multiple array/string allocations and makes parsing faster. diff --git a/QuickShell.Core/Services/WslPathResolver.cs b/QuickShell.Core/Services/WslPathResolver.cs index e849dfb0..232ba4c9 100644 --- a/QuickShell.Core/Services/WslPathResolver.cs +++ b/QuickShell.Core/Services/WslPathResolver.cs @@ -142,16 +142,39 @@ public static string ResolveDistro(WslLocation location, LaunchTarget target) => private static bool TryParseUncRemainder(string remainder, string fullUnc, out WslLocation location) { location = null!; - var parts = remainder.Split('\\', StringSplitOptions.RemoveEmptyEntries); - if (parts.Length < 2) + // Bolt: Performance optimization - avoid string.Split(), Linq Skip(), and string.Join() allocations. + var span = remainder.AsSpan(); + string? distro = null; + var linuxPathBuilder = new System.Text.StringBuilder(); + + foreach (var range in span.Split('\\')) + { + var part = span[range]; + if (part.IsEmpty) + { + continue; + } + + if (distro is null) + { + distro = part.ToString(); + } + else + { + linuxPathBuilder.Append('/'); + linuxPathBuilder.Append(part); + } + } + + if (linuxPathBuilder.Length == 0 || distro is null) { return false; } location = new WslLocation { - Distro = parts[0], - LinuxPath = "/" + string.Join('/', parts.Skip(1)), + Distro = distro, + LinuxPath = linuxPathBuilder.ToString(), UncPath = fullUnc, };