Skip to content

shim9610/lockfreequeue

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lock-Free Queue

그냥 간단한 블로그 포스팅용 실험 입니다.

SPSC(Single Producer Single Consumer) Lock-Free Queue의 최적화 단계별 벤치마크 비교.

Rust와 C로 동일한 4단계 최적화를 구현하고, 정적/동적 버퍼 할당에 따른 성능 차이를 측정한다.

최적화 4단계

단계 이름 설명
1 basic modulo 연산, 매번 atomic load, 패딩 없음
2 padded + 캐시라인 패딩 (false sharing 방지)
3 cached + cached index (atomic load 절감)
4 masked + 비트마스킹 (modulo -> bitwise AND)

각 단계를 동적 버퍼(런타임 크기)와 정적 버퍼(컴파일 타임 고정 크기) 두 가지로 벤치마크한다.

프로젝트 구조

lockfreequeue/
├── src/
│   ├── main.rs          # 벤치마크 + 테스트
│   ├── buffer.rs        # Buffer trait + Static<T,N> / Dynamic<T>
│   ├── queue.rs         # 4모드 통합 구현 (basic/padded/cached/masked)
│   └── queue_proto.rs   # 초기 프로토타입 구현
├── C/
│   ├── include/
│   │   ├── lockfree_queue.h         # 동적 큐 4종
│   │   └── lockfree_queue_static.h  # 정적 큐 매크로 생성
│   ├── bench_main.c                 # C 벤치마크
│   └── Makefile
├── Cargo.toml
├── BENCHMARK.md     # 벤치마크 결과
└── sample.md        # 이전 블로그 포스트

Rust 설계

Buffer<T> trait으로 정적/동적 버퍼를 추상화하여, 같은 큐 코드로 두 가지 모드를 지원한다:

use buffer::{Static, Dynamic};

// 정적 — 컴파일러가 capacity를 상수로 알고 modulo 자동 최적화
let (mut p, mut c) = queue::cached::Queue::<u64, Static<u64, 1024>>::new().split();

// 동적 — 같은 push/pop 코드, 런타임 capacity
let (mut p, mut c) = queue::cached::Queue::<u64, Dynamic<u64>>::new(1024).split();

// 사용법은 동일
p.push(42);
let val = c.pop(); // Some(42)

Rust의 제네릭 + const generic으로 monomorphization되므로, trait 추상화에 의한 런타임 오버헤드가 없다.

C에서는 동일한 효과를 매크로 코드 생성으로 달성한다:

DEFINE_ALL_STATIC_QUEUES(1024)  // SBasicQueue_1024, SCachedQueue_1024, ... 생성

빌드 & 실행

요구사항

  • Rust: rustc (edition 2024)
  • C: gcc (C11 지원), pthread
  • OS: Linux 또는 Windows (MSYS2/MinGW-w64)

Rust

# 벤치마크 (release 모드, 5회 평균)
cargo run --release

# 테스트 (8개: 동적 4종 + 정적 4종)
cargo test

# Miri 동시성 안전성 검증
cargo +nightly miri test

C

cd C

# 직접 컴파일
gcc -std=c11 -O3 -Wall -pthread -o bench bench_main.c

# 또는 Makefile 사용 (make 설치 시)
make bench

# 실행
./bench

벤치마크 사양

  • 패턴: SPSC (Producer 1스레드 -> Consumer 1스레드, spin-loop 대기)
  • 아이템: u64 / uint64_t, 10,000,000개
  • 큐 용량: 64, 256, 1024, 4096, 65536
  • 측정: 5회 실행 평균 (M ops/sec, ns/op)
  • Rust 추가: rtrb 크레이트와 비교

자세한 결과는 BENCHMARK.md 참조.

주요 결과

  • cached index가 가장 큰 영향: ~4배 향상
  • 비트마스킹 추가로 ~3배 향상
  • 정적 버퍼가 동적 대비 3~5배 빠름 (컴파일러 modulo 자동 최적화)
  • 정적 cached > 동적 masked: 컴파일 타임 최적화가 수동 비트마스킹을 능가
  • C static cached (cap=65536): ~988 M/s (거의 1 GHz ops)

라이선스

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors