etc

Sync & Async / Blocking & Non-Blocking

나는 원래 Java를 사용하여 개발을 했는데, 이제는 Node.js 기반으로 개발을 하는 입장으로서 Non-Blocking에 대한 개념이 중요하게 됐고,
이에 더해서 Sync와 Blocking에 대한 차이도 이해하는 것이 필요하다고 느꼈는데,
최근 Slipp에서 주최한 세미나에서 자바지기님의 발표를 통해서 이러한 점이 명쾌하게 이해가 되었다.
이번 글은 그 기반으로 Sync & Async / Blocking & Non-Blocking 에 대해서 알아보고 정리한 것이다.


Sync & Async / Blocking & Non-Blocking

SyncBlocking, AsyncNon-Blocking 서로 비슷한 개념이라고 생각할 수 있다.
나 역시 이 점에 대해 다른 것이 없다고 생각해왔었다.
하지만 분명한 차이가 있고 그 차이는 이해하기 어렵지 않다.
관련해서 여러 글을 찾아봤지만 Slipp 세미나에서 자바지기님이 설명해주신 것이 가장 명쾌하다고 생각한다.

Blocking vs Non-Blocking

I/O를 담당하는 함수를 호출했을 때 바로 리턴을 하느냐 아니냐가 관심사이다.

  • Blocking: 바로 리턴하지 않음
  • Non-Blocking: 바로 리턴

Sync vs Async

I/O를 담당하는 함수의 작업 완료 여부를 누가 신경쓰느냐가 관심사이다.

  • Sync: Application
  • Async: Kernel

I/O Models

앞서 살펴본 대략적인 개념만 기억하고 있으면 I/O Model에 대해 쉽게 이해할 수 있다.

(IBM 블로그 글을 보고 정리하였다.)

Synchronous blocking I/O

Synchronous blocking I/O는 가장 간단한 I/O model이다.
Application이 I/O 함수를 호출했을 때 바로 리턴을 하지 않고(Blocking) 끝날 때까지 대기한다.
이러한 대기 동안 아무것도 할 수 없다는 것이 가장 큰 단점이다.

Synchronous non-blocking I/O

Synchronous non-blocking I/O model의 경우,
Application이 I/O 함수를 호출했을 때 바로 리턴(Non-Blocking)을 한다.
하지만 Application이 I/O 작업이 끝났음을 알기 위해서 Application이 주기적으로 I/O 작업이 완료되었는지를 확인(Sync)해야한다.
주기적으로 확인하는 사이사이 다른 작업을 할 수 있지만 계속 확인해야하는 비효율성을 갖고있다.

Asynchronous blocking I/O

Asynchronous blocking I/O model의 경우,
Application이 I/O 함수를 호출했을 때 I/O 작업이 완료될 때 까지 blocking이 된다.
(함수 호출 후 바로 리턴을 받지만 Application은 다른 작업을 하지 않고 blocking 상태가 된다.)
I/O 작업이 끝나 Kernel에서 완료됨을 Application에게 알리면서(Async) Application의 blocking이 풀리게된다.

Asynchronous non-blocking I/O (AIO)

Asynchronous blocking I/O model에서 I/O 작업이 완료될 때까지 blocking이 되지 않고 다른 작업을 실행한다면 Asynchronous non-blocking I/O이다.

위와 같이 I/O System call을 호출하면 바로 응답을 받고(Non-Blocking),
I/O 작업이 완료되면 Kernel이 Application에게 I/O 작업 완료 signal을 보낸다(Async).
이 model의 장점은 Application이 I/O 요청 후 작업 완료를 직접 확인하지 않아, CPU가 다른 요청을 효과적으로 처리할 수 있다는 것이다.

Node.js와 Async I/O

Node.js의 Event Loop가 Single thread로도 많은 요청을 처리할 수 있는 것은 Async I/O 기반으로 I/O 작업을 처리하기 때문이다.

Node.js는 내부에 libuv를 사용하는데 이를 통해 Node.js가 Async I/O를 사용할 수 있는 것이다.

libuv is a multi-platform support library with a focus on asynchronous I/O.

from libuv document

libuv의 내부 구조를 보면 아래와 같이 되어있는데 여러 OS에서도 일관된 AIO 인터페이스를 사용할 수 있도록 구현되어 있다.
Windows의 경우 IOCP라는 Async I/O를 지원하는데, Windows가 아닌 경우 epoll, kqueue 등을 사용하여 Async I/O를 구현한 uv__io_t라는 AIO Wrapper를 사용한다.


참고:
https://developer.ibm.com/articles/l-async/
http://docs.libuv.org/en/v1.x/

Share