Comparing Filesystem Performance in Virtual Machines

Mitchell Hashimoto

가상 머신에서 파일시스템 성능 비교

수년 동안 Vagrant를 사용한 가상 머신 기반 개발 환경의 주요 병목 지점은 파일시스템 성능이었습니다. CPU 차이는 미미해서 거의 느낄 수 없고, RAM도 가상 머신이 여러 개 실행 중일 때만 문제가 됩니다.

저는 어제 하루의 대부분을 일반적인 파일시스템 메커니즘을 벤치마킹하고 분석하는 데 보냈습니다. 이제 그 결과를 여러분과 공유합니다.

결과 분석부터 시작하겠습니다. 대부분의 사람들이 가장 관심 있어 하는 부분이기 때문입니다. 테스트 방법, 사용된 소프트웨어, 그리고 원시 데이터는 이 분석 아래에서 확인할 수 있습니다.

아래의 모든 차트에서 우리는 파일을 읽거나 쓰는 방식을 테스트합니다. 각 그래프에서 읽거나 쓰는 파일의 총 크기는 고정되어 있습니다. Y축은 처리량(KB/s)이고, X축은 "레코드 크기", 즉 한 번에 읽거나 쓰는 데이터 청크의 크기(KB)입니다.

다양한 테스트 환경은 네이티브, VirtualBox 네이티브, VMware 네이티브, VirtualBox 공유 폴더(vboxsf), VMware 공유 폴더(vmhgfs), NFS입니다. "네이티브" 환경은 해당 환경에서 파일시스템을 단독으로 사용하는 것을 의미합니다. "네이티브"는 호스트 머신에서, "VirtualBox 네이티브"는 VirtualBox 가상 머신 내부의 루트 디바이스에서 사용하는 것을 말합니다. NFS는 VirtualBox와 VMware에서 성능 특성이 비슷해야 하므로 VirtualBox에서만 테스트했습니다.

모든 차트에서 처리량(Y축)이 높을수록 좋습니다.

작은 파일 순차 읽기

먼저 64KB 파일을 다양한 읽기 레코드 크기로 테스트한 순차 읽기 결과입니다. 작은 파일 순차 읽기의 실제 사례로는 애플리케이션을 실행, 컴파일 또는 테스트하기 위해 소스 파일을 로드하는 경우가 있습니다.

가장 먼저 눈에 띄는 것은 NFS의 읽기 성능이 작은 레코드 크기에서 놀라울 정도로 뛰어나다는 점입니다. NFS는 이러한 성능을 얻기 위해 적극적인 미리 읽기(Read-ahead) 작업과 캐싱을 수행하는 것 같습니다. NFS가 네이티브 가상 파일시스템보다 어떻게 더 나은 성능을 내는지에 대한 좋은 이론은 없습니다.

이 테스트에서 VMware 공유 폴더는 VirtualBox 공유 폴더를 완전히 압도합니다. VirtualBox 공유 폴더의 읽기 성능은 정말 형편없습니다. 원시 데이터를 보면 처리량이 실제로 100MB/s를 넘지 않는 반면, VMware는 500MB/s 아래로 내려가지 않고 900MB/s 이상으로 정점에 달합니다.

흥미로운 점은 가상 머신 내부의 네이티브 파일시스템이 호스트 머신의 네이티브 파일시스템보다 더 나은 성능을 보일 때가 있다는 것입니다. 이 테스트는 사용자 공간 버퍼링 없이 원시 read 시스템 호출을 사용합니다. 하이퍼바이저가 가상 머신에서 읽기를 버퍼링하기 때문에 네이티브 커널로의 컨텍스트 스위칭이 줄어들어 성능이 더 좋은 것일 가능성이 높습니다. 이 이론은 fread 벤치마크의 원시 결과 데이터를 보면 더욱 뒷받침됩니다. 그 테스트에서는 네이티브 파일시스템이 항상 가상 파일시스템을 이겼습니다.

대용량 파일 임의 읽기

이 테스트는 64MB 파일의 여러 부분을 무작위로 읽는 처리량을 측정한 것으로, 역시 다양한 읽기 레코드 크기로 테스트했습니다. 이 파일은 이전 테스트보다 1000배 더 큽니다. 이런 종류의 동작은 데이터베이스 읽기가 파일시스템에 닿을 때 발생할 수 있습니다.

VMware 공유 폴더와 VirtualBox 공유 폴더 간의 격차는 작은 파일 순차 읽기에 비해 상당히 넓어졌습니다. VirtualBox는 성능이 너무 나빠서 거의 보이지 않을 정도입니다. 역시 VirtualBox의 처리량은 100MB/s를 넘지 않습니다. 반면 VMware는 7GB/s로 정점을 찍습니다. 다양한 테스트 케이스에서 VirtualBox 처리량의 편차가 매우 작기 때문에, VirtualBox 공유 폴더 시스템의 단일 핫 패스(hot path) 코드가 이를 제한하고 있을 것이라고 추측합니다. 분명히 뭔가 잘못하고 있습니다.

