# ADR-004: Use C++ for Selective Native Optimization

## Status
Proposed

## Context
Profiling identified ~80 functions in the Go codebase. Of these, only 4 functions showed significant syscall overhead that could benefit from native optimization:

| Function | Syscall Reduction | CGo Overhead Risk |
|----------|-------------------|-------------------|
| queue_index | 96% | Low (batch operations) |
| dataset_hash | 78% | High (per-file calls) |
| artifact_scanner | 87% | Low (single scan) |
| streaming_io | 95% | N/A (streaming) |

The key question is whether to implement all 4 libraries or focus on the highest ROI ones first, and how to manage the CGo overhead risk.

## Decision
We will implement **selective C++ optimization** for 4 specific libraries, prioritized by ROI (syscall reduction × operational simplicity).

**Phase 1: queue_index** (Highest ROI)
- 96% syscall reduction
- Natural batch operations minimize CGo overhead
- Heap-based priority queue in C++

**Phase 2: dataset_hash**
- Requires batching layer to amortize CGo overhead
- Single-file interface explicitly removed
- Only batch and combined interfaces exposed

**Phase 3: artifact_scanner**
- 87% syscall reduction
- Single scan operation (low CGo overhead risk)

**Phase 4: streaming_io**
- Simplified implementation: mmap + thread pool only
- **Explicitly excludes io_uring** (complexity exceeds benefit)

## Consequences

### Positive
- Significant syscall reduction (78-96%) for hot paths
- Maintains Go for business logic (fast iteration)
- Gradual implementation reduces risk
- Batch-first design amortizes CGo overhead

### Negative
- CGo boundary adds ~100ns per call
- Cross-platform complexity (Intel vs ARM SIMD)
- Additional build complexity (CMake, C++ toolchain)
- Runtime CPU feature detection required
- Two implementations to maintain (Go + C++)

## Options Considered

### Option 1: Pure Go Only
**Pros:** Simple build, single codebase, no CGo complexity  
**Cons:** Cannot achieve syscall reduction for file-heavy operations  
**Verdict:** Rejected - syscall overhead is the bottleneck

### Option 2: All Functions in C++
**Pros:** Maximum performance  
**Cons:** Most functions don't benefit; adds CGo overhead where not needed  
**Verdict:** Rejected - 4/80 functions show measurable benefit

### Option 3: Selective C++ (Chosen)
**Pros:** Focus on measurable wins, manageable complexity  
**Cons:** Need discipline to avoid CGo creep  
**Verdict:** Accepted - data-driven approach

## Risk Mitigations

### CGo Overhead Risk
- **Rule:** Native library ONLY used via batch interface
- **Enforcement:** Code review + benchmarks fail if CGo > 1% of runtime
- **Fallback:** Go implementation always available via build tags

### SIMD Cross-Platform Risk
- Runtime CPU feature detection (never assume)
- CI tests on both Intel and Apple Silicon
- Generic C++ fallback always compiled

### Zero-Allocation Discipline
- Hot path uses bump allocator with asserts
- ASan-enabled CI catches leaks
- Code review: any malloc/new in hot path requires justification

## Rationale

The 96% syscall reduction for queue_index alone justifies the C++ approach. The key discipline is **selectivity**: only functions with >75% syscall reduction and low CGo overhead risk are candidates. The simplified streaming_io (no io_uring) keeps operational complexity manageable while retaining 95% of the benefit.

The batch-first API design is mandatory, not optional. Single-file CGo calls are slower than Go stdlib due to boundary crossing overhead.
