BitChat Performance Characteristics: Benchmarks, Throughput Metrics, and Architectural Optimizations

BitChat achieves sustained throughputs of 11,000 BLE packets/sec for local mesh communication and 2,000 Nostr events/sec for global relay processing, with sub-millisecond latency for deduplication and filter operations.

The BitChat message routing system, maintained in permissionlesstech/bitchat, is engineered for high-throughput, low-latency communication across dual transport layers. Its performance characteristics emerge from a combination of zero-copy binary protocols, adaptive battery management, and carefully optimized data structures that minimize CPU and memory overhead on mobile devices.


Core Performance Goals and Design Philosophy

BitChat operates simultaneously on two network layers with distinct performance requirements:

  • Bluetooth LE mesh for local, offline-capable communication with tight latency budgets
  • Nostr protocol for global, censorship-resistant message relay

The architecture prioritizes fast local communication through a binary protocol that avoids memory copies wherever possible. In localPackages/BitFoundation/Sources/BitFoundation/BinaryProtocol.swift, the BinaryProtocol implementation uses Swift Data views to encode and decode packets without allocating new buffers.

Battery efficiency is equally critical. Adaptive battery modes dynamically throttle BLE scanning and transmission when devices are idle, extending operational time without sacrificing responsiveness when active.


Performance Baseline Benchmarks

The PerformanceBaselineTests suite in bitchatTests/Performance/PerformanceBaselineTests.swift establishes quantitative throughput floors for every critical code path. These benchmarks run in CI and enforce performance regressions via scripts/check-perf-floors.sh.

Nostr Inbound Processing

Benchmark Path Throughput
Nostr inbound (fresh events) Full processing: deduplication, geo-hash validation, scheduling ~2,000 events/sec
Nostr inbound (duplicate events) Fast-path deduplication without cryptographic operations ~30,000 events/sec

The 15x throughput differential between fresh and duplicate events highlights the cost of cryptographic validation and state management versus the O(1) deduplication check. The MessageDeduplicator stores compact 64-bit keys enabling constant-time duplicate detection.

BLE Mesh Communication

Benchmark Operation Throughput
BLE inbound packet pipeline Decode + deduplication of 100-300 byte packets ~11,000 packets/sec

This measurement covers the complete path from raw Data through BitchatPacket.from(_:) to deduplication key generation. The zero-copy binary protocol eliminates buffer allocations that would otherwise dominate latency.

Data Structure Operations

Benchmark What It Measures Throughput
GCS filter build & decode Golomb-Coded Set construction and parsing for 1,000 packet IDs ~140 filters/sec
Delivery status (coordinator) Incremental updates through DeliveryStatusCoordinator ~9,000 updates/sec
Delivery status (store direct) Direct ConversationStore updates ~13,000 updates/sec

The coordinator overhead reduces throughput by approximately 30%, reflecting the cost of cross-component synchronization versus direct store access.

Message Processing Pipelines

Benchmark Scope Throughput
Message formatting 200 messages with mentions, hashtags, URL detection ~1,000 messages/sec
Private ingest pipeline Full ChatViewModel path for private messages ~1,000 messages/sec
Public ingest pipeline Full path with 50 distinct senders ~900 messages/sec

Public message processing incurs slightly higher overhead due to sender validation and provenance tracking across multiple identities.

ConversationStore Performance

Benchmark Scenario Throughput
ConversationStore append 1,000 out-of-order inserts with ordering maintenance ~5,000 messages/sec
Steady-state append Append under 1,337-message retention cap with eviction ~12,000 messages/sec
ConversationStore audit Invariant validation over 5,000-message corpus ~80 audits/sec

The 2.4x throughput increase in steady-state operation reflects streamlined eviction paths versus the binary search and insertion overhead of out-of-order appends.


Architectural Optimizations

Zero-Copy Binary Protocol

The BinaryProtocol implementation at BinaryProtocol.swift#L84-L86 uses Data.subdata(in:) and withUnsafeBytes to parse packet fields without copying underlying bytes. This eliminates heap allocation pressure during high-frequency BLE operations.

LZ4 Compression

Outgoing BLE payloads undergo LZ4 compression, reducing transmission time and radio-on duration. The compression ratio typically achieves 2-3x reduction for text-heavy messages, directly improving battery life.

Noise Protocol Encryption

Mesh encryption uses the Noise protocol via NoiseEncryptionService.swift#L78, providing forward secrecy with minimal overhead. The handshake completes in single round-trip with small message expansion, unlike TLS which would require multiple exchanges and certificate overhead.

Golomb-Coded Set Filters

GCS filters enable bandwidth-efficient state synchronization between mesh nodes. Each filter represents 1,000 packet IDs in ~150 bytes, allowing nodes to identify missing messages with sub-millisecond set operations rather than transmitting full inventories.

Single-Source-of-Truth Store

