programing

Java NIO 파일 채널과 FileOutputstream의 퍼포먼스/유용성 비교

newsource 2022. 9. 28. 00:11

Java NIO 파일 채널과 FileOutputstream의 퍼포먼스/유용성 비교

nio를 할 때 장점.FileChannel과 비교하다FileInputStream/FileOuputStream파일 시스템에 파일을 읽고 쓸 수 있습니다.에서 두 모두 같은 되었고, 번 수준으로 작동한다는 것을 알게 . 또한 여러 번FileChannel길이 더 느리다.이 두 가지 방법을 비교해 좀 더 자세히 알 수 있을까요?여기 제가 사용한 코드가 있습니다.★★★★★★★★★★★★★★★★★★★★★★★,350MB랜덤 액세스나 기타 고도의 기능을 검토하고 있지 않다면 파일 I/O에 NIO 기반의 클래스를 사용하는 것이 좋은 옵션입니까?

package trialjavaprograms;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class JavaNIOTest {
    public static void main(String[] args) throws Exception {
        useNormalIO();
        useFileChannel();
    }

    private static void useNormalIO() throws Exception {
        File file = new File("/home/developer/test.iso");
        File oFile = new File("/home/developer/test2");

        long time1 = System.currentTimeMillis();
        InputStream is = new FileInputStream(file);
        FileOutputStream fos = new FileOutputStream(oFile);
        byte[] buf = new byte[64 * 1024];
        int len = 0;
        while((len = is.read(buf)) != -1) {
            fos.write(buf, 0, len);
        }
        fos.flush();
        fos.close();
        is.close();
        long time2 = System.currentTimeMillis();
        System.out.println("Time taken: "+(time2-time1)+" ms");
    }

    private static void useFileChannel() throws Exception {
        File file = new File("/home/developer/test.iso");
        File oFile = new File("/home/developer/test2");

        long time1 = System.currentTimeMillis();
        FileInputStream is = new FileInputStream(file);
        FileOutputStream fos = new FileOutputStream(oFile);
        FileChannel f = is.getChannel();
        FileChannel f2 = fos.getChannel();

        ByteBuffer buf = ByteBuffer.allocateDirect(64 * 1024);
        long len = 0;
        while((len = f.read(buf)) != -1) {
            buf.flip();
            f2.write(buf);
            buf.clear();
        }

        f2.close();
        f.close();

        long time2 = System.currentTimeMillis();
        System.out.println("Time taken: "+(time2-time1)+" ms");
    }
}

파일 사이즈가 커지면java.niojava.io. 매우 빨라졌습니다.250%를 넘는 범위입니다.단, 마이크로 벤치마크에 문제가 있을 수 있는 명백한 병목현상을 해소하고 있습니다.조사 대상 분야:

버퍼 사이즈기본적으로 가지고 있는 알고리즘은

  • 디스크에서 버퍼로 복사
  • 버퍼에서 디스크로 복사

제 경험으로는 이 버퍼 사이즈는 튜닝하기에 무르익었습니다.어플리케이션의 한 부분은 4KB, 다른 부분은 256KB로 정했습니다.당신의 코드가 그렇게 큰 버퍼로 인해 고통받고 있는 것 같습니다.버퍼가 1KB, 2KB, 4KB, 8KB, 16KB, 32KB 및 64KB인 벤치마크를 실행하여 직접 증명합니다.

동일한 디스크에 읽고 쓰는 Java 벤치마크를 수행하지 마십시오.

그렇다면 Java가 아니라 디스크를 벤치마킹하는 것입니다.또, CPU가 비지 상태가 아닌 경우는, 다른 병목 현상이 발생하고 있을 수 있습니다.

필요없으면 버퍼를 사용하지 마세요.

대상이 다른 디스크 또는 NIC인 경우 메모리에 복사하는 이유는 무엇입니까?파일이 클수록 지연 시간은 간단하지 않습니다.

말했지만, '하다'를 하세요.FileChannel.transferTo() ★★★★★★★★★★★★★★★★★」FileChannel.transferFrom()여기서 중요한 장점은 JVM이 OS의 DMA(Direct Memory Access)에 대한 액세스를 사용한다는 것입니다(이는 구현에 따라 다르지만 범용 CPU에 대한 최신 SunIBM 버전을 사용하는 것이 좋습니다).데이터는 디스크에서 버스로, 그리고 목적지로 바로 이동합니다.RAM 또는 CPU를 경유하는 회선을 바이패스합니다.

밤낮으로 작업한 웹 앱은 IO가 매우 무겁습니다.마이크로 벤치마크와 실제 벤치마크도 해봤습니다.결과는 제 블로그에 게재되어 있습니다.이것을 봐 주세요.

실가동 데이터 및 환경 사용

