· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
IO PerformanceHOWTO

I/O Performance HOWTO

Sharon Snider v1.1, 05/2002

Revision History Revision v1.1 2002-05-01 Revised by: sds

Updated technical information and links.

Revision v1.0 2002-04-01 Revised by: sds

Wrote and converted to DocBook XML.

This HOWTO covers information on available patches for the 2.4 kernel that can improve the I/O performance of your Linux™ operating system.

이 문서의 영문 원본은 다음의 위치에 있습니다.


번역 : hb_kim (at) hotmail.com

2003-12-11 ver 1.1-trans-0.1


1. 배포정책

The I/O Performance-HOWTO is copyrighted © 2002, by IBM Corporation

Permission is granted to copy, distribute, and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation with no Invariant Sections, no Front-Cover text, and no Back-Cover text. A copy of the license can be found at http://www.gnu.org/licenses/fdl.txt.


2. 소개

이 문서는 2.4 커널을 쓰는 Linux 오퍼레이팅 시스템의 I/O 성능을 개선하는데 대한 정보를 담고 있다. 추가적인 패치가 만들어지는대로 이 문서에 더해질것이다.

어떠한 제안이나, 이 문서에 도움이 될만한 내용이 있다면 Sharon Snider에게 e-mail을 보내주기를 바란다.


3. 바운스 버퍼의 사용을 피하기

이 장에서는 리눅스 2.4 커널에 바운스 버퍼 패치를 적용하고 사용하는 것에 대한 정보를 제공한다. Jens Axboe가 만든 이 바운스 버퍼 패치는 디바이스 드라이버들이 높은 주소의 물리적 메모리에 직접 DMA 를 수행할수 있도록 지원함으로써 바운스 버퍼의 사용을 피하게 해준다.

이 문서는 리눅스 커널에서의 메모리 어드레싱에 대해 간략하게 서술한뒤, 왜 바운스 버퍼 패치를 사용해야 하는지, 어떻게 사용해야 하는지를 알려준다.

3.1. 리눅스 2.4 커널에서의 메모리 어드레싱

리눅스 2.4 커널은 대상 컴퓨터의 물리적 메모리의 양을 지정할수 있는 제어 옵션이 있다. 기본값을 그냥 사용할때, 이 제어 옵션은 커널의 가상메모리 공간에 직접 매핑될수있는 메모리의 양을 지정하는것으로만 한정되어 있다. I386 시스템에서 기본 매핑 방법은 커널 모드에서 사용하는 메모리를 물리적 메모리에서 처음 1 기가 바이트로 제한한다. 이 처음 1 기가 바이트의 메모리를 낮은 주소의 메모리(low memory) 라고 부르기도 한다. 따라서 높은 주소의 메모리란 1 기가 바이스 이상의 주소를 가지는 메모리를 통칭하는것이다. 보통의 경우, 이 높은 주소의 메모리는 커널에 의해 직접적으로 액세스되거나, 영구적으로 매핑될수 없다. 이 높은 주소 메모리에 대한 지원 옵션은 리눅스 커널을 설정할때 켤 수 있다.


3.2. 바운스 버퍼의 문제점

이 높은 주소의 메모리에 DMA I/O 가 수행될때는, 낮은 주소의 메모리에 바운스 버퍼가 할당된다. 데이터가 디바이스와 높은 주소의 메모리 사이를 움직일때는 먼저 이 바운스 버퍼를 통해서 복사된다.

많은 양의 메모리를 가지고 있는 시스템에서 집중적인 I/O 를 수행하면, 이 바운스 버퍼가 낮은 주소의 메모리에 많이 필요하게 되므로 메모리의 부족 현상을 초래한다. 게다가 바운스 버퍼를 통한 데이터의 복사가 대량으로 발생하게 되므로 성능은 저하하게 마련이다.

