피드로 돌아가기
I built a native C# Grep engine that's holding it's own with ripgrep (with zero allocations)
Dev.toDev.to
Backend

.NET 10 Zero-Allocation 설계를 통한 ripgrep 성능 능가

I built a native C# Grep engine that's holding it's own with ripgrep (with zero allocations)

Ian Cowley2026년 6월 9일4advanced

Context

AI Context Layer 구현 시 sub-20ms 실행 시간이 필수적이나, 외부 CLI 도구 호출에 따른 IPC 오버헤드와 Managed Heap 할당으로 인한 GC 부하가 성능 병목 지점으로 작용.

Technical Solution

  • System.IO.Enumeration.FileSystemEnumerable와 ref struct 활용으로 파일 경로 할당 없는 Stack 기반 파일 시스템 탐색 및 Trie 구조 기반 .gitignore 필터링 구현
  • 파일 크기에 따른 Hybrid I/O Dispatcher 도입으로 1MB 미만 소형 파일은 ArrayPool를 통한 Buffer Pool링, 1MB 이상 대형 파일은 MemoryMappedFile 및 unsafe byte* 포인터를 통한 커널 오버헤드 최소화
  • .NET 10 SearchValues 기반의 AVX-512/AVX2 SIMD 가속을 적용하여 UTF-8 Raw Byte 단위의 벡터화 스캔 수행
  • 매칭 발생 시 라인 분리 할당을 배제하고 바운더리 기반의 ReadOnlySpan 슬라이싱을 통한 Zero-Allocation 라인 추출
  • Model Context Protocol (MCP) 서버 구조 채택 및 System.IO.Pipelines와 Utf8JsonWriter 조합을 통한 매칭 결과의 Zero-Allocation 스트리밍 전송

Impact

  • 257.83 MB(590개 파일) 벤치마크 기준, Case-sensitive 검색 시 120.4ms를 기록하며 ripgrep(134.9ms) 대비 1.12x 성능 우위 확보

Key Takeaway

Managed Language 환경에서도 Mechanical Sympathy를 기반으로 Heap 추상화를 제거하고 CPU 레지스터와 메모리 레이아웃을 직접 제어함으로써 Native 수준의 성능 달성이 가능함.


- 고성능 스캔 로직 설계 시 String 대신 ReadOnlySpan<byte>와 UTF-8 Raw Byte 처리를 우선 검토할 것 - 파일 I/O 시 데이터 크기에 따라 Buffer Pool과 Memory-Mapped File을 선택적으로 사용하는 Dispatcher 패턴 적용 - 빈번한 객체 생성 구간에 ref struct와 ArrayPool을 도입하여 GC Pressure를 원천 차단할 것 - 하드웨어 가속이 가능한 SIMD 명령어 집합을 지원하는 최신 런타임 API(예: SearchValues) 활용

원문 읽기