마이크로벤치마크는 일그러지기 쉽습니다.가능한 경우 예상되는 하드웨어에 대한 부하를 고려하여 계획한 작업으로부터 데이터를 수집합니다.

제 벤치마크는 견고하고 신뢰할 수 있습니다.왜냐하면 생산 시스템, 튼튼한 시스템, 부하가 걸리는 시스템, 통나무에 모아져 있기 때문입니다.JVM이 하드디스크를 실행하는 것을 주의 깊게 지켜보면서 노트북의 7200 RPM 2.5인치 SATA 드라이브가 아니었다.

뭐 하는 거야?그건 중요해.

비교 대상이 파일 복사 성능인 경우 채널테스트에서는 다음 작업을 수행해야 합니다.

final FileInputStream inputStream = new FileInputStream(src);
final FileOutputStream outputStream = new FileOutputStream(dest);
final FileChannel inChannel = inputStream.getChannel();
final FileChannel outChannel = outputStream.getChannel();
inChannel.transferTo(0, inChannel.size(), outChannel);
inChannel.close();
outChannel.close();
inputStream.close();
outputStream.close();

이것은 한 채널에서 다른 채널로 자신을 버퍼링하는 것보다 느리지 않고 잠재적으로 매우 빨라집니다.Javadocs에 따르면:

많은 운영체제는 실제로 바이트를 복사하지 않고 파일 시스템 캐시에서 타깃 채널로 직접 바이트를 전송할 수 있습니다.

테스트(Win7 64비트, 6GB RAM, Java6)에 따르면 NIO 전송은 작은 파일에서만 빠르고 큰 파일에서는 매우 느립니다.NIO 데이터베이스 버퍼 플립은 항상 표준 IO를 능가합니다.

  • 1000x2 복사MB

    1. NIO(transfer From) ~2300ms
    2. NIO(다이렉트 데이터베이스 버퍼 5000b 플립) 최대 3500밀리초
    3. 표준 IO(버퍼 5000b)~6000ms
  • 100 x 20 mb 복사

    1. NIO(다이렉트 데이터베이스 버퍼 5000b 플립)~4000밀리초
    2. NIO(transfer From) ~5000ms
    3. 표준 IO(버퍼 5000b)~6500ms
  • 1 x 1000 mb 복사

    1. NIO(다이렉트 데이터베이스 버퍼 5000b 플립) 최대 4500초
    2. 표준 IO(버퍼 5000b)~7000ms
    3. NIO(transfer From) ~8000ms

transfer To() 메서드는 파일 청크로 동작합니다.개요 수준의 파일 복사 방식은 아닙니다.Windows XP에서 대용량 파일을 복사하는 방법

질문의 "유용성" 부분에 대한 답변:

한 가지 미묘한 사용법이 있습니다.FileChannel에 걸쳐서FileOutputStream의 어느쪽인가를 하는 것을 「블럭킹 조작」).read() ★★★★★★★★★★★★★★★★★」write()인터럽트 상태에 있는 스레드로부터의)를 사용하면 채널이 와 함께 갑자기 닫힙니다.

이건 좋은 일이 될 수 있어FileChannel에 사용된 것은 스레드의 주요 기능의 일부이며, 설계에서는 이를 고려했습니다.

그러나 로깅 기능 등의 보조 기능으로 사용하면 번거로울 수도 있습니다.예를 들어, 로그 함수도 중단된 스레드에 의해 호출될 경우 로그 출력이 갑자기 닫히는 것을 발견할 수 있습니다.

유감스럽게도 이 문제를 설명하지 않으면 [1][2]쓰기 무결성에 영향을 미치는 버그가 발생할 수 있기 때문에 이 문제는 매우 미묘합니다.

File Input Stream과base64 인코딩된 파일을 디코딩하기 위한 FileChannel.제 경험에서 저는 꽤 큰 파일을 테스트했습니다.기존의 io는 nio보다 훨씬 더 빨랐습니다.

FileChannel은 여러 io 관련 클래스의 동기화 오버헤드로 인해 이전 버전의 jvm에서 이점을 누렸을 수 있지만, 최신 jvm은 불필요한 잠금을 제거하는 데 매우 능숙합니다.

transferTo 기능 또는 논블로킹 기능을 사용하지 않는 경우 기존 IO는 NIO에 매핑되므로 기존 IO와 NIO(2)의 차이를 알 수 없습니다.

단, transfer From/To 등의 NIO 기능을 사용할 수 있거나 Buffers를 사용할 경우 NIO를 사용하는 것이 좋습니다.

제 경험으로는 NIO는 작은 파일로 훨씬 더 빠릅니다.그러나 대용량 파일의 경우 FileInputStream/FileOutputStream이 훨씬 빠릅니다.

언급URL : https://stackoverflow.com/questions/1605332/java-nio-filechannel-versus-fileoutputstream-performance-usefulness