-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NIO 그게 대체 뭔데..? #10
Comments
들어가며Java의 입출력을 담당하는 패키지로 알고리즘 등에서 이용해봤을 듯 한 java.io가 있다. 하지만 java.io의 단점을 극복하기 위해서 새로 등장한 패키지가 있으니, 이것이 java.nio라고 한다. nio란 New IO라는 뜻이라는데, 대체 기존 I/O의 어떤 점을 변경하고 싶어서 새로운 패키지를 만들었을까? Java NIOIO와의 차이Java NIO는 Java에서의 IO의 단점을 극복하기 위해서 Java 4버전에서부터 추가되었고, Java 7과 8에서 새로운 기능이 추가되면서, 상당한 성능의 발전을 보였다. 기존의 Java IO와의 차이점으로는 크게 2가지를 고를 수 있는데, 이는 사용 편의성과 성능이다. (Java 4에서 추가된 것과 7,8에서 추가된 기능을 찾으려고 하는데, 기존에 있던 패키지에 통합되어서 알기힘들다ㅠㅠ) 사용 편의성기존의 io패키지에서 파일을 이용할 때에는 File이라는 클래스를 이용해서 굉장히 많은 역할을 했다. File이 경로, 디렉토리, 파일의 역할을 전부 했었고, File 클래스에 담긴 메서드 역시 굉장히 많았다. 하지만 nio패키지에선 경로를 Path, 디렉토리와 파일들에 대한 작업을 Files에서 진행한다. 또한 예외 클래스 역시 다양해져서 기존의 IOException의 에러 메세지를 통해서 에러 처리를 다르게 해야 했던 것과 달리 nio에서는 19개의 Exception class가 추가되었다고 한다. java io와 nio의 사용 방법의 차이는 아래와 같다. nio에서는 // 파일 생성
File file = new File("/hello.txt");
file.createNewFile();
Path path = Paths.get("/hello.txt");
Files.createFile(path);
// 디렉토리 생성
File dir = new File("/assets");
dir.mkdir();
Path dirPath = Paths.get("/assets");
Files.createDirectory(dirPath); 또한 파일을 입출력할 때 버퍼를 이용하는 것 역시 쉽다. ( // 버퍼 리더 생성
File bufFile = new File("/hello.txt");
BufferedReader br1 = new BufferedReader(new FileReader(bufFile));
Path bufPath = Paths.get("/hello.txt");
BufferedReader br2 = Files.newBufferedReader(bufPath); 성능io와의 성능의 차이를 보이는 주된 요소는 3가지로 꼽을 수 있다. Buffer 기반 작동NIO에서는 기존 IO의 Stream 방법과 달리 Buffer기반으로 작동한다. 기존의 자바 IO에서 그 성능을 향상시키기 위해서 BufferedReader와 같은 보조스트림을 이용했던 것을 기억하면 Buffer 기반이 성능이 좋다는 것을 알 수 있다. NIO에서 기본적으로 이용하는 통신 객체는 NIO의 패키지인 files에서 생성되는 객체들 ex) (아래 블로그에 따르면 line 단위로 읽는 경우 기존 io 방식이 더 빠를 수 있다고 한다.) Directed Byte Buffer기존 JAVA IO에서는 Buffer가 JVM의 Heap 영역에서 생성이 된다. 파일 시스템을 통해서 데이터를 읽어오면, 시스템 커널에 해당 내용에 대한 버퍼가 생성되고, 그 버퍼의 내용을 복사해서 JVM에 생성을 한다. 하지만 NIO의 Buffer는 Direct Buffer로 생성이 가능하다. Direct Buffer에 대한 설명은 Java Docs의 내용을 가져왔다.
위의 내용에서 버퍼의 콘텐츠를 중간 버퍼로 복사하지 않으려고 시도합니다. 라는 말이 앞서서 설명한 non-direct 방식의 buffer이고, 일반적인 Java IO에서 나타나는 방식이다.
위의 말은 Direct Byte Buffer가 JVM의 메모리가 아닌 시스템의 메모리를 이용하기 때문에, 할당, 해제의 오버헤드가 더 높다는 것을 의미한다. 이 내용을 토대로 정리하자면, NIO에서 이용하는 Direct Byte Buffer는 시스템 메모리에서 생성이 되어, 네이티브 수준의 I/O가 가능하기 때문에, 할당,해제 오버헤드가 발생해도 I/O의 성능 자체는 훌륭하다는 것을 알 수 있다. 논블로킹NIO가 성능을 향상시키는 가장 큰 요인 중 하나인 논블로킹은, NIO에서 이용하는 먼저 논블로킹을 이용할 수 있는 채널로는
Future<V> operation(...)
void operation(... A attachment, CompletionHandler<V,? super A> handler)
적용 사례사실 nio의 특별히 nio의 논블로킹 기능을 이용한 사례를 본다면, 책에 나온 아래와 같은 그림에서 하지만 아래와 같이 Selector를 두게 된다면, Selector가 결론Java NIO는 Java IO의 불편함을 해소하기 위해 등장한 패키지로, 성능과 편의성을 향상시켜준다. NIO에서 이용하는 참고 자료https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/ByteBuffer.html BufferReader보다 느린 것.. static ReadableByteChannel in = Channels.newChannel(System.in);
static ByteBuffer buffer = ByteBuffer.allocate(100000000); // 버퍼 크기
// ...
st = new StringTokenizer(readAll(), "\r\n");
liner = new StringTokenizer(st.nextToken());
//...
private static String readAll() throws IOException { // 왜 다 읽어버리니..
in.read(buffer);
buffer.flip(); // limit 은 포지션 position은 0으로 이동.
Charset charset = Charset.defaultCharset();
return charset.decode(buffer).toString();
} 아래 두 성공했습니다는 BufferReader, CustomerReader, 위에 2개는 Channel 이용했을 경우.. |
👍 문제
책에서는 간략히 여러가지 IO와 IO의 단점을 보완하기 위한 NIO를 소개하였다. 하지만 그 과정에서 설명이 부족하다고 느껴지는 부분이 있어 문제를 제시하고자 한다. NIO의 어떤 특성으로 인해서 IO의 단점을 보완할 수 있는지, 또한 NIO를 사용해야하는 use-case에 대해서 알아보자.
알고리즘만 풀던 나에게는 낯선 NIO를 좀 더 자세히 알아볼 수 있으면 좋겠다는 생각에 이 문제를 선정하게 되었다.
📺 관련 챕터 및 레퍼런스
ch9. IO에서 발생하는 병목 현상
🐳 비고
The text was updated successfully, but these errors were encountered: