성능 평가 — MCU 타겟 및 서버 동시성¶
Xylolabs API — 종합 성능 평가 개정: 2026-03-23
1. XAP 코덱 벤치마크 결과¶
모든 측정은 Apple M 시리즈 호스트에서 --release 모드로 수행되었다. XAP 인코더는 crates/xylolabs-sdk/src/codec/xap.rs에 구현되어 있다. ADPCM 인코더는 crates/xylolabs-sdk/src/codec/adpcm.rs의 IMA-ADPCM 구현이다.
1.1 프레임당 인코딩 시간 — 모노, 10ms¶
| 샘플레이트 | 채널 | 샘플 수 | 프레임 | 평균 (us) | 최소 (us) | 최대 (us) | 예산 대비% |
|---|---|---|---|---|---|---|---|
| 8000 | 1 | 80 | 10ms | 0.5 | 0.4 | 12.7 | 0.005% |
| 16000 | 1 | 160 | 10ms | 1.1 | 1.0 | 1.2 | 0.011% |
| 24000 | 1 | 240 | 10ms | 1.9 | 1.6 | 6.8 | 0.019% |
| 32000 | 1 | 320 | 10ms | 3.0 | 2.6 | 9.0 | 0.030% |
| 48000 | 1 | 480 | 10ms | 512.3 | 451.1 | 700.0 | 5.123% |
| 96000 | 1 | 960 | 10ms | 1954.0 | 1763.8 | 2207.8 | 19.540% |
핵심 관찰 — 코사인 테이블 임계값: 32kHz (3.0 us)와 48kHz (512.3 us) 사이에 170배의 불연속이 존재한다. 이는 사전 계산된 코사인 테이블의 컷오프가 XAP_PRECOMPUTE_MAX_N = 320 샘플로 설정되어 있기 때문이다. N <= 320인 프레임(10ms에서 최대 32kHz)은 삼각함수 호출 없이 O(N^2) 테이블 검색을 사용한다. N > 320인 프레임(48kHz = 480, 96kHz = 960)은 MDCT 계수마다 런타임 cosf() 호출로 폴백하며, 이로 인해 속도가 대폭 저하된다.
실제 MCU 타겟에서 DSP 확장이 있는 경우, CMSIS-DSP의 arm_rfft_fast_f32가 이 전체 MDCT 경로를 대체하여 불연속이 제거된다. 호스트 벤치마크는 소프트웨어 전용 인코더 동작을 반영한다.
1.2 채널 스케일링 — 16kHz, 10ms¶
| 샘플레이트 | 채널 | 채널당 샘플 | 평균 (us) | 채널당 (us) | 스케일링 |
|---|---|---|---|---|---|
| 16000 | 1 | 160 | 1.0 | 1.0 | 1.00x |
| 16000 | 2 | 160 | 1.9 | 1.0 | 1.90x |
| 16000 | 3 | 160 | 2.8 | 0.9 | 2.80x |
| 16000 | 4 | 160 | 3.7 | 0.9 | 3.70x |
채널 스케일링은 준선형이다 (4채널에서 4.0배 대신 3.7배). 인코더는 공유 인프라(헤더 쓰기, 디인터리브)와 함께 채널을 독립적으로 처리한다. 채널당 MDCT 비용이 지배적이며, 약간의 준선형성은 헤더/설정 오버헤드의 분산에서 비롯된다.
1.3 4채널 스트레스 — 주요 샘플레이트¶
| 샘플레이트 | 채널 | 채널당 샘플 | 평균 (us) | 최소 (us) | 최대 (us) | 예산 대비% |
|---|---|---|---|---|---|---|
| 16000 | 4 | 160 | 3.6 | 3.2 | 4.6 | 0.036% |
| 48000 | 4 | 480 | 2004.7 | 1829.7 | 2378.2 | 20.047% |
| 96000 | 4 | 960 | 7930.9 | 7390.5 | 10632.4 | 79.309% |
4ch@96kHz 구성은 호스트에서 10ms 프레임 예산의 79.3%를 소비한다. XMBP 인코딩, I/O, 센서, 기타 작업을 위해 2.1ms만 남는다. DSP 가속이 있는 MCU 타겟에서는 MDCT가 하드웨어 가속 FFT 경로로 대체되어 37-56 MIPS로 감소한다(2절 참조).
1.4 프레임 길이 비교 — 48kHz, 2채널¶
| 샘플레이트 | 채널 | 프레임 길이 | 채널당 샘플 | 평균 (us) | 예산 대비% |
|---|---|---|---|---|---|
| 48000 | 2 | 7.5ms | 360 | 581.7 | 7.756% |
| 48000 | 2 | 10ms | 480 | 1007.6 | 10.076% |
7.5ms 프레임은 더 적은 샘플(360 vs 480)을 처리하여 절대 시간이 42% 빠르지만, 짧은 예산에서 더 높은 비율을 차지한다 (7.8% vs 10.1%). MCU 타겟에서는 10ms 프레임이 선호되는데, 더 긴 예산 창이 스케줄링 지터와 인터럽트 지연에 더 많은 여유를 제공하기 때문이다.
1.5 ADPCM 인코딩 시간 — 10ms¶
| 샘플레이트 | 채널 | 샘플 수 | 평균 (us) | 최소 (us) | 최대 (us) | 예산 대비% |
|---|---|---|---|---|---|---|
| 16000 | 1 | 160 | 0.93 | 0.83 | 7.21 | 0.009% |
| 16000 | 2 | 320 | 1.83 | 1.71 | 2.58 | 0.018% |
| 16000 | 4 | 640 | 3.70 | 3.50 | 10.21 | 0.037% |
| 48000 | 1 | 480 | 2.87 | 2.62 | 9.58 | 0.029% |
| 48000 | 2 | 960 | 5.68 | 5.38 | 12.33 | 0.057% |
| 48000 | 4 | 1920 | 11.56 | 10.79 | 19.67 | 0.116% |
| 96000 | 1 | 960 | 5.79 | 5.38 | 13.50 | 0.058% |
| 96000 | 2 | 1920 | 11.51 | 10.83 | 20.42 | 0.115% |
| 96000 | 4 | 3840 | 23.00 | 21.75 | 48.79 | 0.230% |
ADPCM은 모든 구성에서 비용이 매우 낮다. 4ch@96kHz에서도 23 us (예산의 0.23%)만 소비한다. 이는 ADPCM이 스펙트럼 변환 없이 순수 정수 산술을 사용하여 룩업 테이블로 샘플별 델타를 인코딩하기 때문이다.
1.6 XAP 대 ADPCM 비용 비율¶
| 구성 | XAP (us) | ADPCM (us) | 비율 |
|---|---|---|---|
| 1ch@16kHz | 1.0 | 0.93 | 1x |
| 4ch@16kHz | 3.6 | 3.66 | 1x |
| 4ch@48kHz | 2054.1 | 11.72 | 175x |
| 4ch@96kHz | 7973.9 | 22.91 | 348x |
저 샘플레이트(<=32kHz)에서 XAP과 ADPCM은 사전 계산된 코사인 테이블이 런타임 삼각함수를 제거하므로 비슷한 비용이다. 48kHz 이상에서 XAP은 런타임 cosf()를 사용하는 O(N^2) MDCT로 인해 175-348배 더 비싸다. MCU 타겟에서 DSP 가속 FFT 경로는 이 격차를 크게 좁히지만(약 20-40배), ADPCM은 CPU 제약 타겟에서 여전히 가장 가벼운 옵션이다.
2. MCU 실현 가능성 매트릭스¶
2.1 타겟별 최대 지속 가능 구성¶
PERFORMANCE-PROFILE.md 및 CODEC-ANALYSIS.md의 문서화된 MIPS 프로파일을 기반으로 평가하고, 벤치마크 측정값과 교차 검증했다. CPU%에는 코덱 인코딩, I/O 스택(I2S DMA, 전송 프로토콜, 센서 샘플링) 및 시스템 오버헤드가 포함된다. RAM%에는 SDK 클라이언트 상태, 코덱 버퍼, 링 버퍼, XMBP 프레이밍, 전송 스택 및 태스크 스택이 포함된다.
| 타겟 | 클럭 | SRAM | DSP/FPU | 최대 오디오 구성 | CPU% | RAM% | 판정 |
|---|---|---|---|---|---|---|---|
| RP2350 (Pico 2) | 150 MHz | 520 KB | M33 DSP+FPU | 4ch @96kHz XAP | 46.0% | 16.9% | 여유 |
| ESP32-S3 | 240 MHz | 512 KB + 8MB PSRAM | PIE SIMD+FPU | 4ch @96kHz XAP | 17.7% | 24.2% | 여유 |
| STM32F411 | 100 MHz | 128 KB | M4F DSP+FPU | 4ch @48kHz XAP | 40.0% | 34.4% | 적합 |
| nRF52840 | 64 MHz | 256 KB | M4F DSP+FPU | 2ch @48kHz XAP | 42.2% | 21.9% | 적합 |
| nRF9160 | 64 MHz | 256 KB | M33 DSP+FPU | 2ch @48kHz XAP | 44.5% | 21.9% | 적합 |
| STM32WB55 | 64 MHz | 256 KB | M4F DSP+FPU | 2ch @48kHz XAP | 42.2% | 17.2% | 적합 |
| RP2040 (Pico) | 133 MHz | 264 KB | 없음 | ADPCM 4ch @96kHz | 3.0% | 12.1% | ADPCM 전용 |
| ESP32-C3 | 160 MHz | 400 KB | M ext만 | ADPCM 4ch @96kHz | 2.5% | 8.0% | ADPCM 전용 |
| STM32F103 | 72 MHz | 20 KB | 없음 | ADPCM 2ch @24kHz | 1.4% | 80.0% | 센서 전용 |
2.2 판정 기준¶
| 판정 | CPU 사용률 | 의미 |
|---|---|---|
| 여유 (COMFORTABLE) | < 50% | 추가 처리, OTA 업데이트 또는 향후 기능을 위한 충분한 여유. |
| 적합 (FEASIBLE) | 50-70% | 신중한 스케줄링으로 안정적인 운영을 위한 충분한 여유. |
| 빡빡함 (TIGHT) | 70-85% | 운영 가능하나 최악의 인터럽트 지연에서 지터 발생 가능. |
| 한계 (MARGINAL) | 85-100% | 부하 시 프레임 드롭 위험. 프로덕션에 권장하지 않음. |
| ADPCM 전용 | 해당 없음 (XAP 불가) | DSP/FPU 없음; XAP 인코더 실행 불가. 4:1 압축 ADPCM만 가능. |
| 센서 전용 | 해당 없음 (오디오 제한) | 극심한 SRAM 제약. ADPCM 1-2ch + 센서 텔레메트리만 가능. |
2.3 타겟별 상세 CPU 예산¶
RP2350 (Pico 2) — 4ch XAP @96kHz¶
150 MHz 듀얼코어 Cortex-M33. Core 0은 I2S DMA + XAP 인코딩, Core 1은 XMBP + HTTP + 센서를 처리한다.
| 구성 요소 | 기준 MIPS | DSP MIPS | 150 MHz 대비% |
|---|---|---|---|
| I2S DMA 처리 | 2 | 2 | 1.3% |
| XAP MDCT 순방향 | 50 | 35 | 23.3% |
| XAP 양자화+패킹 | 15 | 10 | 6.7% |
| XMBP 배치 인코딩 | 5 | 5 | 3.3% |
| HTTP 전송 | 10 | 10 | 6.7% |
| 센서 샘플링 (26ch) | 5 | 5 | 3.3% |
| 워치독 + 기타 | 2 | 2 | 1.3% |
| 합계 | 89 | 69 | 46.0% |
| 여유 | 61 | 81 | 54.0% |
듀얼코어 분할 시: 시스템 사용률이 ~39.3%로 감소한다.
ESP32-S3 — 4ch XAP @96kHz¶
240 MHz 듀얼코어 Xtensa LX7 (총 480 MIPS).
| 구성 요소 | 기준 MIPS | PIE MIPS | 480 MHz 대비% |
|---|---|---|---|
| I2S DMA 처리 | 2 | 2 | 0.4% |
| XAP MDCT 순방향 | 50 | 20 | 4.2% |
| XAP 양자화+패킹 | 15 | 6 | 1.3% |
| WiFi 스택 (FreeRTOS) | 30 | 30 | 6.3% |
| XMBP 배치 인코딩 | 5 | 5 | 1.0% |
| HTTP/TLS 전송 | 20 | 12 | 2.5% |
| 센서 샘플링 (26ch) | 5 | 5 | 1.0% |
| PSRAM DMA 관리 | 3 | 3 | 0.6% |
| 워치독 + 기타 | 2 | 2 | 0.4% |
| 합계 | 132 | 85 | 17.7% |
| 여유 | 348 | 395 | 82.3% |
ESP32-S3는 MDCT 내부 루프의 128비트 PIE SIMD와 TLS를 위한 하드웨어 AES/SHA 오프로드 덕분에 가장 넉넉한 마진을 제공한다.
STM32F411 — 4ch XAP @48kHz¶
100 MHz 싱글코어 Cortex-M4F.
| 구성 요소 | 기준 MIPS | DSP MIPS | 100 MHz 대비% |
|---|---|---|---|
| I2S DMA 처리 | 2 | 2 | 2.0% |
| XAP MDCT 순방향 | 25 | 15 | 15.0% |
| XAP 양자화+패킹 | 8 | 5 | 5.0% |
| XMBP 배치 인코딩 | 3 | 3 | 3.0% |
| UART LTE-M1 전송 | 8 | 8 | 8.0% |
| 센서 샘플링 (26ch) | 5 | 5 | 5.0% |
| 워치독 + 기타 | 2 | 2 | 2.0% |
| 합계 | 53 | 40 | 40.0% |
| 여유 | 47 | 60 | 60.0% |
M4F FPU는 XAP 부동소수점 인코더 경로를 가능하게 하며, 이 코어에서는 고정소수점보다 빠르다. 4ch@96kHz는 권장하지 않는다(80% 사용률 초과).
nRF52840 — 2ch XAP @48kHz¶
64 MHz 싱글코어 Cortex-M4F.
| 구성 요소 | 기준 MIPS | DSP MIPS | 64 MHz 대비% |
|---|---|---|---|
| I2S DMA 처리 | 1 | 1 | 1.6% |
| XAP MDCT 순방향 | 12 | 7 | 10.9% |
| XAP 양자화+패킹 | 4 | 3 | 4.7% |
| BLE GATT 스택 | 10 | 10 | 15.6% |
| XMBP 배치 인코딩 | 2 | 2 | 3.1% |
| 센서 샘플링 (4ch) | 2 | 2 | 3.1% |
| 워치독 + 기타 | 2 | 2 | 3.1% |
| 합계 | 33 | 27 | 42.2% |
| 여유 | 31 | 37 | 57.8% |
BLE 스택 오버헤드가 코덱 외 가장 큰 소비자(15.6%)이다. 4ch@48kHz도 가능(~28 MIPS with DSP, 44% 사용률)하지만 여유가 최소화된다.
STM32F103 — 센서 전용 + ADPCM 폴백¶
72 MHz 싱글코어 Cortex-M3, 20 KB SRAM.
| 구성 요소 | MIPS | 72 MHz 대비% |
|---|---|---|
| ADPCM 인코딩 2ch @24kHz | 1 | 1.4% |
| XMBP 배치 인코딩 | 2 | 2.8% |
| UART LTE-M1 전송 | 8 | 11.1% |
| 센서 샘플링 (4ch) | 3 | 4.2% |
| 워치독 + 기타 | 2 | 2.8% |
| 합계 | 16 | 22.2% |
| 여유 | 56 | 77.8% |
XAP은 불가능하다: 4채널 인코더 상태 32 KB가 전체 SRAM 20 KB를 초과한다. 모노 XAP(인코더 상태 8 KB)조차 나머지 모든 것에 12 KB만 남긴다. ADPCM 2ch @24kHz가 실용적 최대 오디오 구성이다.
3. DSP/FPU 영향 분석¶
3.1 DSP 아키텍처별 속도 향상¶
| DSP 아키텍처 | 플랫폼 | 핵심 명령어 | XAP 속도 향상 | 메커니즘 |
|---|---|---|---|---|
| ARMv8-M DSP (Cortex-M33) | RP2350, nRF9160 | SMLAD 듀얼 MAC, QADD, SSAT | ~30% | 듀얼 16x16 MAC이 16비트 오디오에서 처리량을 2배로 증가. 포화 산술이 분기 기반 클리핑을 제거. 고정소수점 (Q15) 경로 선호. |
| Cortex-M4F FPU+DSP | STM32F411, STM32WB55, nRF52840 | FPU + SMLAD + SDIV | ~35-40% | 하드웨어 부동소수점 곱셈-누산이 1-3 사이클. 부동소수점 인코더 경로가 고정소수점보다 빠름. CMSIS-DSP arm_rfft_fast_f32로 MDCT를 3-5배 가속. |
| Xtensa PIE SIMD (ESP32-S3) | ESP32-S3 | 128비트 4x f32, 8x i16 | ~60% | 전용 128비트 레지스터에서 4-wide 벡터 연산. 하드웨어 AES/SHA가 TLS를 CPU에서 오프로드. 대형 버퍼 전송을 위한 PSRAM DMA. |
| DSP 없음 | RP2040, ESP32-C3, STM32F103 | 소프트웨어 곱셈만 | 0% (기준) | 모든 연산이 소프트웨어. SIMD 없음, 하드웨어 부동소수점 없음. XAP MDCT에 소프트웨어 cosf()가 필요하며 DSP 가속 FFT보다 10-50배 느림. |
3.2 MDCT 경로 선택¶
MDCT 순방향 변환은 인코더 핫 패스로, 총 XAP 인코딩 시간의 60-70%를 소비한다. SDK는 컴파일 시점에 최적 경로를 선택한다:
| 코어 | FPU | 컴파일 경로 | MDCT 전략 |
|---|---|---|---|
| Cortex-M33 (RP2350, nRF9160) | 단정밀도 | cmsis-dsp 피처 |
SMLAD 듀얼 MAC으로 고정소수점 Q15. Q15 형식의 사전 계산 코사인 테이블. |
| Cortex-M4F (F411, WB55, nRF52840) | 단정밀도 | cmsis-dsp 피처 |
arm_rfft_fast_f32로 부동소수점. 하드웨어 FPU가 부동소수점 경로를 고정소수점보다 빠르게 만듦. |
| Xtensa LX7 (ESP32-S3) | 단정밀도 | esp32-simd 피처 |
PIE 128비트 SIMD로 부동소수점. 벡터 명령어당 4개의 f32 값 처리. |
| Cortex-M0+ (RP2040) | 없음 | 기본 (DSP 없음) | 불가능. 소프트웨어 부동소수점 MDCT가 CPU 예산 초과. ADPCM만 가능. |
| Cortex-M3 (STM32F103) | 없음 | 기본 (DSP 없음) | 불가능. M0+과 동일. ADPCM만 가능. |
| RISC-V (ESP32-C3) | 없음 | 기본 (DSP 없음) | 불가능. M 확장이 정수 곱셈을 제공하지만 SIMD 없음. ADPCM만 가능. |
3.3 벤치마크 측정 코사인 테이블 영향¶
호스트 벤치마크에서 사전 계산된 코사인 테이블의 영향이 명확히 드러난다:
| 샘플레이트 | 프레임 샘플 | 테이블 사용 | 인코딩 시간 (1ch) | 비고 |
|---|---|---|---|---|
| 8 kHz | 80 | 예 | 0.5 us | O(N^2) 테이블 검색, 삼각함수 호출 없음 |
| 16 kHz | 160 | 예 | 1.1 us | O(N^2) 테이블 검색 |
| 24 kHz | 240 | 예 | 1.9 us | O(N^2) 테이블 검색 |
| 32 kHz | 320 | 예 (한계) | 3.0 us | 사전 계산 테이블의 최대 N |
| 48 kHz | 480 | 아니오 | 512.3 us | 계수당 런타임 cosf() -- 170배 느림 |
| 96 kHz | 960 | 아니오 | 1954.0 us | 런타임 cosf() -- 32kHz 대비 651배 느림 |
테이블 한계(XAP_PRECOMPUTE_MAX_N = 320)는 메모리 사용량을 200 KB 미만으로 유지한다 (51,200개 i32 항목 = 200 KB). 480으로 확장하면 (480/2)*480 = 115,200개 항목 = 450 KB가 필요하며, 이는 대부분의 MCU 타겟의 SRAM을 초과한다. MCU 타겟에서 CMSIS-DSP는 전체 MDCT를 하드웨어 가속 FFT로 대체하므로 이 테이블은 무관하다.
4. 메모리 예산 분석¶
4.1 타겟별 메모리 분석¶
모든 값은 KB 단위. 표시된 구성은 2절의 최대 권장 구성이다.
| 타겟 | SRAM | SDK+코덱 | 링 버퍼 | XMBP | HTTP | 스택 | 사용 | 여유 | RAM% |
|---|---|---|---|---|---|---|---|---|---|
| RP2350 (Pico 2) | 520 | 20 | 32 | 16 | 4 | 16 | 88 | 432 | 16.9% |
| ESP32-S3 | 512+8M | 20 | 64* | 16 | 8 | 16 | 124 | 388+ | 24.2% |
| STM32F411 | 128 | 20 | 8 | 4 | 4 | 8 | 44 | 84 | 34.4% |
| nRF52840 | 256 | 20 | 16 | 8 | 4 | 8 | 56 | 200 | 21.9% |
| nRF9160 | 256 | 20 | 16 | 8 | 4 | 8 | 56 | 200 | 21.9% |
| STM32WB55 | 256 | 20 | 8 | 4 | 4 | 8 | 44 | 212 | 17.2% |
| RP2040 (Pico) | 264 | 8 | 8 | 4 | 4 | 8 | 32 | 232 | 12.1% |
| ESP32-C3 | 400 | 8 | 8 | 4 | 4 | 8 | 32 | 368 | 8.0% |
| STM32F103 | 20 | 4 | 4 | 2 | 2 | 4 | 16 | 4 | 80.0% |
*ESP32-S3 링 버퍼는 DMA를 통해 PSRAM에 배치된다.
4.2 메모리 제한 시나리오¶
RP2350 (520 KB SRAM): 4ch @96kHz + 26개 센서 + HTTP = 88 KB (16.9%). 애플리케이션 로직, OTA 스테이징 버퍼 및 파일시스템을 위해 432 KB가 남는다. 넉넉한 SRAM 여유는 RP2350을 기능이 풍부한 배포에 가장 균형 잡힌 타겟으로 만든다.
STM32F411 (128 KB SRAM): 4ch @48kHz XAP = 44 KB (34.4%). 남은 84 KB는 애플리케이션에 적합하지만 OTA 스테이징 공간은 없다. 펌웨어 업데이트는 외부 플래시 또는 스왑 기반 부트로더를 사용해야 한다. 2ch@48kHz로 줄이면 사용량이 36 KB로 감소하여 8 KB가 확보된다.
nRF52840 (256 KB SRAM): 2ch @48kHz + BLE GATT 스택 = 56 KB (21.9%). SoftDevice BLE 스택 자체가 추가로 ~30 KB를 소비한다. SoftDevice 포함 시: 총 ~86 KB 사용, 170 KB 여유. BLE 기반 배포에 적합하다.
STM32F103 (20 KB SRAM): 센서 전용 ADPCM = 16 KB (80.0%). 애플리케이션 로직에 4 KB만 남는다. 이는 절대 최소 실행 가능 구성이다. 추가 센서 스트림 하나만 추가해도 신중한 스택 최적화가 필요하다. XAP은 완전히 불가능하다: 인코더 상태만으로 (채널당 8 KB, 4ch에 32 KB) 전체 SRAM을 초과한다.
ESP32-S3 (512 KB + 8 MB PSRAM): PSRAM이 가용 메모리를 대폭 확장한다. 오디오 링 버퍼(64 KB+)와 XMBP 배치 버퍼가 DMA 접근 가능한 PSRAM에 상주할 수 있어, 빠른 SRAM은 코덱 상태와 스택에 자유롭게 유지된다. 이로 인해 ESP32-S3는 메모리 압박 없이 4ch@96kHz를 초과하는 구성(예: 서라운드 모니터링을 위한 8ch@48kHz)을 실행할 수 있는 유일한 타겟이다.
5. 서버 동시성 평가¶
5.1 아키텍처 개요¶
Xylolabs API 서버는 Axum을 사용한 Tokio 비동기 런타임으로 구축되었다. 수집 파이프라인(crates/xylolabs-server/src/ingest/manager.rs)은 MCU 디바이스로부터 XMBP 배치를 처리하고, 메모리에 샘플을 버퍼링하고, spawn_blocking에서 zstd로 압축한 후, S3와 PostgreSQL로 플러시한다.
5.2 연결 매개변수¶
| 매개변수 | 값 | 비고 |
|---|---|---|
| 런타임 | Tokio 멀티스레드 | 워커 스레드 = CPU 코어 수 |
| DB 커넥션 풀 | 20 (기본, 설정 가능) | DATABASE_MAX_CONNECTIONS 환경 변수 |
| 세션당 메모리 | 스트림 버퍼당 ~1-4 KB | 누적 샘플 제외 |
| 업로드 본문 제한 | 최대 2 GB | 현재 전체 버퍼링 (스트리밍 아님) |
| SSE 라이브 연결 | 무제한 | 세션별 브로드캐스트 채널 |
| HTTP keep-alive | 75초 | Axum 기본값 |
| 인증 요청 제한 | IP당 분당 10회 | 인메모리 캐시, 60초 TTL, 10K IP 용량 |
| 수집 플러시 창 | 10초 (설정 가능) | S3 쓰기 전 샘플 누적 |
| 세션 타임아웃 | 300초 (설정 가능) | 비활성 세션 자동 종료 |
5.3 수집 파이프라인 처리량¶
| 단계 | 지연 시간 | 동시성 모델 | 비고 |
|---|---|---|---|
| XMBP 배치 디코딩 | 배치당 < 100 us | 인라인 비동기 | 순수 CPU, I/O 없음 |
| 샘플 버퍼링 | 샘플당 < 1 us | Mutex 보호 HashMap | 스트림별 Vec |
| 라이브 이벤트 브로드캐스트 | 이벤트당 < 10 us | broadcast::channel | 구독자가 있을 때만 |
| zstd 압축 | 청크당 ~200 us | spawn_blocking |
비동기 런타임에서 오프로드 |
| S3 업로드 | 청크당 ~5-20 ms | 비동기 I/O | 네트워크 바운드; MinIO 로컬 ~2 ms |
| DB 삽입 (청크 레코드) | 레코드당 ~1-2 ms | 비동기 sqlx | 플러시 창 내 배치 처리 |
| DB 통계 업데이트 | 배치당 ~1 ms | 인라인 비동기 | 배치당 단일 UPDATE |
코어당 추정 처리량: ~500 XMBP 배치/초 (CPU 바운드 단계는 ~200 us/청크의 압축이지만, 블로킹 풀로 오프로드됨).
5.4 동시 세션 용량¶
| 시나리오 | 세션 수 | 오디오 구성 | 센서 스트림 | 서버 CPU | DB 부하 | RAM |
|---|---|---|---|---|---|---|
| 경량 | 10 | 10 x 2ch @16kHz | 40 @100Hz | < 5% | 낮음 | ~40 KB |
| 표준 | 50 | 50 x 4ch @48kHz | 200 @100Hz | ~20% | 보통 | ~200 KB |
| 고부하 | 100 | 100 x 4ch @96kHz | 2600 @100Hz | ~60% | 높음 | ~400 KB |
| 한계 | ~200 | DB 풀 제한 | DB 풀 제한 | ~90% | 포화 | ~800 KB |
제한 요소는 PostgreSQL 커넥션 풀(기본 20)이다. 각 플러시 작업에 청크 INSERT를 위한 DB 연결이 필요하다. 100개 세션이 10초마다 플러시하면, DB 풀은 연결당 ~10 플러시 작업/초를 처리하며 이는 용량 내이다. 200개 이상의 세션에서 공격적인 플러시 간격 시, 풀 고갈이 병목이 된다.
5.5 동시성 위험 요소 — 식별 및 해결¶
| 문제 | 심각도 | 상태 | 해결 |
|---|---|---|---|
ConfigManager 비동기 컨텍스트에서 블로킹 RwLock |
P2 | 수정됨 | std::sync::RwLock에서 tokio::sync::RwLock으로 마이그레이션. 비동기 런타임에서 블로킹 락이 경합 시 스레드 기아 발생. |
| S3 실패 시 수집 플러시 데이터 손실 | P0 | 수정됨 | 이전에는 S3 쓰기 확인 전에 샘플을 드레인. 현재는 플러시 전 샘플을 복제; 실패 시 원본 유지하여 재시도. flushing 플래그가 동일 버퍼의 동시 플러시를 방지. |
list_uploads의 N+1 태그 쿼리 |
P1 | 수정됨 | 업로드당 태그 가져오기(1+N 쿼리)를 단일 JOIN 배치 쿼리로 교체. |
stats_overview 순차 쿼리 |
P2 | 수정됨 | 6개의 독립 COUNT 쿼리가 tokio::try_join!을 통해 동시 실행. |
| S3 전체 파일 버퍼링 업로드 | P1 | 미해결 | 2 GB 업로드 = 2 GB RAM. 백프레셔가 있는 스트리밍 멀티파트 업로드 필요. |
| 업로드 본문 메모리 버퍼링 | P1 | 미해결 | 큰 업로드 본문이 S3 쓰기 전 전체 메모리에 유지. 스트리밍 본문 처리 필요. |
| 연결 요청 제한 없음 (일반) | P3 | 미해결 | 인증 엔드포인트에 IP 기반 요청 제한(분당 10회) 있음. 일반 API 엔드포인트는 요청 제한 없음. |
mem::forget을 통한 파일 디스크립터 누수 |
P0 | 수정됨 | 임시 파일이 mem::forget으로 누수. 결정적 정리를 위해 into_temp_path로 수정. |
| 세션 락 경합 | P2 | 완화됨 | IngestManager.sessions는 tokio::sync::RwLock 사용. 개별 세션은 tokio::sync::Mutex 사용. 플러시 작업이 I/O 수행 전 세션 락 해제. 비활성 세션 확인은 세션 Mutex 잠금 없이 원자적 last_activity_ms 사용. |
5.6 남은 성능 위험¶
S3 전체 파일 버퍼링: 가장 중요한 미해결 문제. 단일 2 GB 업로드가 2 GB 서버 RAM을 소비한다. 10개의 대용량 동시 업로드 시 서버에 업로드 버퍼링만으로 20 GB RAM이 필요하다. 수정을 위해 경계된 메모리 버퍼와 클라이언트에 대한 백프레셔 신호를 사용한 스트리밍 멀티파트 업로드가 필요하다.
DB 풀 고갈: 기본 20개 연결 풀은 현재 플러시 간격에서 약 200개의 동시 세션을 지원한다. 이를 초과하면 플러시 작업이 풀 뒤에 대기하여 지연 시간과 샘플 버퍼 메모리가 증가한다. 풀 크기 증가는 해당하는 PostgreSQL max_connections 튜닝이 필요하다.
브로드캐스트 채널 무제한 구독자: SSE 라이브 이벤트 엔드포인트가 구독자 수 제한 없이 브로드캐스트 수신자를 생성한다. 악의적인 클라이언트가 수천 개의 SSE 연결을 열면 브로드캐스트 채널 버퍼로 메모리가 고갈될 수 있다.
6. 권장 사항¶
6.1 용도별 플랫폼 선택¶
| 용도 | 권장 플랫폼 | 코덱 | 최대 구성 | 근거 |
|---|---|---|---|---|
| 풀 스펙트럼 산업 모니터링 | ESP32-S3 | XAP | 4ch @96kHz | 82% 여유, 내장 WiFi, 대형 버퍼를 위한 PSRAM |
| 배터리 구동 현장 센서 | RP2350 (Pico 2) | XAP | 4ch @96kHz | 54% 여유, 최저 활성 전력 (25 mA), 듀얼코어 |
| 컴팩트 산업 노드 | STM32F411 | XAP | 4ch @48kHz | 60% 여유, 검증된 M4F 생태계, UART LTE-M |
| BLE 웨어러블 / 비콘 | nRF52840 | XAP | 2ch @48kHz | 58% 여유, BLE 전송, 초저전력 슬립 (1.5 uA) |
| 셀룰러 IoT (LTE-M) | nRF9160 | XAP | 2ch @48kHz | 55% 여유, 통합 LTE-M 모뎀 |
| BLE + Thread 메시 | STM32WB55 | XAP | 2ch @48kHz | 58% 여유, 듀얼 프로토콜 BLE + 802.15.4 |
| 음성 전용 / 레거시 센서 | STM32F103 | IMA-ADPCM | 2ch @24kHz | 78% 여유, ADPCM만, 20 KB SRAM 제한 |
| 저가 WiFi 센서 | ESP32-C3 | IMA-ADPCM | 4ch @96kHz | 98% 여유, ADPCM만, RISC-V, 내장 WiFi |
| 교육 / 프로토타이핑 | RP2040 (Pico) | IMA-ADPCM | 4ch @96kHz | 97% 여유, ADPCM만, 최저 비용 ($1) |
6.2 서버 스케일링 권장사항¶
| 부하 단계 | 세션 수 | 서버 구성 | DB 풀 | 비고 |
|---|---|---|---|---|
| 개발 | 1-10 | 단일 인스턴스, 2 CPU | 10 | 기본 구성으로 충분 |
| 소규모 배포 | 10-50 | 단일 인스턴스, 4 CPU | 20 | 기본 풀 적합 |
| 중규모 배포 | 50-200 | 단일 인스턴스, 8 CPU | 40 | 풀 증가, 플러시 지연 모니터링 |
| 대규모 배포 | 200-1000 | 다중 인스턴스 + LB | 60/인스턴스 | 스트리밍 S3 업로드 수정 필요, 수평 확장 |
| 엔터프라이즈 | 1000+ | Kubernetes 파드, 자동 확장 | 커넥션 풀러 (PgBouncer) | 모든 P1 문제 해결 필요 |
6.3 우선 엔지니어링 작업¶
-
P1 — 스트리밍 S3 업로드: 전체 파일 버퍼링을 스트리밍 멀티파트 업로드로 교체. O(파일크기) 메모리 소비 제거. 100 MB 이상 파일을 처리하는 모든 배포에 필수.
-
P1 — 스트리밍 업로드 본문: HTTP 본문에서 S3로의 백프레셔 인식 스트리밍 구현, 경계된 버퍼(예: 4 MB) 이상을 메모리에 유지하지 않음.
-
P2 — SSE 구독자 제한: 세션당 브로드캐스트 채널 수신자 제한(예: 100). 초과 시 429 반환.
-
P3 — 일반 API 요청 제한: 인증뿐만 아니라 모든 API 엔드포인트에 Tower 요청 제한 미들웨어 추가.
-
최적화 — 코사인 테이블 확장: 충분한 SRAM을 가진 타겟(PSRAM이 있는 ESP32-S3)에서
XAP_PRECOMPUTE_MAX_N을 480으로 확장하여 DSP 의존성 없이 48kHz 테이블 기반 인코딩 고려. 이는 48kHz 사용 사례의 170배 불연속을 제거한다.
7. 관련 문서¶
- 성능 프로파일 -- DSP 가속 매트릭스, 타겟별 CPU/메모리 예산
- 코덱 분석 -- 5개 MCU 플랫폼에서 16개 오디오 코덱 비교
- RP2350 실현 가능성 -- 4ch 96kHz 아키텍처, 상세 CPU/메모리 예산
- Pico 2 플랫폼 가이드 -- RP2350 하드웨어 설정 및 빌드
- STM32 플랫폼 가이드 -- F103/F411/WB55/WBA55 구성
- ESP32 플랫폼 가이드 -- S3/C3 WiFi, ESP-IDF 통합
- SDK 개요 -- Rust 우선 임베디드 SDK 아키텍처