PCI 디바이스는 보통 4 기가바이트의 물리적 메모리를 액세스할 수 있다. 바운스 버퍼가 4 기가바이트 이하의 주소를 갖는 높은 주소 메모리에 사용되는 경우에(역자주: 즉 1 기가바이트부터 4 기가바이트 사이에 있는 메모리), PCI 디바이스 자체가 직접 액세스 할수 있는 메모리 공간을 액세스하면서 바운스 버퍼를 거쳐서 사용함으로써, 시간과 메모리를 낭비하고 있는것이다. 바운스 버퍼 패치를 사용함으로써 이러한 바운스 버퍼의 사용을 최소화하거나 완전히 없애줄 수 있다.

3.3. 패치 다운 받기

이 바운스 버퍼 패치의 최신 버젼은 block-highmem-all-18b.bz2 이며, 다음 주소에 있는 Andrea Arcangeli's -aa 시리즈 커널에 있다.


3.3.1. 바운스 버퍼를 사용하지 않도록 리눅스 커널 설정하기

이 장에서는 바운스 버퍼를 사용하지 않도록 리눅스커널을 설정하는 방법을 다루고 있다. 리눅스 커널을 컴파일하는 방법에 대해서는 다음의 문서를 참조하도록.


다음과 같은 커널 설정 옵션을 켜야만 바운스 버퍼 패치를 사용할수 있게 된다.

Development Code : 설정 메뉴에서 높은 주소 메모리 사용옵션이 나오게 하려면, Code maturity level 항목에 가서 development and/or incomplete code/drivers 옵션을 켜야 된다.

High Memory Support : 1기가 바이트 이상의 물리적 메모리 지원을 가능하게 하기 위해서는, Processor type and features 항목에 가서 High Memory Support 옵션을 켠다.

High Memory I/O Support : 1기가 바이트 이상의 물리적 메모리에 대해 DMA I/O를 지원하기 위해서는, Processor type and features 항목에서 HIGHMEM I/O support 옵션을 "y"로 켜주어야 한다. 이 설정 옵션은 바운스 버퍼 패치로 인해 새로 생긴 옵션이다.

3.3.2. 이미 고쳐진 드라이버들

이 바운스 버퍼 패치들은 높은 주소 메모리의 DMA I/O 를 지원하기 위한 커널의 인프라스트럭쳐와 함께 변경된 SCSI와 IDE의 중간 레벨 드라이버를 포함한다. 또한 위에서 새롭게 추가된 지원 사항을 사용하도록 수정된 몇몇 디바이스 드라이버들도 포함되어 있다.

바운스 버퍼 패치가 적용되고, 커널을 높은 주소의 메모리에 I/O 가능하도록 설정하면, 많은 IDE 설정과 다음에 나열된 디바이스 드라이버들은 바운스 버퍼없이 DMA I/O 를 수행할수 있게 된다.

aic7xxx_drv.o

aic7xxx_old.o

cciss.o

cpqarray.o

megaraid.o

qlogicfc.o

sym53c8xx.o


3.4. 바운스 버퍼를 사용하지 않도록 디바이스 드라이버를 수정하는 방법

만약 당신이 사용하고 있는 디바이스 드라이버가 위의 수정된 디바이스 드라이버 목록에 포함되지 않았지만, 디바이스 자체는 높은 주소의 메모리에 DMA I/O 가 가능하다고 하면, 다음에 서술된 방법으로 당신이 직접 디바이스 드라이버를 수정해서 바운스 버퍼 패치를 적용하는것을 시도해 볼수도 있겠다. 리눅스 디바이스 드라이버에 대한 전반적인 정보가 필요하다면 다음의 링크를 참조하도록.



1. a. SCSI 어댑터의 드라이버: Scsi_Host_Template 구조체의 highmem_io 비트를 세트해줄것.

b. IDE 어댑터의 드라이버: ide_hwif_t 구조체의 highmem_io 비트를 세트해줄것.

