Java NIO 와 동기 non-blocking + CPU 자원

Java NIO (new IO) 를 이용한 Server - Client 의 동작을

동기 / 비동기, blocking / non-blocking 관점에서 알아보겠다.

 

 

참고로 java.nio 패키지에 존재하는 selector 는 다음 포스팅에서 다루겠다.

 

Java IO 와 다르게 Java NIO 는 non-blocking 하게 동작할 수 있는 옵션이 존재한다.

-> ServerSocketChannel::configureBlocking 메서드를 호출해주고 파라미터 값으로 false 를 전달한다.

해당 옵션을 사용하면, accept 와 read 에서 blocking 되지 않고 바로 넘어간다.

각각 null, 0 을 리턴해버린다.

 

accept 의 예시 코드를 보며 계속 하겠다.

즉, non-blocking mode 에서 accept 를 호출하면 즉시 null 을 리턴하게 되어

해당 스레드는 blocking 되지 않고 다른 작업을 그동안 할 수 있다.

(위 코드에서는 sleep 을 주어 스레드를 일시정지 상태로 전환 하였으며, 상태 전환에 따른 컨텍스트 스위칭 발생)

 

즉, Java IO 와 비교하면

CPU 관점에서는...

위와 같이 sleep 을 주면 컨텍스트 스위칭이 발생하는 것은 동일하나..

sleep 을 주지 않고 의미 있는 일을 한다면, IO 대기 상태 진입이 없어지므로 그에 따른 컨텍스트 스위칭이

없기 때문에 CPU 자원 소모를 많이 줄일 수 있다.

또한, Java IO 처럼 IO 때문에 스레드가 blocking 되지는 않아서

대기상태(아무 일도 못하는)의 스레드가 생겨버리는 상황이 없기 때문에

스레드 관리 자원 차원에서는 무조건 이득인 상황이다.

 

Java IO 에서는...

DMA 로 Disk 에서 커널로 데이터 카피가 이루어져서 CPU 소모가 없었지만

커널에서 JVM 내부 메모리로 데이터 카피가 이루어져야 해서 CPU 소모가 있었다.

Java NIO 에서는..

1. ByteBuffer 단위로 데이터가 in / out 된다.

2. ByteBuffer 에는 2가지 종류가 있는데..

DirectByteBuffer 와 HeapByteBuffer 이다.

 

DirectByteBuffer 는..

native memory (off-heap) 에 저장되고 커널 메모리에서 복사가 일어나지 않는다. (CPU 소모 X)

off-heap 메모리라서 GC 관리 대상에서 제외된다. (CPU 소모 X, 대신 native 언어와 같이 메모리 해제를 직접해줘야함)

system-call 기반이므로 할당과 해제가 비용이 많이드는 작업이다.

따라서, 재사용을 많이 하는 쪽으로 생각해줘야한다.

 

HeapByteBuffer 는..

Java IO 와 같이 GC 에서 관리하는 on-heap 메모리를 사용하고

커널 메모리에서 복사가 이루어 져야한다.

대신 할당과 해제 비용은 싸고 빠르다.

 

 

주의 사항

non-blocking mode 에서 accept, read 호출 시

원하는 값을 바로주는 보장이 없기 때문에 (각각 null, 0 을 바로 리턴) 실제 결과를 받으려면

loop 를 통해 busy-wait 방식이 필요하다.

 

즉, callback 을 지원하지 않기 때문이다.

accept 가 완료되었는지.. read 가 가능한지.. 주기적으로 확인을 해야한다는 것이다.

다른 말로 동기 코드인 것이다.

 

 

참고

동기 non-blocking 에서 주로 busy-wait 동작이 이루어진다.

상태를 확인하는 주기가 짧다면..

-> 사실상 blocking 과 다를바가 없으며, CPU 가 확인하는 동작에 그만큼 점유가 되는 것이다.

상태를 확인하는 주기가 길다면..

-> 그만큼 실시간성이 떨어지는 상황에 놓인다.

 

 

 

'Java' 카테고리의 다른 글

Java NIO 의 Selector 와 epoll  (0) 2023.11.19
Java NIO 의 Selector  (0) 2023.11.17
Java IO 와 동기 blocking + CPU 자원  (0) 2023.11.15
Java 16 주요 변경점  (0) 2023.05.20
Java 11 ~ 15 주요 변경점  (0) 2023.05.19