Skip to main content
Measure the model and integration on the CPU, operating system and resource limits you will deploy. Throughput measured on a quiet development machine is not a production capacity guarantee.

CPU requirements

The SDK runs inference on the CPU. Available operating-system and architecture builds vary by binding; check your language guide and the compatibility matrix. Model complexity, host-rate conversion, block adaptation, wrapper copies, concurrent streams and other workloads all contribute to CPU cost. Test smaller models if the larger variant exceeds your capacity budget. Choose by task quality as well as runtime cost using the evaluation guide.

Real-time guarantees

A serial processing path must keep pace with incoming audio. Define the frame budget and processing ratio as: frame_duration=block_sizesample_rate,ratio=processing_call_durationframe_duration\text{frame\_duration} = \frac{\text{block\_size}}{\text{sample\_rate}},\qquad \text{ratio} = \frac{\text{processing\_call\_duration}}{\text{frame\_duration}} A sustained ratio above 1 means that path cannot keep up. A ratio below 1 on average does not rule out deadline misses: inspect high percentiles, maximum duration and queue growth. Reserve capacity for capture, resampling, transport and downstream work. For example, 160 samples at 16 kHz represent 10 ms. This is an illustrative budget calculation, not a measured inference time.

Performance (CPU usage)

Changing the host sample rate can change conversion cost even when the model stays the same. Changing block size can change buffering and scheduling overhead. Keep both fixed when comparing model variants, then measure the actual production configuration separately. Distinguish audio delay from time spent computing a block. Reducing one does not prove that the other improved.

Parallel processing

In Python SDK 3.2.0, Processor.process() blocks its calling thread while native processing releases the Python interpreter lock. ProcessorAsync.process_async() schedules work on the native blocking pool so the event loop can continue. Use one instance per stream and await frames sequentially within each stream. More concurrent instances improve capacity only while the machine has resources to run them. Reuse loaded model weights where supported; each stream still owns processing state.

Async execution footguns

  • Submitting one stream concurrently: A mutex prevents simultaneous mutation but does not make submission order an audio-order guarantee. Await one frame before sending the next.
  • Unbounded work queues: Pending calls retain audio buffers and add waiting time. Bound admission and measure queue depth.
  • Reinitializing during processing: Stop input and settle in-flight work before changing configuration or resetting state.
  • Blocking the event loop with control calls: Create contexts during setup and keep initialization, synchronous teardown and other blocking work off the loop.
  • Treating cancellation as rollback: A cancelled await does not prove native work stopped. Follow the lifecycle guidance.

Run a bounded comparison

Use Python 3.12 or newer, an SDK key and a finite, non-silent mono WAV recording. The script below targets Python SDK 3.2.0/core 0.24.0 and compares one stream with two independent streams by running it twice. It measures call duration, scheduling lateness and process memory/CPU; it does not measure enhancement quality.
Set AIC_SDK_LICENSE through your normal secret mechanism. Save this as measure_runtime.py:
Run with a controlled recording, then compare the JSON results:
The file is repeated to fill the requested duration; the final incomplete input block is excluded. Warmup and model download are outside per-call timing. CPU percentage covers the process and can exceed 100% across cores; before/after resident memory is not peak memory. Record the CPU model and deployment CPU/memory limits alongside the output. For sustained-load validation, test your pipeline under deployment resource limits at the intended concurrency. This script holds at most one call per stream; measure queueing, drops, bypass and processing errors in your application. Stop runs that fall behind; their nominal stream count is not supported capacity.

Record and compare results

Retain the fixture hash, exact package/core/model versions, settings, hardware, resource limits and repetitions with each result. Report p50/p95/p99 and maximum call duration, deadline misses, queue depth, peak memory and output/error checks. Compare the same fixtures before and after an upgrade. Use the SDK benchmark example for further experiments and deployment verification for the release checklist. Every published number should identify what was measured and what the measurement excludes.