태그 보관물: java i/o

I/O 퍼포먼스 개선

자바에서는 자료를 읽거나 쓰기 위해 stream을 사용한다. 자바는 두가지 형태의 stream을 지원한다. Readers and Writers와 Input and Output stream이 그것이다. Reader and Writers는 high-level의 I/O(예. String)를 지원하고 Input and Output stream은 low-level의 I/O(byte)를 지원한다. 속도 향상을 위해서는 Buffered stream을 사용한다. Buffered stream을 사용할 경우 버퍼의 기본값은 2K이다. 이 값은 조정될 수 있으나, 자료의 용량이 클 경우 메모리가 많이 필요하기 때문에 Buffered stream을 사용할 경우 여러 가지 사항을 고려해야 한다.

예제1) Simple file copy

public static void copy(String from, String to) throws IOException{
  InputStream in=null;
  OutputStream out=null;
  try{
    in=new FileInputStream(from);
    out=new FileOutputStream(to);
    while(true){
        int data=in.read();
        if(data==-1)
          break;
        out.write(data);
    }
    in.close();
    out.close();
  }finally{
    if(in!=null){in.close();}
    if(out!=null){out.close();}
  }
}

Buffered stream을 사용하지 않고 I/O를 했을 경우의 예제이다. 370K의 JPEG 파일을 복사하는데 10800ms.

예제2) Faster file copy

public static void copy(String from, String to) throws IOException{
  InputStream in=null;
  OutputStream out=null;
  try{
    in=new BufferedInputStream(new FileInputStream(from));
    out=new BufferedOutputStream(new FileOutputStream(to));
    while(true){
      int data=in.read();
      if(data==-1)
        break;
      out.write(data);
    }
  }finally{
    if(in!=null){in.close();}
    if(out!=null){out.close();}
  }
}

Bufferd stream을 사용해서 퍼포먼스를 개선한 예제이다. 예제1)과 같은 파일을 복사하는데 130ms.

예제3) Custom buffered copy

public static void copy(String from, String to) throws IOException{
  InputStream in=null;
  OutputStream out=null;
  try{
    in=new FileInputStream(from);
    out=new FileOutputStream(to);
    int length=in.available();
    byte[] bytes=new byte[length];
    in.read(bytes);
    out.write(bytes);
  }finally{
    if(in!=null){in.close();}
    if(out!=null){out.close();}
  }
}

while 루프를 사용하지 않고 배열을 사용함으로서 퍼포먼스를 개선한 예제이다. 예제1)과 같은 파일을 복사하는데 33ms. 하지만 예제3)은 byte배열로 선언되는 메모리 버퍼의 크기가 실제 파일의 크기와 동일해야 한다. 이에 따라 두 가지의 문제점이 발생할 수 있다. 첫 번째는 파일의 용량이 클 경우 상당한 메모리 낭비를 초래한다는 점이다. 두 번째 문제점은 copy()메소드가 수행될 때마다 new byte[]에 의해 버퍼가 새로 만들어진다는 점이다. 만일 파일의 용량이 클 경우 버퍼가 만들어지고 Garbage Collector에 의해 수집될 때 상당한 OverHead를 초래할 수 있다.

예제4) Improved custom buffered copy

static final int BUFF_SIZE=100000;
static fianl byte[] buffer=new byte[BUFF_SIZE];
public static void copy(String from, String to) throws IOException{
  InputStream in=null;
  OutputStream out=null;
  try{
    in=new FileInputStream(from);
    out=new FileOutputStream(to);
    while(true){
      synchronized(buffer){
        int amountRead=in.read(buffer);
        if(amountRead==-1)
          break;
        out.write(buffer,0,amountRead);
      }
  }finally{
    if(in!=null){in.close();}
    if(out!=null){out.close();}
  }
}

크 기가 100K인 byte 배열을 임시버퍼로 지정하고, 이를 static으로 선언함으로서 퍼포먼스를 개선했다. 예제1)과 같은 파일을 복사하는데 22ms. static buffer의 사용으로 I/O작업을 수행할 경우 발생할 수 있는 문제점을 해결하기 위해 synchronized block을 사용했다. 비록 synchronization을 사용함에 따라 성능 저하를 초래하지만, 실제 while 루프에 머무는 시간이 극히 짧기 때문에 퍼포먼스에 문제는 없다. 테스트에 의하면 synchronized 버전과 unsynchronized 버전 모두 같은 시간에 수행을 완료했다.

