From f6a13dc8cfc225a5c0ffbd2aa9b708e8c58ed0ec Mon Sep 17 00:00:00 2001 From: sirily11 <32106111+sirily11@users.noreply.github.com> Date: Tue, 14 Jul 2026 11:01:27 +0800 Subject: [PATCH] fix: performance issue with message list --- .../RxCodeChatKit/MessageListView.swift | 18 +- .../xcshareddata/swiftpm/Package.resolved | 378 +++++++++--------- 2 files changed, 205 insertions(+), 191 deletions(-) diff --git a/Packages/Sources/RxCodeChatKit/MessageListView.swift b/Packages/Sources/RxCodeChatKit/MessageListView.swift index 556aa6a..b80f035 100644 --- a/Packages/Sources/RxCodeChatKit/MessageListView.swift +++ b/Packages/Sources/RxCodeChatKit/MessageListView.swift @@ -21,6 +21,11 @@ struct MessageListView: View { @Environment(ChatBridge.self) private var chatBridge @Environment(WindowState.self) private var windowState @State private var settledItems: [ChatMessage] = [] + /// Pre-grouped rows for `settledItems`. Streaming deltas re-evaluate this + /// view frequently, so rebuilding every historical row from `settledItems` + /// in `body` makes long threads do work proportional to their full history + /// for every delta. + @State private var settledTranscriptItems: [ChatTranscriptListItem] = [] /// Owns the debounced content-growth scroll. @State private var scrollTask: Task? /// Owns the multi-frame "settle at the bottom" sweep used on session open @@ -293,7 +298,7 @@ struct MessageListView: View { var items: [ChatTranscriptListItem] = [ .accessory(.init(id: "desktop-top-padding", kind: .topPadding)), ] - items += ChatTranscriptListItem.items(for: settledItems) + items += settledTranscriptItems if !windowState.focusMode { let activeMessages = activeResponseMessages(from: chatBridge.messages) @@ -343,9 +348,18 @@ struct MessageListView: View { private func rebuildSettledItems() { PerformanceDiagnostics.increment("chat.settled_rebuild.total") let messages = settledOnlyMessages(from: chatBridge.messages) + guard messages != settledItems else { + PerformanceDiagnostics.increment("chat.settled_rebuild.skipped_unchanged") + return + } + let transcriptItems = ChatTranscriptListItem.items(for: messages) var t = Transaction() t.animation = nil - withTransaction(t) { settledItems = messages } + withTransaction(t) { + settledItems = messages + settledTranscriptItems = transcriptItems + } + PerformanceDiagnostics.increment("chat.settled_rebuild.applied") } private func handleLastMessageChange() { diff --git a/RxCode.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/RxCode.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 55543e8..214de4c 100644 --- a/RxCode.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/RxCode.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,285 +1,285 @@ { - "originHash": "41271d02c93dbc18e9be262d16b5eb4573ee0d396c9b773ccf1525c1f6931890", - "pins": [ + "originHash" : "44ebc85e966c82ebc9594079fae8ad88d1f3caf7e56e32ce136050b581e95491", + "pins" : [ { - "identity": "abseil-cpp-binary", - "kind": "remoteSourceControl", - "location": "https://github.com/google/abseil-cpp-binary.git", - "state": { - "revision": "bbe8b69694d7873315fd3a4ad41efe043e1c07c5", - "version": "1.2024072200.0" + "identity" : "abseil-cpp-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/abseil-cpp-binary.git", + "state" : { + "revision" : "bbe8b69694d7873315fd3a4ad41efe043e1c07c5", + "version" : "1.2024072200.0" } }, { - "identity": "app-check", - "kind": "remoteSourceControl", - "location": "https://github.com/google/app-check.git", - "state": { - "revision": "61b85103a1aeed8218f17c794687781505fbbef5", - "version": "11.2.0" + "identity" : "app-check", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/app-check.git", + "state" : { + "revision" : "61b85103a1aeed8218f17c794687781505fbbef5", + "version" : "11.2.0" } }, { - "identity": "eventsource", - "kind": "remoteSourceControl", - "location": "https://github.com/mattt/eventsource.git", - "state": { - "revision": "a3a85a85214caf642abaa96ae664e4c772a59f6e", - "version": "1.4.1" + "identity" : "eventsource", + "kind" : "remoteSourceControl", + "location" : "https://github.com/mattt/eventsource.git", + "state" : { + "revision" : "a3a85a85214caf642abaa96ae664e4c772a59f6e", + "version" : "1.4.1" } }, { - "identity": "firebase-ios-sdk", - "kind": "remoteSourceControl", - "location": "https://github.com/firebase/firebase-ios-sdk", - "state": { - "revision": "fdc352fabaf5916e7faa1f96ad02b1957e93e5a5", - "version": "11.15.0" + "identity" : "firebase-ios-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/firebase-ios-sdk", + "state" : { + "revision" : "fdc352fabaf5916e7faa1f96ad02b1957e93e5a5", + "version" : "11.15.0" } }, { - "identity": "google-ads-on-device-conversion-ios-sdk", - "kind": "remoteSourceControl", - "location": "https://github.com/googleads/google-ads-on-device-conversion-ios-sdk", - "state": { - "revision": "a2d0f1f1666de591eb1a811f40b1706f5c63a2ed", - "version": "2.3.0" + "identity" : "google-ads-on-device-conversion-ios-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/googleads/google-ads-on-device-conversion-ios-sdk", + "state" : { + "revision" : "a2d0f1f1666de591eb1a811f40b1706f5c63a2ed", + "version" : "2.3.0" } }, { - "identity": "googleappmeasurement", - "kind": "remoteSourceControl", - "location": "https://github.com/google/GoogleAppMeasurement.git", - "state": { - "revision": "45ce435e9406d3c674dd249a042b932bee006f60", - "version": "11.15.0" + "identity" : "googleappmeasurement", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleAppMeasurement.git", + "state" : { + "revision" : "45ce435e9406d3c674dd249a042b932bee006f60", + "version" : "11.15.0" } }, { - "identity": "googledatatransport", - "kind": "remoteSourceControl", - "location": "https://github.com/google/GoogleDataTransport.git", - "state": { - "revision": "617af071af9aa1d6a091d59a202910ac482128f9", - "version": "10.1.0" + "identity" : "googledatatransport", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleDataTransport.git", + "state" : { + "revision" : "617af071af9aa1d6a091d59a202910ac482128f9", + "version" : "10.1.0" } }, { - "identity": "googleutilities", - "kind": "remoteSourceControl", - "location": "https://github.com/google/GoogleUtilities.git", - "state": { - "revision": "60da361632d0de02786f709bdc0c4df340f7613e", - "version": "8.1.0" + "identity" : "googleutilities", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleUtilities.git", + "state" : { + "revision" : "60da361632d0de02786f709bdc0c4df340f7613e", + "version" : "8.1.0" } }, { - "identity": "grpc-binary", - "kind": "remoteSourceControl", - "location": "https://github.com/google/grpc-binary.git", - "state": { - "revision": "75b31c842f664a0f46a2e590a570e370249fd8f6", - "version": "1.69.1" + "identity" : "grpc-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/grpc-binary.git", + "state" : { + "revision" : "75b31c842f664a0f46a2e590a570e370249fd8f6", + "version" : "1.69.1" } }, { - "identity": "gtm-session-fetcher", - "kind": "remoteSourceControl", - "location": "https://github.com/google/gtm-session-fetcher.git", - "state": { - "revision": "c756a29784521063b6a1202907e2cc47f41b667c", - "version": "4.5.0" + "identity" : "gtm-session-fetcher", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/gtm-session-fetcher.git", + "state" : { + "revision" : "c756a29784521063b6a1202907e2cc47f41b667c", + "version" : "4.5.0" } }, { - "identity": "interop-ios-for-google-sdks", - "kind": "remoteSourceControl", - "location": "https://github.com/google/interop-ios-for-google-sdks.git", - "state": { - "revision": "040d087ac2267d2ddd4cca36c757d1c6a05fdbfe", - "version": "101.0.0" + "identity" : "interop-ios-for-google-sdks", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/interop-ios-for-google-sdks.git", + "state" : { + "revision" : "040d087ac2267d2ddd4cca36c757d1c6a05fdbfe", + "version" : "101.0.0" } }, { - "identity": "leveldb", - "kind": "remoteSourceControl", - "location": "https://github.com/firebase/leveldb.git", - "state": { - "revision": "a0bc79961d7be727d258d33d5a6b2f1023270ba1", - "version": "1.22.5" + "identity" : "leveldb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/leveldb.git", + "state" : { + "revision" : "a0bc79961d7be727d258d33d5a6b2f1023270ba1", + "version" : "1.22.5" } }, { - "identity": "nanopb", - "kind": "remoteSourceControl", - "location": "https://github.com/firebase/nanopb.git", - "state": { - "revision": "b7e1104502eca3a213b46303391ca4d3bc8ddec1", - "version": "2.30910.0" + "identity" : "nanopb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/nanopb.git", + "state" : { + "revision" : "b7e1104502eca3a213b46303391ca4d3bc8ddec1", + "version" : "2.30910.0" } }, { - "identity": "promises", - "kind": "remoteSourceControl", - "location": "https://github.com/google/promises.git", - "state": { - "revision": "540318ecedd63d883069ae7f1ed811a2df00b6ac", - "version": "2.4.0" + "identity" : "promises", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/promises.git", + "state" : { + "revision" : "540318ecedd63d883069ae7f1ed811a2df00b6ac", + "version" : "2.4.0" } }, { - "identity": "rxauthswift", - "kind": "remoteSourceControl", - "location": "https://github.com/rxtech-lab/RxAuthSwift", - "state": { - "revision": "f1bc8a1004c58f7eae628eaf8ae705e4f8c21c51", - "version": "1.1.1" + "identity" : "rxauthswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/rxtech-lab/RxAuthSwift", + "state" : { + "revision" : "f1bc8a1004c58f7eae628eaf8ae705e4f8c21c51", + "version" : "1.1.1" } }, { - "identity": "sdwebimage", - "kind": "remoteSourceControl", - "location": "https://github.com/SDWebImage/SDWebImage.git", - "state": { - "revision": "2de3a496eaf6df9a1312862adcfd54acd73c39c0", - "version": "5.21.7" + "identity" : "sdwebimage", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SDWebImage/SDWebImage.git", + "state" : { + "revision" : "2de3a496eaf6df9a1312862adcfd54acd73c39c0", + "version" : "5.21.7" } }, { - "identity": "sdwebimagesvgcoder", - "kind": "remoteSourceControl", - "location": "https://github.com/SDWebImage/SDWebImageSVGCoder", - "state": { - "revision": "85b5d58ad02c207c496fa34426dc6560d6ae32f0", - "version": "1.8.0" + "identity" : "sdwebimagesvgcoder", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SDWebImage/SDWebImageSVGCoder", + "state" : { + "revision" : "85b5d58ad02c207c496fa34426dc6560d6ae32f0", + "version" : "1.8.0" } }, { - "identity": "sparkle", - "kind": "remoteSourceControl", - "location": "https://github.com/sparkle-project/Sparkle.git", - "state": { - "revision": "066e75a8b3e99962685d6a90cdd5293ebffd9261", - "version": "2.9.1" + "identity" : "sparkle", + "kind" : "remoteSourceControl", + "location" : "https://github.com/sparkle-project/Sparkle.git", + "state" : { + "revision" : "066e75a8b3e99962685d6a90cdd5293ebffd9261", + "version" : "2.9.1" } }, { - "identity": "swift-argument-parser", - "kind": "remoteSourceControl", - "location": "https://github.com/apple/swift-argument-parser", - "state": { - "revision": "626b5b7b2f45e1b0b1c6f4a309296d1d21d7311b", - "version": "1.7.1" + "identity" : "swift-argument-parser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-argument-parser", + "state" : { + "revision" : "626b5b7b2f45e1b0b1c6f4a309296d1d21d7311b", + "version" : "1.7.1" } }, { - "identity": "swift-atomics", - "kind": "remoteSourceControl", - "location": "https://github.com/apple/swift-atomics.git", - "state": { - "revision": "0442cb5a3f98ab802acb777929fdb446bda11a34", - "version": "1.3.1" + "identity" : "swift-atomics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-atomics.git", + "state" : { + "revision" : "0442cb5a3f98ab802acb777929fdb446bda11a34", + "version" : "1.3.1" } }, { - "identity": "swift-collections", - "kind": "remoteSourceControl", - "location": "https://github.com/apple/swift-collections", - "state": { - "revision": "fea17c02d767f46b23070fdfdacc28a03a39232a", - "version": "1.5.1" + "identity" : "swift-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-collections", + "state" : { + "revision" : "fea17c02d767f46b23070fdfdacc28a03a39232a", + "version" : "1.5.1" } }, { - "identity": "swift-json-schema", - "kind": "remoteSourceControl", - "location": "https://github.com/sirily11/swift-json-schema", - "state": { - "revision": "663afab8c131151950fd7fb114871c02a529a4b4", - "version": "1.0.2" + "identity" : "swift-json-schema", + "kind" : "remoteSourceControl", + "location" : "https://github.com/sirily11/swift-json-schema", + "state" : { + "revision" : "663afab8c131151950fd7fb114871c02a529a4b4", + "version" : "1.0.2" } }, { - "identity": "swift-jsonschema-form", - "kind": "remoteSourceControl", - "location": "https://github.com/sirily11/swift-jsonschema-form", - "state": { - "branch": "main", - "revision": "a4feb400a0bca57bc39b8ea95544c71aa768fbfd" + "identity" : "swift-jsonschema-form", + "kind" : "remoteSourceControl", + "location" : "https://github.com/sirily11/swift-jsonschema-form", + "state" : { + "branch" : "main", + "revision" : "a4feb400a0bca57bc39b8ea95544c71aa768fbfd" } }, { - "identity": "swift-log", - "kind": "remoteSourceControl", - "location": "https://github.com/apple/swift-log.git", - "state": { - "revision": "7dc6101ae4dbe95cd3bc9cebad3b7cf8e49a7a63", - "version": "1.13.0" + "identity" : "swift-log", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-log.git", + "state" : { + "revision" : "7dc6101ae4dbe95cd3bc9cebad3b7cf8e49a7a63", + "version" : "1.13.0" } }, { - "identity": "swift-nio", - "kind": "remoteSourceControl", - "location": "https://github.com/apple/swift-nio.git", - "state": { - "revision": "cd3e1152083706d77b223fb29110e590efcc70c0", - "version": "2.101.2" + "identity" : "swift-nio", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio.git", + "state" : { + "revision" : "cd3e1152083706d77b223fb29110e590efcc70c0", + "version" : "2.101.2" } }, { - "identity": "swift-protobuf", - "kind": "remoteSourceControl", - "location": "https://github.com/apple/swift-protobuf.git", - "state": { - "revision": "f6506eaa86ed2e01cb0ae14a75035b7fdbf0918f", - "version": "1.38.0" + "identity" : "swift-protobuf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-protobuf.git", + "state" : { + "revision" : "f6506eaa86ed2e01cb0ae14a75035b7fdbf0918f", + "version" : "1.38.0" } }, { - "identity": "swift-sdk", - "kind": "remoteSourceControl", - "location": "https://github.com/modelcontextprotocol/swift-sdk", - "state": { - "revision": "a0ae212ebf6eab5f754c3129608bc5557637e605", - "version": "0.12.1" + "identity" : "swift-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/modelcontextprotocol/swift-sdk", + "state" : { + "revision" : "a0ae212ebf6eab5f754c3129608bc5557637e605", + "version" : "0.12.1" } }, { - "identity": "swift-system", - "kind": "remoteSourceControl", - "location": "https://github.com/apple/swift-system.git", - "state": { - "revision": "b5544ba79a70a0cb3563e75bf26dc198d6b40ed3", - "version": "1.7.4" + "identity" : "swift-system", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-system.git", + "state" : { + "revision" : "b5544ba79a70a0cb3563e75bf26dc198d6b40ed3", + "version" : "1.7.4" } }, { - "identity": "swiftterm", - "kind": "remoteSourceControl", - "location": "https://github.com/migueldeicaza/SwiftTerm.git", - "state": { - "revision": "8e7a1e154f470e19c709a00a8768df348ba5fc43", - "version": "1.13.0" + "identity" : "swiftterm", + "kind" : "remoteSourceControl", + "location" : "https://github.com/migueldeicaza/SwiftTerm.git", + "state" : { + "revision" : "8e7a1e154f470e19c709a00a8768df348ba5fc43", + "version" : "1.13.0" } }, { - "identity": "viewinspector", - "kind": "remoteSourceControl", - "location": "https://github.com/nalexn/ViewInspector", - "state": { - "revision": "e9a06346499a3a889165647e3f23f8a7b2609a1c", - "version": "0.10.3" + "identity" : "viewinspector", + "kind" : "remoteSourceControl", + "location" : "https://github.com/nalexn/ViewInspector", + "state" : { + "revision" : "e9a06346499a3a889165647e3f23f8a7b2609a1c", + "version" : "0.10.3" } }, { - "identity": "waterfallgrid", - "kind": "remoteSourceControl", - "location": "https://github.com/paololeonardi/WaterfallGrid", - "state": { - "revision": "c7c08652c3540adf8e48409c351879b4caea7e89", - "version": "1.1.0" + "identity" : "waterfallgrid", + "kind" : "remoteSourceControl", + "location" : "https://github.com/paololeonardi/WaterfallGrid", + "state" : { + "revision" : "c7c08652c3540adf8e48409c351879b4caea7e89", + "version" : "1.1.0" } } ], - "version": 3 + "version" : 3 }