From 044d1ea68cc1153e776567cfa5555559c3061ceb Mon Sep 17 00:00:00 2001 From: jack <212554440+jackjackbits@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:24:27 +0200 Subject: [PATCH] Gate geochat scaling regressions in the performance floor check (#1791) * Gate geochat scaling regressions in the performance floor check * Base the geochat format floor on its first CI run Co-Authored-By: Claude Opus 5.5 --- .../PerformanceBaselineTests+Geochat.swift | 185 ++++++++++++++++++ .../PerformanceBaselineTests.swift | 3 +- bitchatTests/Performance/perf-floors.json | 22 ++- 3 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 bitchatTests/Performance/PerformanceBaselineTests+Geochat.swift diff --git a/bitchatTests/Performance/PerformanceBaselineTests+Geochat.swift b/bitchatTests/Performance/PerformanceBaselineTests+Geochat.swift new file mode 100644 index 00000000..a9c46fd6 --- /dev/null +++ b/bitchatTests/Performance/PerformanceBaselineTests+Geochat.swift @@ -0,0 +1,185 @@ +// +// PerformanceBaselineTests+Geochat.swift +// bitchatTests +// +// Geochat (location channel) benchmarks at a busy-room size. Each guards a +// cost that used to grow with the number of participants N: +// +// - the people sheet resolved every row's color by rebuilding the whole +// roster, so one render was O(N^2); +// - every roster rebuild hex-encoded our own key once per participant with +// String(format:) per byte; +// - every inbound event (presence heartbeats arrive ~N/60 times a second) +// rebuilt and republished the roster. +// +// perf-floors.json keeps each floor far above those regression values. +// + +import XCTest +import BitFoundation +@testable import bitchat + +extension PerformanceBaselineTests { + /// The room size at which the regressions above cost seconds. + private static let geochatParticipants = 500 + + // MARK: - Geochat people list colors + + /// One people-sheet render resolves a color for every row. + func testGeochatPeopleListColors() { + let fixture = GeochatPerfFixture(participants: Self.geochatParticipants) + let pubkeys = fixture.pubkeys + var samples: [TimeInterval] = [] + + measure { + let start = Date() + for pubkey in pubkeys { + _ = fixture.viewModel.colorForNostrPubkey(pubkey, isDark: true) + } + samples.append(Date().timeIntervalSince(start)) + } + + reportThroughput("geochat.peopleListColors", samples: samples, operations: pubkeys.count, unit: "rows") + } + + // MARK: - Geochat participant heartbeats + + /// Presence heartbeats and messages from people already in the room. + func testGeochatParticipantHeartbeats() { + let fixture = GeochatPerfFixture(participants: Self.geochatParticipants) + let tracker = fixture.viewModel.participantTracker + let pubkeys = fixture.pubkeys + let events = 2_000 + var samples: [TimeInterval] = [] + + measure { + let start = Date() + for index in 0.. XCTest's default 10 measure iterations + let batchSize = 200 + let batches: [[BitchatMessage]] = (0.. 0 ? Double(operations) / avg : .infinity diff --git a/bitchatTests/Performance/perf-floors.json b/bitchatTests/Performance/perf-floors.json index 751caf74..3426d105 100644 --- a/bitchatTests/Performance/perf-floors.json +++ b/bitchatTests/Performance/perf-floors.json @@ -34,6 +34,16 @@ "store.steadyStateAppend_before": 2315, "store.steadyStateAppend": 53976 }, + "_reference_local_numbers_2026_10": { + "geochat.peopleListColors_before": 112, + "geochat.peopleListColors": 406134, + "geochat.participantHeartbeat_before": 110, + "geochat.participantHeartbeat": 1581264, + "geochat.formatMessage_before": 107, + "geochat.formatMessage": 18006, + "hex.encodePublicKey_before": 64366, + "hex.encodePublicKey": 1194627 + }, "floors": { "nostrInbound.fresh": 450, "nostrInbound.duplicate": 250000, @@ -46,7 +56,11 @@ "pipeline.publicIngest": 2400, "store.append": 48000, "store.steadyStateAppend": 10000, - "store.audit": 70 + "store.audit": 70, + "geochat.peopleListColors": 40000, + "geochat.participantHeartbeat": 150000, + "geochat.formatMessage": 2500, + "hex.encodePublicKey": 250000 }, "_slowest_observed_ci_numbers_2026_06": { "nostrInbound.fresh": 918, @@ -60,5 +74,11 @@ "pipeline.publicIngest": 5006, "store.append": 97423, "store.audit": 140 + }, + "_slowest_observed_ci_numbers_2026_10": { + "geochat.peopleListColors": 212895, + "geochat.participantHeartbeat": 717459, + "geochat.formatMessage": 5176, + "hex.encodePublicKey": 655398 } }