- lsr은 io_uring 기반 IO 라이브러리 ourio를 활용해 개발된 새로운 ls(1) 대체 프로그램
- 기존 ls 및 대안 도구(eza, lsd, uutils ls)에 비해 명령 실행 속도가 매우 빠르며, 시스템 콜 수도 10배 이상 적음
- 디렉토리 오픈, stat, lstat 등 모든 주요 IO를 io_uring으로 비동기·배치 처리하여 성능 극대화. 파일이 많을수록 더 빠름
- Zig의 StackFallbackAllocator를 활용해 메모리 할당 시 mmap 호출을 최소화함
- 동적 링킹 없이 정적으로 빌드해 실행 파일 크기까지 기존 ls보다 더 작음
소개 및 의의
- lsr 프로젝트는 일반 ls 명령어의 대체제로서 io_uring을 활용하는 빠른 디렉토리 리스팅 도구
- 기존의
ls,eza,lsd,uutils ls와 비교해, 실행 속도와 시스템 콜 사용량에서 탁월한 성능을 보임 - 직접 개발한 io 라이브러리(ourio)로 최대한 많은 IO를 직접 수행
- 벤치마크를 통해 lsr이 대규모 파일환경에서도 빠른 성능과 품질을 증명함
벤치마크 결과
hyperfine을 사용해 n개의 일반 파일이 있는 디렉토리에서 각 명령의 실행 시간을 측정lsr -al10–10,000개 파일 기준, 기존 ls/대체제 대비 월등히 짧은 실행 시간을 기록함- 예: 10,000개 파일에서 lsr이 22.1ms, 기존 ls(38.0ms), eza(40.2ms), lsd(153.4ms), uutils ls(89.6ms) 대비 최고의 속도를 기록
- 시스템 콜 집계는
strace -c로 진행lsr -al: 최소 20회(n=10)부터 최대 848회 (n=10,000)로 매우 낮은 콜 수 유지- ls는 최대 30,396회(n=10,000), lsd가 100,512회 등 나머지 대체제도 수천~십만 회 수준임
- 동일 조건에서 lsr이 최소 10배 이상 적은 syscall 수로 최고의 효율 달성
lsr의 구조와 구현 방식
- 프로그램은 인자 파싱, 데이터 수집, 데이터 출력의 3단계로 동작
- 모든 IO는 두 번째 데이터 수집 단계에서 발생하며, 가능한 모든 파일 접근/정보 조회를 io_uring으로 처리
- 타겟 디렉토리 오픈, stat, lstat, 시간/유저/그룹 정보 조회 모두 io_uring 기반으로 수행
- stat을 배치 처리하여 시스템 콜 수를 획기적으로 줄임
- Zig StackFallbackAllocator로 메모리 1MB를 사전 할당해 mmap 등 추가 시스템 콜을 최소화
정적 빌드와 최적화
- libc 동적 링킹 없이 완전 정적 빌드이므로 실행 오버헤드가 현저히 적음
- GNU ls 대비 lsr의 ReleaseSmall 빌드 사이즈가 138.7KB vs 79.3KB로 더 작음
- 단, lsr은 로케일(언어/지역) 지원이 없음. 일반 ls는 다양한 언어 지원을 위해 오버헤드 발생
시스템 콜 및 성능 이슈 분석
- lsd는 파일당 clock_gettime을 5번 이상 호출, 그 이유는 불명확(내부 타이밍 측정 등 추정)
- 정렬(sorting) 작업이 전체 작업 중 상당 부분(약 30%)을 차지함
- uutils ls는 시스템 콜 효율은 높으나 정렬 처리에서 느려짐
- io_uring 도입만으로도 서버 등 고부하 IO 환경에서 혁신적 성능 향상 가능성 확인
결론
- 개발 시간도 오래 걸리지 않고, syscall 최적화 효과가 기대 이상임
- lsr은 빠른 속도, 적은 시스템 콜, 간결한 크기를 동시에 달성하는 실험적 ls 대체제임
- 대용량 파일 환경이나 고성능 IO가 중요한 시스템에 매우 적합
- locale 미지원 등 일부 기능 한계가 있지만, 실무와 벤치마크 모두에서 혁신적인 결과를 보임