NFS의 우위는 덜 두드러집니다. 아마도 이 테스트 케이스에서는 미리 읽기의 이점이 나타나지 않기 때문일 것입니다. 그럼에도 NFS는 다른 옵션에 비해 매우 좋은 성능을 보여줍니다.

그리고 작은 파일 순차 읽기와 마찬가지로, 가상 머신 내부가 외부보다 더 나은 성능을 보여주고 있습니다. 역시 이는 하이퍼바이저가 영리하게 버퍼링을 수행하기 때문이며, 호스트 머신에 대한 원시 시스템 콜은 이런 일이 일어나지 못하게 합니다.

작은 파일 순차 쓰기

작은 파일의 순차 쓰기 성능을 살펴보겠습니다. 이는 세션 상태, 임시 파일 저장 또는 새 소스 파일 작성 상황을 가장 정확하게 설명합니다.

가장 먼저 눈에 띄는 것은 NFS가 이런 종류의 쓰기에서 성능이 매우 나쁘다는 것입니다. NFS가 여기서 활용할 수 있는 실제 캐싱이 없기 때문에 네트워크 오버헤드에 대한 전체 비용을 지불하고, 호스트 측 디스크에 기록한 다음, 마지막으로 VM에 쓰기 성공을 알리는 ACK를 다시 기다려야 합니다. 아이고.

다양한 "네이티브" 파일시스템은 매우 좋은 성능을 보여줍니다. 다시 한번 가상 머신이 호스트보다 뛰어납니다. 그리고 다시 한번, 이는 하이퍼바이저의 버퍼링 덕분이라고 할 수 있습니다.

공유 파일시스템 간에는 큰 차이가 없지만, 이 테스트 케이스에서는 VirtualBox가 VMware보다 확실히 나은 성능을 보여줍니다.

대용량 파일 임의 쓰기

마지막으로 살펴볼 차트는 대용량(64MB) 파일에 대한 임의 쓰기 테스트 결과입니다. 대용량 임의 읽기 테스트와 마찬가지로 데이터베이스가 어떻게 성능을 보여줄지 확인하는 좋은 테스트입니다.

여기서는 작은 파일 순차 쓰기와 크게 다르지 않습니다. 대용량 파일이기 때문에 서로 다른 테스트 환경 간의 격차가 더 크지만, 그 외에는 결과가 대체로 비슷합니다.

NFS는 쓰기에서 여전히 형편없습니다. VirtualBox 공유 폴더는 쓰기에서 계속 VMware보다 나은 성능을 보여주고, 하이퍼바이저는 호스트 머신보다 뛰어납니다.

하이퍼바이저가 호스트 머신보다 나은 성능을 보여주는 것이 저에게 가장 흥미롭습니다. 이 테스트 결과는 하이퍼바이저가 성능을 위해 동기화 쓰기(synced writes)에 대해 거짓말을 하고 있음을 분명히 보여줍니다. 이는 Packer에서도 본 것과 일치합니다. 가상 머신이 정상적으로 종료되지 않으면 커밋된 쓰기가 손실되는 경우가 있었습니다. 가상 머신에서의 fsync()는 데이터가 호스트에 기록되었다는 의미가 아니라 하이퍼바이저 내에 커밋되었을 뿐입니다.

전체 분석

공유 파일시스템 측면에서는 VMware가 원하는 동작을 보여줍니다. 웹 페이지 로드, 테스트 스위트 실행, 소프트웨어 컴파일은 모두 읽기 작업이 매우 많습니다. VMware 공유 폴더의 읽기 성능은 VirtualBox를 압도하는 반면, VirtualBox 공유 폴더의 쓰기 성능은 VMware보다 아주 약간 나을 뿐입니다.

NFS를 사용할 수 있다면 사용하세요. 다시 말하지만, 읽기 성능이 쓰기 성능보다 훨씬 가치 있습니다.

하이퍼바이저의 읽기/쓰기 성능은 환상적입니다(속임수를 쓰기 때문입니다). 이 데이터 덕분에 저는 네이티브 파일시스템만 사용하는 Vagrant의 새로운 동기화 폴더 구현(예: rsync, 또는 호스트 머신을 서버가 아닌 NFS 클라이언트로 사용하는 방식)에 더욱 집중할 것입니다.

하지만 더 즉시 적용할 수 있는 조언이 있습니다. 개발용으로 가상 머신을 사용한다면, 가능하면 데이터베이스 파일을 공유 파일시스템 밖으로 옮기세요. 아마도 엄청난 성능 향상을 볼 수 있을 것입니다.

마지막으로, 이 결과에 큰 놀라움은 없다고 생각합니다. Vagrant는 2010년부터 NFS 동기화 폴더를 지원해 왔습니다. 우리는 초기에 공유 폴더의 성능이 나쁘다는 것을 깨달았기 때문입니다. 그러나 서로 다른 동작을 보여주는 확실한 데이터를 갖게 된 것은 좋은 일이며, 각 시스템이 무엇을 하고 있는지에 대한 흥미로운 통찰력을 제공합니다.

원문은 Mitchell Hashimoto님이 에 게재했습니다.

이 글은 deepseek-v4-flash 모델을 사용해 번역했습니다.