본문 바로가기

OS/Windows

IOCP로 파일 I/O시 FILE_FLAG_NO_BUFFERING가 주는 효과는?

제프리 리처의 Windows via C/C++에 보면 IOCP에 대해 다루는 부분에서 파일 복사하는 것을 예제로 보여준다.

그런데 파일 읽고 쓰기를 위해 CreateFile 함수에서 핸들을 가져올 때, 6번째 인자 dwFlagsAndAttributes에 FILE_FLAG_NO_BUFFERING 플래그를 주는 것을 볼 수 있다.


이 플래그가 의미하는 것은 MSDN에 아래와 같이 나와있다.

The file or device is being opened with no system caching for data reads and writes.

데이터 읽기와 쓰기에 시스템 캐싱을 사용하지 않고 파일이나 장치를 연다.

This flag does not affect hard disk caching or memory mapped files.

이 플래그는 하드 디스크 캐싱이나 메모리 맵 파일들에 영향을 미치는 것은 아니다.

There are strict requirements for successfully working with files opened with CreateFile using the FILE_FLAG_NO_BUFFERING flag, for details see File Buffering.

FILE_FLAG_NO_BUFFERING 플래그를 사용해서 CreateFile로 여는 파일들에 대한 작업은 제한된 요구사항이 있는데 자세한 것은 파일 버퍼링 문서를 참고하라.

두 번째 줄을 생각해 보면 물리적인 하드디스크에 붙어 있는 캐시에 영향을 미치는 것은 아닌 것 같다. 단지 OS가 수행하는 캐시에 영향을 준다는 내용인 것 같다.

또한 세 번째 줄의 제한사항은 ReadFile이나 WirteFile을 사용할 때 단위의 크기를 디스크의 경우 볼륨 섹터의 크기로 수행한다는 것이다.

File access sizes, including the optional file offset in the OVERLAPPED structure, if specified, must be for a number of bytes that is an integer multiple of the volume sector size.

OVERLAPPED 구조체에 있는 추가적인 파일 오프셋을 포함한 파일 접근 크기는 반드시 볼륨 섹터 크기의 배수인 정수 바이트로 수행되어야 한다.

For example, if the sector size is 512 bytes, an application can request reads and writes of 512, 1,024, 1,536, or 2,048 bytes, but not of 335, 981, or 7,171 bytes.

예로, 섹터의 크기가 512바이트이면, 애플리케이션은 일고 쓰기 요청을 512, 1024, 1536, 2048 바이트로 해야지, 335, 981, 7171 바이트로 해서는 안된다.


이런 제약 조건으로 인해 FileCopy 예제에서는 64KB의 단위로 읽고 쓰기를 하다가, 남은 차이 만큼을 SetEndOfFile 함수를 이용하여 줄여주는 작업을 수행한다. 이 작업을 위해서는 FILE_FLAG_NO_BUFFERING를 사용하지 않고 파일 핸들을 다시 열어주는 작업이 필요하다.


FILE_FLAG_NO_BUFFERING 플래그를 사용하면 이런 번거로운 작업과 섹터 크기를 구하는 여분의 노력이 필요한데, 과연 성능은 얼마나 빠르게 할지 궁금해졌다.


FileCopy 함수 부분은 그대로 두고 앞뒤로 시간을 측정해서 얼마나 구하는지 벤치마킹을 해보았다.

64비트와 32비트로 각각 빌드를 했다.

x64.zip / x86.zip


결과는 아래와 같다.benchmark.xlsx


126MB (132,506,485 bytes) 64비트 32비트
  버퍼링 논버퍼링 버퍼링 논버퍼링
평균(최소/최대를 제외한) 0.090 5.450 0.091 5.365
1 0.096 5.761 0.366 5.231
2 0.088 5.356 0.093 5.529
3 0.087 5.466 0.090 5.206
4 0.090 5.700 0.088 5.533
5 0.090 5.258 0.089 5.109
6 0.104 5.565 0.087 5.566
7 0.091 5.209 0.091 5.142
8 0.087 5.616 3.403 5.531
9 0.092 5.217 0.095 5.131
10 0.085 5.511 0.090 5.486
11 0.090 5.116 0.091 5.212
12 0.093 5.467 0.088 5.531


버퍼링을 하는쪽이 버퍼링을 하지 않는 쪽보다 무려 약 60배나 빨랐다.

그럴 수 밖에 없는 것이 운영체제에서 버퍼링을 해준다면 읽고 쓰는 것을 반복 할 수록 사용자가 모르게 복제(shadow copy)를 해주면 성능이 좋을 수 밖에 없을 것이기 때문이다.

또한 복사가 제대로 되었는지 MD5 해시를 해서 복사가 잘 되었는지 체크를 했다. MD5Hash.exe

 그런데 프로그램의 수행속도가 버퍼링을 할 경우가 월등히 빨리 수행되었다. 운영체제 버퍼링이 다른 프로세스에도 영향을 미치는 것이었다.


또한 32비트로 비교할 때, 1번째와 8번째는 느려진 경우가 있었는데 아마 OS가 캐시하는 부분이 flush되지 않았나 추측해본다.


결론: FILE_FLAG_NO_BUFFERING 플래그는 성능을 더 떨어뜨린다.


인터넷의 글을 검색해보았는데 파일의 크기에 따라 조금 다르다고 한다.

흥배님의 블로그 : http://jacking.tistory.com/781 => (원문) http://d.hatena.ne.jp/wraith13/20080430/1209565632


그래서 크기를 9.03GB로 늘려서 수행해 보았다. 하지만 버퍼링하는 쪽이 더 빨랐다.

1.393 배 빠르다. (116.215초 , 약 2분)

버퍼링: 295.752초 (4분 55초.752)

넌버퍼링: 411.967초 (6분 51초.967)


참고로 큰 파일은 S-ATA에서 수행했고, 이전 126MB 복사는 SSD에서 수행했다.


'OS > Windows' 카테고리의 다른 글

[XP] Windows 악성 소프트웨어 제거 도구 - 2014년 5월  (0) 2014.05.14
Office 파일 버전관리 혹은 비교  (0) 2014.04.03
Windows XP 지원종료를 알림  (0) 2014.03.07
이름이 nul인 파일 지우기  (0) 2013.10.10
포트: LPR  (0) 2013.09.27