Java I/O 성능 향상을 위한 버전(JVM)별 내용

현재 까지 나온 Java 6.0 까지의 I/O 성능향상을 위한 Sun의 작업내역을 보실수가 있네요.. ^^
제가 보기에 Java 6의 가장 큰 이슈는 SelectorProvider가 Linux epoll 기법(IOCP와 비슷)을 지원한다는 것입니다.. 대충 찾아보니.. 여러개의 버그가 리포팅이 되어 있긴 하지만, 추후 대용량 처리를 위해서는 좋은 모습인거 같습니다. ^^
출처는 http://java.sun.com/javase/6/docs/technotes/guides/io/enhancements.html 입니다…..

Enhancements in Java SE 6


java.io


One new class is provided:



  • Console – Contains methods to access a character-based console device. The readPassword() methods disable echoing thus they are suitable for retrieval of sensitive data such as passwords. The method System.console() returns the unique console associated with the Java Virtual Machine.

The following new methods were added to File:



Constructors were added to the following class:



The behavior of the following method was modified:



  • The File.isFile() Windows implementation has been modified to always return false for reserved device names such as CON, NUL, AUX, LPT, etc. Previously it returned true, which customers considered a bug because it was inconsistent with behavior for devices on Unix.

java.nio



  • A new java.nio.channels.SelectorProvider implementation that is based on the Linux epoll event notification facility is included. The epoll facility is available in the Linux 2.6, and newer, kernels. The new epoll-based SelectorProvider implementation is more scalable than the traditional poll-based SelectorProvider implementation when there are thousands of SelectableChannels registered with a Selector. The new SelectorProvider implementation will be used by default when the 2.6 kernel is detected. The poll-based SelectorProvider will be used when a pre-2.6 kernel is detected.
  • The system property sun.nio.ch.disableSystemWideOverlappingFileLockCheck controls whether java.nio.channels.FileChannel.lock() checks whether regions are locked by other instances of FileChannel. Unless this system property is set to true, FileChannel.lock() will throw an OverlappingFileLockException if an application attempts to lock a region that overlaps one that is locked by another instance of FileChannel. The system property exists to provide compatibility with previous releases which do not implement the JVM-wide overlapping file lock check.

Enhancements in J2SE 5.0


java.nio



  • Class javax.net.ssl.SSLEngine was added. The existing J2SDK 1.4.0 secure communication infrastructure, javax.net.ssl.SSLSocket, was based on the I/O model of java.net.Socket. The SSLEngine class abstracts away the I/O model, and leaves developers free to secure communication pathways using alternate types of I/O. SSLEngine can be combined with the New I/O APIs to create implementations such as secure blocking or non-blocking SocketChannels. For details see the JSSE Reference Guide.

Enhancements in Java 2 SDK v1.4


java.io



  • In the FileInputStream and FileOutputStream classes, getChannel methods have been added to return the underlying FileChannel object, and the close methods have been revised to close the underlying channel.
  • Similarly, in the RandomAccessFile class, a getChannel method has been added and the close method has been revised to close the underlying channel. The RandomAccessFile constructors now support the mode characters “s” and “d” to allow the specification, at file-open time, of synchronous writes or synchronous-data writes.
  • In the InputStreamReader and OutputStreamWriter classes, constructors have been added that take a stream and a Charset object, and the getEncoding methods have been revised to return the historical name of the encoding being used. Constructors to InputStreamReader and OutputStreamWriter have been added that take existing CharsetDecoder and CharsetEncoder objects, respectively.

java.nio



  • The nio packages were added to supplement the I/O facilities provided the java.io package.
  • Three new functions were added to the Java Native Interface (JNI) to support direct buffers. For information, see JNI Enhancements in v 1.4.