# Swift Performance

## Finding

The optimized Swift facade is neutral or faster for the shared crypto
workloads. Identity import is 7.38% faster after removing the generic combined
record path; the cached public-key getter is 91.90% faster. Parse-and-verify is
6.96% slower at the median and 12.49% slower at p95, within the descriptive
10%/15% latency budgets and not reproduced as a native Rust regression.

The audit used three paired optimized processes on a GitHub-hosted arm64
`macos-15` runner with Swift 6.1.2. Values are nanoseconds per authored
`SoftchatKit` call. Negative deltas mean the current SDK is faster.

| Operation | Bytes | Old median ns | Current median ns | Delta | Current p95 ns | p95 delta |
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
| Import identity | 32 | 17,871 | 16,552 | -7.38% | 17,979 | -1.18% |
| Read cached public key | 0 | 247 | 20 | -91.90% | 20 | -92.22% |
| NIP-44 encrypt | 32 | 45,979 | 44,054 | -4.19% | 44,490 | -5.50% |
| NIP-44 decrypt | 32 | 43,587 | 43,153 | -1.00% | 43,286 | -6.57% |
| NIP-44 encrypt | 1,024 | 53,399 | 48,900 | -8.43% | 49,421 | -13.90% |
| NIP-44 decrypt | 1,024 | 52,602 | 48,059 | -8.64% | 48,727 | -13.77% |
| NIP-44 encrypt | 64,000 | 376,964 | 366,781 | -2.70% | 379,782 | -8.74% |
| NIP-44 decrypt | 64,000 | 386,037 | 366,391 | -5.09% | 406,401 | +4.27% |
| Sign NIP-01 event | 32 | 95,549 | 92,454 | -3.24% | 97,601 | +0.01% |
| Parse and verify event | 374 | 39,696 | 42,460 | +6.96% | 45,655 | +12.49% |

The 20-ns getter is an API-shape check, not a useful absolute latency claim.

## Current-only baseline

| Operation | Bytes | Median ns | p95 ns |
| --- | ---: | ---: | ---: |
| Create NIP-59 rumor | 15 | 4,897 | 4,947 |
| Create NIP-17 text message | 15 | 15,485 | 15,689 |
| Create durable gift wrap | 15 | 292,357 | 295,934 |
| Authenticate and unwrap | 15 | 173,322 | 173,632 |
| Stream-encrypt attachment | 64,000 | 681,080 | 687,838 |

## Optimizations retained

- `SoftchatIdentity` imports through the lightweight native constructor,
  caches its validated public key, and avoids the Android-only registry state.
- Encrypt and decrypt return or accept direct payload fields instead of
  round-tripping an aggregate generated record.
- Immutable Swift values own received events, messages, and metadata; native
  records do not leak into application layers.
- The identity lock protects handle lifetime and early erasure without making
  every public getter an FFI call.
- Streaming media uses bounded chunks and delays exposing decrypted output
  until authentication succeeds.

## Footprint

The performance harness links three unstripped dynamic libraries:

| Harness library set | Old bytes | Current bytes | Delta |
| --- | ---: | ---: | ---: |
| Rust + generated FFI + `SoftchatKit` | 2,425,336 | 4,895,304 | +101.84% |

This is a link-input measurement, not a shipped iOS application size. The
Swift package carries a static XCFramework so the final application linker can
dead-strip unused code. A release archive and dSYM measurement on physical iOS
is still required before setting an Apple footprint gate.

## Developer guidance

- Create one `SoftchatIdentity` for the authenticated session and retain its
  cached `publicKey`; do not recreate it per message.
- Call synchronous crypto and parsing from a bounded task or executor rather
  than the main actor. Do not add an `async` wrapper that hides unbounded work.
- Keep the identity as an ordinary ARC-owned reference. Call `erase()` only
  when authority must end early.
- Pass complete events, envelopes, relay frames, and attachment chunks through
  `SoftchatKit`. The generated FFI module is internal.
- Keep Keychain/Secure Enclave policy, `URLSession`, GRDB, background transfer,
  and application lifecycle in Swift.
- For extensions, create an independent session owner and close it explicitly;
  do not share callbacks or secret-derived state across process boundaries.

Run the shared and current-only audit with
`scripts/run-swift-performance.sh`, or dispatch the manual performance
workflow. Any facade, FFI, package, or native-profile change requires the
macOS package consumer and affected performance audit.

## Open work

The macOS source, DocC, XCFramework/SwiftPM build, and package consumer are
green. Remaining Apple evidence is an external application/archive/extension
integration, physical-iOS latency, startup and memory, and final archive/dSYM
footprint.
