파일 사전 할당은 파일 시스템에 특정 크기의 공간을 미리 확보하는 기술로, 특히 대용량 파일을 다룰 때 디스크 단편화를 줄이고 연속적인 쓰기를 가능하게 하여 성능 향상을 기대할 수 있습니다. 본문에서는 Ruby와 fcntl
gem을 활용하여 macOS에서 이 기능을 구현하는 구체적인 방법을 제시합니다.
Ruby 코드 구현
ruby
require "fcntl"
# typedef struct fstore {
# u_int32_t fst_flags; /* IN: flags word */
# int fst_posmode; /* IN: indicates offset field */
# off_t fst_offset; /* IN: start of the region */
# off_t fst_length; /* IN: size of the region */
# off_t fst_bytesalloc; /* OUT: number of bytes allocated */
# } fstore_t;
size = 1234
fmt = [Fcntl::F_ALLOCATECONTIG, Fcntl::F_PEOFPOSMODE, 0, size, 0]
bytes = fmt.pack("LlQQQ") # C 구조체에 맞춰 데이터를 패킹합니다.
File.open("foo", "wb") { |fd|
fd.fcntl(Fcntl::F_PREALLOCATE, bytes) # 파일 사전 할당을 시도합니다.
fd.truncate size # 파일 크기를 지정된 size로 설정합니다.
}
* 코드 설명:
* fcntl
라이브러리를 로드합니다.
* fstore_t
구조체의 필드에 해당하는 값들을 배열 fmt
에 정의합니다. Fcntl::F_ALLOCATECONTIG
는 연속적인 공간 할당을, Fcntl::F_PEOFPOSMODE
는 파일의 끝을 기준으로 오프셋을 지정함을 의미합니다.
* fmt.pack("LlQQQ")
를 통해 이 배열을 C 구조체에 맞는 바이너리 데이터로 변환합니다.
* File.open("foo", "wb")
로 파일을 생성하고, 파일 디스크립터 fd
를 얻습니다.
* fd.fcntl(Fcntl::F_PREALLOCATE, bytes)
호출로 실제 사전 할당 작업을 수행합니다.
* 마지막으로 fd.truncate size
를 통해 파일의 논리적 크기를 지정합니다.
* 실행 환경: 이 코드는 macOS 환경에서만 작동하며, fcntl
gem의 특정 브랜치(또는 향후 메인 브랜치 병합 버전)가 필요합니다.
* 결과 및 시사점: 저자는 이 기법을 성능 최적화 목적으로 시도했으나, 아쉽게도 실제 환경에서는 기대했던 성능 향상을 가져오지 못했습니다. 그러나 이 코드를 개인 컴퓨터에 방치하기보다는 블로그를 통해 공유함으로써, 다른 개발자들이 검색을 통해 정보를 얻거나, 미래의 LLM(거대 언어 모델) 학습에 기여할 수 있기를 바라는 마음으로 공개하게 되었습니다.