Workload measurements

September 8, 2026 · View on GitHub

The image, history, and cancellation workloads passed under release optimization. The initial measurements below identified costs for follow-up; the final section records the resulting changes and a fresh before/after comparison. They were collected on arm64 macOS 26.5.1, Xcode 26.6, Apple Swift 6.3.3. Other development tooling was active, so the values are single-run observations rather than stable latency thresholds or a comparison with the previous release.

Reproduce with:

CODEXKIT_RUN_PERFORMANCE_TESTS=1 swift test -c release \
  --filter 'RealisticPerformanceTests|RuntimeSystemBenchmarkTests|RuntimePerformanceTests|SDKDesignTests'

All 16 selected tests passed. Correctness assertions verify results, bounded activation, distinct paged records, and cancellation. Timing is reported without machine-dependent pass/fail thresholds.

Image-heavy context

Each image is a distinct, valid 512×512 PNG containing deterministic high-entropy pixels, approximately 905 KiB. The history includes one user image and one assistant response per pair. Input provider state contains persisted image references. A stub HTTP turn measures request restoration/encoding and completion; compact processing also reads a response containing those images, retains their attachments, and externalizes the provider payload again. Logging is disabled.

ImagesAttachment bytesLargest encoded requestRequest + stub completionCompaction
1926,5101,257,365 bytes13.374 ms77.991 ms
43,709,7655,032,387 bytes27.546 ms338.520 ms
87,421,43510,066,944 bytes59.002 ms700.161 ms

At eight images, the process peak resident memory was 132,120,576 bytes (126 MiB). This includes XCTest, libraries, fixtures, requests, and decoded responses. It is a process-wide high-water mark, not the size of a retained SDK context or a per-request allocation measurement. Every compacted provider payload remained below 32 KiB and retained the expected number of attachments.

Image compaction was the largest measured processing cost here. The follow-up below reduces byte accumulation and reference-validation work. JSON decoding and base64 conversion remain possible profiling targets. These tests use local URLProtocol responses and include no provider inference or real-network latency.

Large database histories

Each database receives alternating user/assistant messages containing about 512 bytes of text. After reopening a new store instance, the workload hydrates at most 16 messages and retrieves five consecutive pages of 100 messages. It verifies that the newest message survives activation and that the 500 paged records contain no duplicates.

AdapterHistory recordsInitial writeActivation after reopenFive pages
SQLite2,000173.773 ms3.463 ms11.261 ms
SQLite20,0001,760.433 ms16.253 ms11.443 ms
Realm2,000532.172 ms5.951 ms14.209 ms
Realm20,0001,064.139 ms32.989 ms43.544 ms

Both adapters hydrated 16 messages at each size. Preparation runs before the activation/page timers. The initial-write timer covers creating the full saved history, not incremental production append throughput. Process memory during these tests includes the complete generated fixture array and database setup, so it does not establish steady-state runtime memory.

SQLite page retrieval stayed similar across the two sizes in this run. Realm page retrieval increased with history size; the follow-up below avoids sorting the full matching history for consecutive pages. A 20,000-record fixture does not establish behavior for arbitrarily large databases.

Slow-consumer cancellation

Both SDK queues have capacity one. The backend attempts 10,000 deltas, and cancellation is requested after the consumer receives its first delta. The consumer optionally pauses after each event.

Consumer delay per eventBackend producer stoppedConsumer finished draining
0 ms0.621 ms0.828 ms
25 ms0.092 ms103.715 ms
100 ms0.090 ms403.080 ms

Backend work stopped promptly in all three cases. Consumer completion includes its deliberate pauses and the bounded queued/lifecycle events. The persistent thread returned to idle in every case. These measurements exercise cooperative cancellation with a custom backend; they do not measure network-server cancellation or physical-device energy use.

Existing pipeline and parser checks

The HTTP-to-SQLite pipeline completed 100 turns and 5,000 deltas in 1.374 seconds, with 1.488 seconds of process CPU time. Retained context remained at eight messages and 16 history records. The parser completed the 8,000-fragment workload in 7.772 ms with one snapshot decode; its repeated-prefix comparison took 327.358 ms. See the earlier benchmark description for their construction and limits.