All message state converges on ConversationStore, eliminating redundant indices. Ordered insertion uses binary search on a sorted array rather than tree structures, optimizing for cache locality and Swift's copy-on-write semantics.

Adaptive Battery Management

BLE scan intervals scale from continuous (active conversation) to 10-second windows (idle), reducing radio power consumption by up to 90% during quiescent periods without breaking mesh connectivity.


Running and Interpreting Benchmarks

Execute Performance Tests Locally


# Run complete suite including performance baselines

swift test

# Skip performance tests for faster iteration

BITCHAT_SKIP_PERF_BASELINES=1 swift test

# Capture structured performance output

BITCHAT_PERF_LOG=perf.log swift test --quiet --filter PerformanceBaselineTests

The BITCHAT_PERF_LOG environment variable triggers formatted output parsing by scripts/check-perf-floors.sh.

Parse Benchmark Output

cat perf.log | grep "PERF\[store.append\]"

# Output: PERF[store.append]: 5400 messages/sec (avg 0.185 ms per pass of 1000, 5 passes)

Interpretation:

  • Operations per pass: 1,000 append calls
  • Average latency: 0.185 ms per operation
  • Sustainable throughput: 5,400 operations/second

Direct Store Usage Pattern

import BitFoundation

let store = ConversationStore()
let message = BitchatMessage(
    id: "msg-\(UUID().uuidString.prefix(8))",
    sender: "alice",
    content: "Zero-copy mesh message",
    timestamp: Date(),
    isRelay: false
)

// O(log n) ordered insert with binary search positioning
store.append(message, to: .mesh)

This pattern mirrors the benchmarked path in testConversationStoreAppend at PerformanceBaselineTests.swift#L268-L304.

BLE Packet Processing Micro-Benchmark

import XCTest
@testable import bitchat

func measureBLEThroughput() {
    let deduplicator = MessageDeduplicator()
    let packets = (0..<1000).map { _ in generateRandomPacket() }
    
    let start = Date()
    for packet in packets {
        guard let data = packet.toBinaryData(),
              let decoded = BitchatPacket.from(data) else { continue }
        
        let key = dedupKey(packet: decoded)
        _ = deduplicator.isDuplicate(key: key)
    }
    let elapsed = Date().timeIntervalSince(start)
    
    print("Throughput: \(Double(packets.count) / elapsed) packets/sec")
}

This replicates the core measurement from testBLEInboundPacketPipeline at PerformanceBaselineTests.swift#L38-L44.


Key Source Files

File Purpose
bitchatTests/Performance/PerformanceBaselineTests.swift Complete benchmark suite with throughput floors
localPackages/BitFoundation/Sources/BitFoundation/BinaryProtocol.swift Zero-copy binary encoding/decoding
bitchat/Services/NoiseEncryptionService.swift Noise protocol mesh encryption
bitchat/ViewModels/ChatViewModel.swift Message ingest pipeline orchestration
scripts/check-perf-floors.sh CI validation of benchmark regressions
README.md High-level architecture and feature overview

Summary

  • BitChat achieves 11,000 BLE packets/sec for local mesh deduplication and decoding via zero-copy binary protocols
  • Nostr processing reaches 2,000 fresh events/sec (30,000/sec for duplicates) through optimized deduplication paths
  • ConversationStore sustains 5,000-12,000 appends/sec depending on ordering constraints and retention policies
  • LZ4 compression, Noise protocol encryption, and GCS filters collectively minimize bandwidth, latency, and battery consumption
  • Adaptive battery modes dynamically balance responsiveness against power efficiency
  • All performance claims are enforced in CI via PerformanceBaselineTests and check-perf-floors.sh

Frequently Asked Questions

What throughput can I expect for BLE mesh messaging?

Expect approximately 11,000 packets per second for packet decoding and deduplication on modern hardware. This covers the complete path from raw Data through BitchatPacket.from(_:) to duplicate detection. Real-world mobile performance is lower due to radio scheduling and OS constraints, but remains well within interactive latency budgets.

How does BitChat handle duplicate messages efficiently?

The MessageDeduplicator class provides O(1) duplicate detection using compact 64-bit keys stored in a hash set. Duplicate events bypass expensive cryptographic validation entirely, achieving 30,000 events/sec versus 2,000/sec for fresh events that require full processing.

Why is steady-state append faster than initial append in ConversationStore?

Steady-state append (12,000 messages/sec) operates under a fixed 1,337-message retention cap with streamlined eviction logic. Initial append (5,000 messages/sec) handles out-of-order inserts requiring binary search positioning and array expansion. The steady-state path avoids these ordering overheads.

How do I run performance benchmarks in my own environment?

Set BITCHAT_PERF_LOG=perf.log and execute swift test --filter PerformanceBaselineTests. The output includes formatted throughput lines like PERF[category.metric]: X ops/sec that scripts/check-perf-floors.sh can validate against expected floors defined in the test source.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →