mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 18:45:20 +00:00
Perf/optimizations (#563)
* Perf: reduce hot‑path overhead (logger autoclosure, zero‑copy BinaryProtocol.decode, prealloc encoders) * Compression: revert to zlib per request (compatibility) * Nostr: parse inbound messages off-main, then update state on main; BLE: debounce peer snapshot publishing to reduce churn * Fix: Swift 6 concurrency - avoid capturing self in detached tasks; deliver parsed Nostr messages via MainActor singleton * Fix: move ParsedInbound + parseInboundMessage to file scope (non-isolated) to satisfy Swift 6; update detached tasks to call free function --------- Co-authored-by: jack <jackjackbits@users.noreply.github.com>
This commit is contained in:
@@ -9,6 +9,7 @@ final class MessageDeduplicator {
|
||||
}
|
||||
|
||||
private var entries: [Entry] = []
|
||||
private var head: Int = 0
|
||||
private var lookup = Set<String>()
|
||||
private let lock = NSLock()
|
||||
private let maxAge: TimeInterval = TransportConfig.messageDedupMaxAgeSeconds // 5 minutes
|
||||
@@ -28,10 +29,18 @@ final class MessageDeduplicator {
|
||||
entries.append(Entry(messageID: messageID, timestamp: Date()))
|
||||
lookup.insert(messageID)
|
||||
|
||||
if entries.count > maxCount {
|
||||
let toRemove = entries.prefix(100)
|
||||
toRemove.forEach { lookup.remove($0.messageID) }
|
||||
entries.removeFirst(100)
|
||||
// Soft-cap and advance head by a chunk to avoid O(n) shifting
|
||||
if (entries.count - head) > maxCount {
|
||||
let removeCount = min(100, entries.count - head)
|
||||
for i in head..<(head + removeCount) {
|
||||
lookup.remove(entries[i].messageID)
|
||||
}
|
||||
head += removeCount
|
||||
// Periodically compact to reclaim memory
|
||||
if head > entries.count / 2 {
|
||||
entries.removeFirst(head)
|
||||
head = 0
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
@@ -61,6 +70,7 @@ final class MessageDeduplicator {
|
||||
defer { lock.unlock() }
|
||||
|
||||
entries.removeAll()
|
||||
head = 0
|
||||
lookup.removeAll()
|
||||
}
|
||||
|
||||
@@ -78,9 +88,13 @@ final class MessageDeduplicator {
|
||||
|
||||
private func cleanupOldEntries() {
|
||||
let cutoff = Date().addingTimeInterval(-maxAge)
|
||||
while let first = entries.first, first.timestamp < cutoff {
|
||||
lookup.remove(first.messageID)
|
||||
entries.removeFirst()
|
||||
while head < entries.count, entries[head].timestamp < cutoff {
|
||||
lookup.remove(entries[head].messageID)
|
||||
head += 1
|
||||
}
|
||||
if head > 0 && head > entries.count / 2 {
|
||||
entries.removeFirst(head)
|
||||
head = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,11 +140,11 @@ class SecureLogger {
|
||||
}
|
||||
|
||||
/// Log general messages with automatic sensitive data filtering
|
||||
static func log(_ message: String, category: OSLog = noise, level: LogLevel = .debug,
|
||||
static func log(_ message: @autoclosure () -> String, category: OSLog = noise, level: LogLevel = .debug,
|
||||
file: String = #file, line: Int = #line, function: String = #function) {
|
||||
guard shouldLog(level) else { return }
|
||||
let location = formatLocation(file: file, line: line, function: function)
|
||||
let sanitized = sanitize("\(location) \(message)")
|
||||
let sanitized = sanitize("\(location) \(message())")
|
||||
|
||||
#if DEBUG
|
||||
os_log("%{public}@", log: category, type: level.osLogType, sanitized)
|
||||
@@ -157,10 +157,10 @@ class SecureLogger {
|
||||
}
|
||||
|
||||
/// Log errors with context
|
||||
static func logError(_ error: Error, context: String, category: OSLog = noise,
|
||||
static func logError(_ error: Error, context: @autoclosure () -> String, category: OSLog = noise,
|
||||
file: String = #file, line: Int = #line, function: String = #function) {
|
||||
let location = formatLocation(file: file, line: line, function: function)
|
||||
let sanitized = sanitize(context)
|
||||
let sanitized = sanitize(context())
|
||||
let errorDesc = sanitize(error.localizedDescription)
|
||||
|
||||
#if DEBUG
|
||||
|
||||
Reference in New Issue
Block a user