Linux환경에서 SSD 성능 최적화하기

1.
SSD가 대세입니다. SSD의 가격이 낮아지면서 속도를 원하는 일반 이용자들도 SSD를 사용합니다. CPU나 Ram을 늘리기 보다 SSD를 적용하면 체감속도는 휠씬 빠르다고 합니다. Low Latency를 원하는 트레이더들의 경우도 SSD는 기본입니다. 처음 SSD를 바라본 시각은 HDD의 대체재였습니다. HDD 보다 SSD를 이용하면 저장매체가 다르므로 당연히 빠릅니다. 딱 여기까지만 생각했습니다. 그런데 NHN 개발자 블로그에 올란 온 글을 보니 더 가야할 길이 있었습니다.

SSD는 소프트웨어 아키텍처를 어떻게 바꾸고 있는가?

오래전 알티베이스가 나오기 전에 Main Memory Database를 개발할 때 B-Tree 대신에 T-Tree를 써야 한다는 이야기를 들은 적이 있었습니다. 이와 같은 이치일 듯 합니다. 그렇지만 트레이딩 어플리케이션은 SSD를 Application Logging을 위해 사용하므로 위의 글을 적용할 수 필요가 없습니다.

SSD를 리눅스환경에서 최적화기 위해 어떤 노력을 하여야 하는지 이것 저것 찾아보았습니다. 아직 SSD를 사용하지 않으므로 직접 실험한 결과를 소개하지 못함을 이해바랍니다. 또한 아래의 글들로부터 많은 도움을 받았습니다.

How to maximise SSD performance with Linux
리눅스에서 SSD 세부조정

먼저 HDD와 SSD의 차이점입니다. 가장 쉽게 설명한 글입니다.

HDD(Hard Disk Drive)는 디스크라고 부르는 원형 금속판에 데이터를 저장하지만, SSD (Solid-State Drive)는 NAND flash 라는 메모리에 데이터를 저장한다. DRAM 에 저장하는 특수한 저장장치도 역시 SSD 라고 부르기도 하는데, 일반인이 구경할 일은 없다.1 그러므로, SSD 라 하면 flash 에 저장하는 것만 생각해도 무방하다.SSD는 읽고 쓰기가 아주 빠르고, 물리적 충격에 강하고, 가볍고, 전력 소모량이 적으며, 사이즈를 줄이는데도 용이한 점 등등 수많은 장점이 있다. 단, 용량에 비해 무지무지 비싸다는 단 하나의 단점만을 가지고 있다. 현재 2TB HDD 가 약 15만원인데, 64GB SSD 역시 그정도 가격이다. 즉, SSD 가 HDD 에 비해서 30 배 정도 비싼 셈이다.

SSD 는 저장 매체의 특성으로 쓰기(좀더 정확히는 다시쓰기,rewrite) 에서의 동작이 다르다. HDD 는 처음에 한번 포맷을 해두면, 데이터를 몇번이나 덮어서 다시 써도 문제가 없다. 그래서 데이터를 쓴 뒤, 삭제하기 위해서는 삭제하겠다고 마크만 해두면 되며, 그 위에 다시 다른 데이터를 써버리면 된다.

HDD 의 다시쓰기 방식:데이터 쓰기 -> 삭제한다는 마크 표시 -> 그 위에 덮어쓰기

하지만, SSD 는 데이터를 다시 쓰기 위해서, 반드시 그 영역을 깨끗히 삭제해주는 절차가 필요하다. 포맷 자체가 삭제하는 동작을 해주므로, 처음 사용시에는 문제가 없으나, 데이터를 지우고 다시 쓰는 경우에는 삭제해주는 작업를 해야 해서, 쓰기 속도가 느려진다. 하지만, 그래도 HDD 보다 빠르다.

SSD 의 다시쓰기 방식:데이터 쓰기 -> 삭제한다는 마크 표시 -> 데이터 삭제 -> 그 위에 다시 쓰기

SSD 에서 TRIM 은 무엇인가?중에서

이처럼 SSD는 미리 블럭을 비워놓지 않으면, 쓰기작업을 할때 블럭을 비우는 작업을 해야하기 때문에 쓰기 성능이 떨어집니다. 이런 단점을 해결하기 위하여 운영체제가 한가할 때 삭제한다고 표시한 데이터를 미리 비워 두도록 하는 기능을 만들었고 이를 TRIM이라고 합니다. TRIM은 읽기와 무관하고 오직 쓰기와 관계합니다. 또한 SSD가 TRIM을 지원하여야 하고 OS도 지원하여야 합니다. Linux의 경우 TRIM을 활성화하려면 다음과 같이 명령어를 실행합니다.

이제 TRIM을 OS와 SSD가 지원한다고 하면 File System을 Mount를 할 때 옵션을 추가해주어야 합니다.

2.
네트워크카드로 자주 만나는 후배와 SSD를 이야기하다 중요한 개념을 소개받았습니다. HDD와 SSD는 구조가 다르기때문에 I/O Scheduler가 무척 중요하다고 합니다. I/O Scheduler는 I/O Elivator라고도 합니다. 좋은 글을 많이 쓰시는 Mimul님은 다음과 같이 I/O Scheduler를 설명합니다.

