perf: eliminate List<T> alloc in DisplayText and GetSessionListInternal

SessionInfo.DisplayText was allocating new List<string> + internal
backing array on every call (happens every UI refresh per session).
Replace with a simple tuple-switch over at most two optional segments
so only the final interpolated string is allocated.

GetSessionListInternal was constructing a List<SessionInfo> from the
dictionary values and then calling .ToArray(), paying two heap
allocations per session-list snapshot. Replace with a single
new SessionInfo[_sessions.Count] + Values.CopyTo + Array.Sort
so only one array is allocated and the sort is performed in-place.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
github-actions[bot] 2026-04-08 01:06:59 +00:00
parent bd0a7b0d67
commit fc8299a962
2 changed files with 14 additions and 15 deletions

View File

@ -182,17 +182,16 @@ public class SessionInfo
get
{
var prefix = IsMain ? "Main" : "Sub";
var parts = new List<string> { prefix };
if (!string.IsNullOrEmpty(Channel))
parts.Add(Channel);
if (!string.IsNullOrEmpty(CurrentActivity))
parts.Add(CurrentActivity);
else if (!string.IsNullOrEmpty(Status) && Status != "unknown" && Status != "active")
parts.Add(Status);
return string.Join(" · ", parts);
string? mid = !string.IsNullOrEmpty(Channel) ? Channel : null;
string? end = !string.IsNullOrEmpty(CurrentActivity) ? CurrentActivity
: (!string.IsNullOrEmpty(Status) && Status != "unknown" && Status != "active" ? Status : null);
return (mid, end) switch
{
(null, null) => prefix,
(not null, null) => $"{prefix} · {mid}",
(null, not null) => $"{prefix} · {end}",
_ => $"{prefix} · {mid} · {end}",
};
}
}

View File

@ -1358,14 +1358,14 @@ public class OpenClawGatewayClient : WebSocketClientBase
private SessionInfo[] GetSessionListInternal()
{
var list = new List<SessionInfo>(_sessions.Values);
list.Sort((a, b) =>
var result = new SessionInfo[_sessions.Count];
_sessions.Values.CopyTo(result, 0);
Array.Sort(result, static (a, b) =>
{
// Main session first, then by last seen
if (a.IsMain != b.IsMain) return a.IsMain ? -1 : 1;
return b.LastSeen.CompareTo(a.LastSeen);
});
return list.ToArray();
return result;
}
// --- Parsing helpers ---