2009-07-05 3 views
5

디스크에 파일을 읽고 쓰는 작은 프로그램이 있습니다. 가장 간단한 레벨로 분류하여 하나의 파일 스트림에서 바이트를 읽고 다른 파일 스트림에 씁니다. 그것의 임무를 잘 수행하지만 가장 빠른 것은 아니다..NET에서 디스크를 읽고 쓰는 가장 빠른 방법은 무엇입니까?

놀랍게도 기가 바이트 이상의 읽기/쓰기로 찢어 질 수있는 다른 응용 프로그램을 보았습니다. 분명히 그들은 조금 더. 닷넷 애플 리케이션보다 금속에 가까운 운영하고 있습니다.

디스크에서 스트리밍하는 데 가장 효율적인 .NET API는 무엇입니까? 신속한 디스크 액세스를 위해 사용할 수있는 Win32 API는 무엇입니까?

+3

왜 WinAPI 호출이 .NET 클래스보다 더 빠르지는 모르겠다. 후자는 전 내부적으로 사용한다. 그 외에도 메모리 매핑 파일 (http://en.wikipedia.org/wiki/Memory_mapped_file)이 아마도 적합할까요? – Noldorin

+0

Dot.net이 파일에 쓰는 방법이 두 가지 이상인 이유는 무엇입니까? 파일을 읽거나 쓰는 것은 꽤 기초적이며, "빠른"및 "느린"형식을 갖는 데는 아무런 의미가 없습니다. 둘 다 동일한 목표를 가진 "느린"버전을 사용하지 않으므로 말입니다. –

+0

30 분 안에 .net 파일 조작 (질문의 일부인 간단한 구현)과 집중 IO (QuickPAR 등)가있는 기본 응용 프로그램을 비교하여 .NET에서 문제를 해결할 수있는 테스트를 설정할 수 있습니다. 앱. 그 점이 문제입니다. .NET에서 최적의 디스크 처리량을 얻으려면 어떻게해야합니까? – Will

답변

10

빠른 파일 I/O는 사용자가 만드는 특정 API 호출에 대해서는 적지 만, I/O와 함께 작동하도록 응용 프로그램을 구성하는 방법에 대해서는 적습니다.

당신은 예를 들어, 순차적으로 단일 스레드에서 I/O 작업을 모두 수행하는 경우

    메모리에
  1. 프로세스 블록 메모리 어떻게 든
  2. 쓰기 블록 아웃에
  3. 읽기 블록 완료 될 때까지 당신이 사전 처리로 시스템의 I/O 대역폭 병목 있습니다 ...

  • 반복을 파일로 단일 스레드의 루프를 부른다. 대안이지만보다 복잡한 디자인은 처리량을 최대화하고 대기 시간을 피하기 위해 응용 프로그램을 다중 스레드하는 것입니다. 이를 통해 시스템은 CPU와 I/O 컨트롤러 대역폭을 동시에 이용할 수 있습니다. 작업자 스레드가 디스크에서 데이터를 읽고 공유 입력 큐
  • 하나 (또는 ​​그 이상)의 작업자 스레드가 공유에서 블록을 읽기에 추가

    1. 하나 (또는 ​​그 이상)이의 일반적인 디자인과 같을 것 입력 큐를 처리하고이를 공유 출력 큐에 추가합니다.
    2. 처리 된 하나 이상의 (또는 그 이상의) 작업자 스레드가 공유 출력 큐에서 차단되고 해당 출력 파일에 쓰여집니다.

    이것은 설계하기가 쉬운 아키텍처가 아니며, 메모리 내 잠금 경합을 피하기 위해 상당한 노력이 필요하거나 동시 I/O 요청으로 시스템을 압도합니다. 출력 처리 상태가 스레드의 호출 스택이 아니라 입/출력 작업 대기열에서 관리되도록 제어 메타 데이터를 제공해야합니다. 멀티 스레드 I/O를 사용하면 작업이 보장 된 순서로 입력 대기열에 배치 될 수 없으므로 출력을 올바른 순서로 변환하고 쓸 수 있어야합니다. 복잡하기는하지만 직렬 연결 방식보다 처리량이 크게 다를 수 있습니다.

    실제로 시간이 있고 시스템 성능을 최대한 늘리려는 경우 비교적 낮은 수준의 API 인 I/O completion ports을 사용하여 처리량을 극대화 할 수 있습니다.

    행운을 빈다.

  • 1

    디스크 입출력에 병목 현상이 있는지 확인하기 위해 응용 프로그램을 프로파일 링 했습니까?

    실행중인 하드웨어 유형은 무엇입니까? 하드웨어 구성이란 무엇입니까?

    .NET에서 System.IO.File 네임 스페이스를 사용해보십시오.

    Win32 함수의 경우 CreateFile, WriteFile, ReadFile 시리즈를 사용해보십시오.

    예 :

    http://msdn.microsoft.com/en-us/library/bb540534(VS.85).aspx

    이 확실히 잘라 건조되지 않습니다. 그것은 모두 테스트와 측정에 관한 것입니다.

    +0

    디스크 IO가 문제라면 개인적으로 * 매우 * 놀랄 것입니다 ... .NET 기본 요소 중 하나를 사용하여 디스크 입출력을 최대화하는 데 전혀 문제가 없었습니다. (아마도 .NET 1을 실행하지 않는 한 파일 스트림에 내장 된 버퍼가 없다고 생각합니다.) – jerryjvl

    +1

    질문은 방법에 관한 것이 아니라 얼마나 빠릅니다. System.IO.File (풍자, ftw)에 대한 팁 주셔서 감사합니다. – Will

    0

    BinaryReaderBinaryWriter은 적절한 버퍼 크기로 매우 빠릅니다. 구조체를 읽는다면 안전하지 않은 접근 방법으로 in this article을 사용하면 빨리 읽을 수 있으며 필기 방법도 비슷합니다. 또한 I/O가 실제로 병목 현상인지 다시 확인하라는 제안에 동의합니다. 나는 그런 실수로 인해 그 기사를 처음 보았습니다.

    6

    .NET 파일 지원이 충분히 빠릅니다 (기본 Win32 기능과 유사). 당신이 당신의 성능을 향상시킬 수있는 몇 가지 옵션 : 당신의 읽기/쓰기가 순차적

    1. 경우, 적절한 전략을 적용하여 캐시 관리자를 도와 - RandomAccess or SequentalScan을 제공하여 FileStream
    2. 인스턴스화 할 때 저장하기위한 큰 메모리 버퍼를 사용하는 것을 고려 데이터 읽기
    3. 여러 개의 작은 파일을 복사하는 경우 먼저 여러 파일을 한 번에 메모리 버퍼에 읽고 (2 참조) 디스크에 파일을 쓸 수 있습니다.
    4. 원본 및 대상 스트림이 서로 다른 위치에있는 경우 즉, 동일한 하드 드라이브에 있지 않고 네트워크상의 하나의 파일 일 수도 있고 다른 하나의 파일 일 수도 있습니다. 로컬 하드 드라이브 등)을 사용하면 비동기 패턴을 사용하여 속도를 높이고 BeginRead을 사용하여 데이터를 읽은 다음 BeginWrite을 사용하여 데이터를 쓸 수 있으며 데이터를 쓰는 동안 BeginRead를 사용하여 다음 데이터 블록을 읽습니다.
    5. 여전히 성능이 충분하지 않다고 생각되는 경우 (내 테스트에서 내부 Windows 복사본과 동등하거나 더 빠름) CopyFileEx Win32 함수를 사용할 수 있지만이 함수는 스트림이 아닌 파일에서 작동합니다.
    +1

    질문의 일부는 올바르게 사용하는 것입니다.이 대답은 적어도 달성하려고합니다. 감사. – Will