Physical-device energy and live-provider latency remain outside these measurements. The later concurrent lifecycle workload is recorded below.

Implemented performance follow-up

Compact responses now collect bytes in a reusable 64 KiB buffer before appending to Data. Exact response limits, truncated error-body handling, download cancellation, and network-error propagation remain enforced. Retained image references are validated by digest without constructing another expanded base64 JSON tree. Images continue to persist as disk attachments with references in provider metadata.

Realm now tries bounded primary-key reads for consecutive sequence windows used by ordinary history pages, unfiltered sequence queries, and activation. Missing rows or rows excluded by compaction/redaction filters fall back to the existing database query. Date sorting and additional filters retain their query paths. Cursor validation uses the history primary key, and existence checks stop at the first match instead of counting all matches. The schema and public API are unchanged.

A fresh baseline was collected immediately before these changes. The optimized verification run afterward passed all 16 performance/SDK tests:

WorkloadBefore this follow-upAfter this follow-upObserved reduction
Compact one image68.899 ms41.921 ms39%
Compact four images322.551 ms140.864 ms56%
Compact eight images543.972 ms280.348 ms48%
Realm: five pages, 2,000 records9.663 ms6.033 ms38%
Realm: five pages, 20,000 records44.577 ms9.219 ms79%

An earlier post-change run measured 288.148 ms for eight-image compaction and 9.204 ms for five Realm pages at 20,000 records. This supports the direction of the changes, but these runs are not a controlled statistical latency study. The before/after baseline above differs from the earlier audit measurements because it was rerun for this implementation pass.

The final eight-image process high-water mark was 132,218,880 bytes, approximately 126 MiB; no reduction in process peak memory is claimed. Realm activation at 20,000 records measured 30.667 ms versus 33.735 ms before, so the strong paging improvement should not be generalized to cold activation. Backend cancellation stopped in 0.101–0.119 ms across the three consumer delays, and the 100-turn pipeline completed in 1.161 seconds while retaining eight messages and 16 history records.

Eight new regression tests cover buffer boundaries, interrupted downloads, nested/invalid image references, paging parity across filters and directions, restored histories, empty histories, and sequence arithmetic near integer limits. Timing remains diagnostic; correctness assertions determine test success.

Verification after storage cancellation changes

After the storage-lock fix, the optimized selection passed all 26 tests: the 16 performance/SDK checks above plus ten new storage cancellation regressions. This run treated warnings as errors. Eight-image compaction measured 283.557 ms, and five Realm pages at 20,000 records measured 8.775 ms, close to the earlier improved results. The 100-turn pipeline completed in 0.859 seconds while retaining eight messages and 16 history records; backend cancellation stopped in 0.093–0.190 ms across the three consumer delays. These are local diagnostic observations, not a controlled throughput comparison or sustained contention benchmark.

Concurrent lifecycle verification

The expanded optimized selection passed 29 tests with warnings treated as errors. Its three new lifecycle tests each ran 40 waves using two runtimes and six conversations in one shared disk store. Every wave forced three completed turns, one interrupted turn, one completed compaction, and one cancelled compaction to overlap with a fresh database reader. Capacity-one queues and slow consumers exercised backpressure. Each wave compared saved messages, history sequences, images, lifecycle records, and compaction generations with an independent expected transcript. Both owning runtimes were replaced every four waves and reactivated their conversations before continuing.

AdapterLifecycle operationsReader reopensOwning-runtime replacementsWorkload duration
File2404020135.055 s
SQLite240402010.639 s
Realm24040206.025 s

These durations include full saved-state reads, assertion work, activation, and deliberate consumer delays; they are diagnostic observations of this workload rather than incremental-write throughput measurements. The complete optimized selection took 160.917 seconds after compilation. The tests use a local custom backend and cooperative cancellation; they do not establish live-provider compatibility, abrupt-crash recovery, minimum-OS support, or physical-device energy use. Verification instructions include the exact command, six-wave ordinary-suite default, and 1–200 wave configuration range.