2. pci_set_dma_mask(struct pci_dev *pdev, dma_addr_t mask) 를 호출해서, 그 디바이스가 DMA 로 액세스할수 있는 주소번지의 범위를 지정해줄것.

지정된 주소번지의 범위에 DMA I/O가 지원된다면 pci_set_dma_mask()는 pdev->dma_mask 값을 세트하고 0을 리턴한다. SCSI나 IDE 디바이스의 경우, 이 주소범위는 중간 레벨 드라이버에서 blk_queue_bounce_limit(request_queue_t *q, u64 dma_addr) 함수로 전달되서, 이 디바이스가 직접 액세스할수 있는 물리적 메모리를 액세스하는 경우에 바운스 버퍼가 생성되지 않도록 한다. SCSI나 IDE 드라이버가 아닌 경우에는 blk_queue_bounce_limit() 함수를 직접 호출해주어야 한다.

3. pci_map_single(dev, address, size, direction) 함수 대신에 pci_map_page(dev, page, offset, size, direction) 함수를 사용해서 디바이스가 직접 액세스할 수 있는 메모리 영역을 맵해준다. pci_map_page() 함수는 높은 주소의 메모리와 낮은 주소의 메모리를 모두 지원해준다.

pci_map_single() 함수에서의 주소 인자는 pci_map_page()의page 와 offset 파라메터로 변환될수 있다. virt_to_page() 매크로를 사용해서 주소를 page와 offset으로 변환해서 사용하도록. virt_to_page() 매크로를 사용하려면 pci.h 를 include 해야한다. 예로:

void *address;
 
struct page *page;
 
unsigned long offset;
 
page = virt_to_page(address);
 
offset = (unsigned long) address & ~PAGE_MASK;
DMA I/O가 완료되면 pci_unmap_page() 함수를 호출해서 pci_map_page() 함수로 생성한 매핑을 제거해야 한다.

  • pci_map_single() 함수는 virt_to_bus() 를 사용해서 구현되었는데, virt_to_bus()는 낮은 주소의 메모리만을 다룬다. 높은주소의 메모리를 지원하는 드라이버는 더 이상 virt_to_bus() 나 bus_to_virt()를 사용하면 안된다.


4. 드라이버가 pci_map_sg() 를 써서 scatter-gather DMA 를 매핑하고 있었다면, scatterlist 구조체의 address 필드를 사용하던 것을 page와 offset 필드를 사용하도록 고쳐야 된다.주소를 page 와 offset으로 변경하는 법은 위의 있는 단계 3 을 참조하도록.


  • 드라이버가 이미 PCI DMA API 를 사용하고 있었다면, 계속 pci_map_page()나 pci_map_sg()를 사용해도 좋다. scatterlist 구조체의 address 필드는 사용하지 말것.


4. Raw I/O 가변 크기 최적화 패치

이장은 리눅스 2.4 커널을 위한Badari Pulavarty 의 Raw I/O 가변 크기 최적화 패치에 대해서 설명한다. 이 패치는 RAW VARY 혹은 PAGESIZE_io 패치라는 이름으로도 알려져 있다.

이 Raw I/O 가변 크기 최적화 패치는 raw I/O 에 사용되는 블록의 크기를 hardsect_size(일반적으로 512 바이트)에서 4 KByte로 바꾸어준다. 이 패치는 raw I/O 수행에 필요한 버퍼 헤드의 수를 줄여줌으로써 I/O throughput과 CPU 활용도를 개선해준다.

4.1. 패치다운받기

다음 장소에서 이 패치를 다운받을수 있다.

Andrea Arcangeli 가 올려놓은 장소


파일의 이름은10_rawio-vary-io-1이다.

Alan Cox 는 이 패치를2.4.18pre9-ac2 커널 패치에 포함시켰다. 이것을 받으려면,



최신 버젼은PAGESIZE_io-2.4.17.patch 이다.

4.2. Raw I/O 가변 크기 최적화 패치를 사용하도록 드라이버를 수정하는법

이 패치의 이전 버젼에서는 모든 드라이버가 이 패치를 사용하도록 변경하였다. 하지만 2.4.17 이후의 버젼에서는 Adaptec, Qlogic ISP1020, IBM ServerRAID 드라이버에만 사용되도록 수정되었다. 2.4.17 이후 버젼의 패치를 설치한 후에, 위의 드라이버를 제외한 드라이버에서 이 패치의 내용을 적용하려면, Scsi_Host_Template 구조체의 can_do_varyio 비트를 세트하도록 수정되어야만 한다.


  • Raw I/O 가변 크기 최적화 패치를 사용하도록 수정된 드라이버는 반드시 한 I/O request에서 가변크기의(b_size) 버퍼헤드를 지원하도록 수정되어야 한다. 이는 데이터 버퍼가 4K 경계에 놓여있지 않으면 hardsect_size 가 사용되기 때문이다.


리눅스 디바이스 드라이버를 빌드하는데 필요한 추가적인 정보가 필요하다면 다음의 링크를 참조하도록.



5. I/O Request Lock 패치

이 장에서는I/O Request Lock 패치에 대한 정보를 제공한다. 이 패치는 Johnathan Lahr 가 작성한 것으로, SCSI 병렬 큐잉 패치(sior1)라는 이름으로도 알려져 있다.

I/O Request Lock 패치는 병렬 I/O 큐잉을 제공함으로써, 리눅스 2.4 커널을 쓰는 SMP 환경에서의 SCSI I/O의 성능을 향상시킨다. 멀티 프로세서 환경에서 여러개의 프로세서가 동시에 여러개의 블록디바이스들을 구동할수 있게 해줌으로써 I/O 성능과 CPU 활용율을 대폭으로 개선할 수 있다.

이 패치가 적용되기전에는, 블록 I/O request는 전역 spinlock을 잡고 있는 상태에서 하나씩 하나씩 차례로 큐에 추가되어졌다. 이 패치가 적용되면, SCSI I/O request는 이 I/O request에 해당하는 큐에 관련한 lock 만을 잡고 있는 상태에서 큐에 추가될수 있다. 따라서 서로 다른 디바이스에 해당하는 I/O request들은 동시에 큐에 추가될수 있다. 물론 같은 디바이스에 해당하는 I/O request들은 순차적으로 큐에 추가된다.

5.1. 패치 다운 받기

이 패치는 SourceForge 에서 받을수 있다.


최신 버젼은 sior1-v1.2416 이다. 또한 이 패치를 적용한 각 드라이버들도 SourceForge에서 받을수 있다. Emulex SCSI/FC 드라이버용 패치는 lpfc_sior1-v0.249 이며 Adaptec SCSI 드라이버용 패치는 aic_sior1-v0.249이다.




5.2. I/O Request Lock 패치를 사용하도록 드라이버를 수정하는 방법

이 I/O Request Lock 패치는 병렬 I/O 큐잉이 지원되는 SCSI 중간 레이어 드라이버를 설치한다. 이 병렬 I/O 큐잉은 각각의 SCSI 어댑터 디바이스 드라이버마다 활성화되어야 한다. 드라이버에서 이를 활성화 하려면, 드라이버가 등록될때 Scsi_Host_Template 구조체에서 concurrent_queue 필드를 세트해주면 된다.

  • 병렬 큐잉을 활성화하는 드라이버들은 request_queue 의 액세스가 request_queue.queue_lock에 의해서 보호되도록 구현되어야 한다.


리눅스 디바이스 드라이버를 빌드하는데 필요한 추가적인 정보가 필요하다면 다음의 링크를 참조하도록.



6. 참고문헌

다음에 열거하는 웹사이트들은 디바이스 드라이버를 변경하거나 리눅스 커널을 설정하는 것에 대한 추가적인 정보를 제공한다.


ID
Password
Join
Nobody expects the Spanish Inquisition!


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2008-12-12 13:25:44
Processing time 0.0088 sec