I/O Scheduler는 Request Queue를 적절히 조작하여 seek time을 최소화하면서 global throughput을 최대화하는 것인데, 여기엔 merging과 sorting의 두개의 기본 동작이 쓰인다. 즉 request가 들어왔을때 큐에 이미 그 request가 있거나 이웃한 block에 대한 request가 있을때 두개의 request를 합치는 것이다. 또한 디스크의 seek를 줄이기 위해서 새로 들어온 request를 FIFO 방식으로 뒤에 붙이는것이 아니라 이미 기다리고 있는 request들 사이에 block번호에 따라 sorting된 상태가 되게끔 삽입해 넣는것이다. 이렇게 함으로써 디스크의 seek를 최소화하고 disk의 arm은 디스크를 왕복 횡단하면서 서비스를 할수 있게 된다. 그렇다고 해서, “굶고 있는(starving)” I/O request가 많아도 안된다. 적당히 공정성(fairness)을 유지해서, latency도 줄여주어야 한다. 이러한 모습은 마치 Elevator와 비슷하기 때문에 I/O Scheduler는 Elevator라고도 불린다.
디스크 IO 성능 – I/O 스케줄러중에서

Linux가 제공하는 Scheduler는 네가지입니다. Noop, Anticipatory, Deadline및 CFQ입니다. 이중 CFQ가 Linux의 기본 스케줄러입니다. Mimul님이 각각 자세히 설명해주고 있습니다. 이제 어떤 스케줄러를 선택하여야 할까요? Mimul님도 실험치를 소개하고 계시지만 저는 다른 실험치를 소개합니다.

먼저 시험 방법입니다.

a) untar kernel source
b) sync
c) copy kernel source tree
d) sync
e) copy tar file
f) sync
g) rm -rf kernel source tree
h) rm -rf copy of source tree
i) sync

이상의 시험방법에 따른 결과값입니다.

cfq: 3m59s, noop: 3m25s, anticipatory: 3m51s, deadline: 3m42s
Which I/O scheduler is best for SSD? 중에서

그러면 현재 사용중인 Linux의 Scheduler가 무엇이고 어떻게 변경하는지 알아보겠습니다.

변경은 아래와 같이 합니다.

SSD의 종류와 사용하고자 하는 목적에 따라 다를 수 있습니다. 용도에 맞는 방법론을 만들어 시험을 해보시길 바랍니다. 또 2012년 1월 SSD를 위한 새로운 I/O Scheduler가 나왔습니다. 이에 대한 실험도 해보시면 좋을 듯 합니다.

FIOS: A Fair, Efficient Flash I/O Scheduler – USENIX

3.
I/O Scheduler가 Read/Write와 관계가 있다고 하면 File System도 중요하지 않을까? 조사하니 Btrfs와 Ext4를 둘러싸고 다양한 의견들이 오고가고 있더군요. 그렇지만 많은 글이 Ext4를 추천하고 있습니다. 혹 사용 목적이 다를 수 있으므로 Phoronix한 결과를 보고 각자 평가를 해보시길 바랍니다.

Linux 3.7 File-System Benchmarks: EXT4, Btrfs, XFS

Linux를 설치할 때 파일시스템을 선택합니다. 이 때 Swap영역도 같이 생깁니다. Swap이 SSD의 성능에 영향을 줄 수 있다고 합니다. 만약 SSD외에 HDD를 같이 사용한다고 하면 SSD에 만들어진 Swap영역을 HDD로 옮기도록 권고합니다.

HDD가 없고 Ram의 크기가 클 경우 Swap기능을 꺼버릴 수도 있습니다.

Swappiness는 0부터 100까지 숫자이며, 리눅스가 메모리에서 디스크의 스왑 공간으로 데이터를 얼마나 적극적으로 이동 시키는 지를 나타낸다. 숫자가 높으면, 시스템이 메모리 부족시에 스왑으로 이동하는 것을 더욱 선호한다. 현재 swappiness 설정을 보려면 /proc/sys/vm/swappiness 파일의 내용을 보면 된다.

cat /proc/sys/vm/swappiness

SSD를 사용할때, 나는 swappiness를 항상 1로 설정했다. 스왑공간이 있지만, 가장 까다로운 상황을 빼고는 절대 사용하지 않을것이다. 다시말하면, 이것은 쓰기 회수를 줄여 디스크의 수명을 늘이자는 것이다. swappiness 값을 변경하려면 /etc/rc.local 파일에 아래 줄을 추가해라.

echo 0 > /proc/sys/vm/swappiness

/etc/rc.local 은 시스템 시작시, 다른 모든 초기화 스크립트가 실행된 후에 실행되는 파일이며, 다른 초기화 스크립트 안에 적용되지 않는 최적화를 위해 관리자가 사용하는 것이다.
리눅스에서 SSD 세부조정중에서

마지막으로 불필요하게 SSD에 쓰는 것을 막기 위하여 메모리파일시스템인 tmpf를 이용하는 것도 방법입니다. 하는 방법은 아래와 같습니다.

글을 글입니다. 적용은 여러분의 몫입니다. 다양한 실험을 해보고 자신에 맞는 최적화된 방법을 찾아야 합니다.

1 Comment

  1. smallake (Post author)

Leave a Comment

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.