1. 블록킹 자바 IO

- 자바에서 파일 읽기를 시도하면, 먼저 커널에 명령이 전달되고,
 커널은 시스템 콜을 사용해서 디스크 컨트롤러가 읽어온 데이터를 커널의 버퍼에 저장한다.
 그 후 모든 파일 데이터가 커널의 버퍼에 복사되면, JVM의 버퍼로 복사한다.

- 첫번째 문제점은, 커널의 버퍼에 저장된 데이터를 프로세스 영역의 버퍼로 복사하는 것이다.
 만약 커널의 버퍼를 직접 사용할 수 있다면, 복사하는 시간이 필요없다.
 
- 두번째 문제점은, 디스크 컨트롤러에서 커널의 버퍼로 데이터를 복사하는 동안, 프로세스 영역이 블로킹 된다는 것이다.


2. IO 속도 향상을 위한 OS수준의 기술들

1) 버퍼
 - 효율적으로 데이터를 전달하기 위한 객체.
 - 버퍼의 크기가 크면 클수록 성능 향상이 이루어진다.

2) Scatter/Gather
 - 사용하는 버퍼가 여러개 일때, Scatter/Gather를 사용하면 시스템 콜을 한번만 호출하고,
 사용할 버퍼의 주소 목록을 넘겨줌으로서, 운영체제에서 버퍼들에게서 순차적으로 데이터를 읽거나 쓰게 된다.

3) 가상 메모리
 - 프로그램이 사용할 수 있는 주소 공간을 늘이기 위해 운영체제에서 지원하는 기술.
 - 가상 메모리를 사용함으로써 실제 물리적 메모리보다 더 큰 공간을 사용할 수 있고,
   여러 개의 가상 주소가 하나의 물리적 메모리 주소를 참조함으로써 메모리를 효율적으로 사용할 수 있게 해준다.
- 프로그래밍에서 가상 메모리를 사용하게 되면, 프로세스의 버퍼와 커널의 버퍼를 매핑시킴으로써
   커널의 버퍼에서 프로세스의 버퍼로 복사할 필요가 없게 된다.

4) 메모리 맵 파일
 - Memory-mapped IO는 파일시스템의 페이지들과 유저 영역의 버퍼를 가상 메모리로 매핑시킨다.
 - 메모리 맵 파일을 사용하면, 프로세스가 파일 데이터를 메모리로서 바라보기 때문에 시스템 콜을 할 필요가 없다.
   따라서 프로세스가 파일 데이터를 변경하면 별도의 입출력을 할 필요가 없이 물리적 디스크에 자동으로 반영하게 된다.
 - 또한, 매우 큰 파일을 복사하기 위해 많은 양의 메모리를 소비하지 않아도 된다.
   그때그때 필요한 부분만을 실제 메모리에 올려놓고 사용하면 된다.

5) 파일 락
 - 스레드의 동기화와 거의 비슷한 개념이다. 한 프로세스가 어떤 파일에 락을 획득하면, 다른 프로세스가 그 파일에 접근하는 것을
  막거나, 접근 방식에 제한을 두는 것이다.
 - 파일의 일부분만을 잠궈서 사용하기 때문에, 락이 설정되지 않은 부분은 다른 프로세스가 작업할 수 있다.
 - 일반적으로 공유 락은 읽기 작업에 사용되고, 배타 락은 쓰기 작업에 사용된다.
 - 공유 락이 걸려있는 부분은 읽기 작업은 얼마든지 더 할수 있지만, 쓰기 작업을 할 수 없다.
   배타 락이 걸려있는 부분은 어떤 다른 작업도 할 수 없다.


3. 자바의 변화

1) 포인터 버퍼 도입
 - NIO에서는 커널이 관리하는 시스템 메모리를 직접 사용할 수 있는 Buffer 클래스가 도입되었다.
 - 내부적으로는 C로 만들어져 있지만 우리는 추상화되어 제공되는 자바 클래스인 Buffer만을 사용하게 된다.

2) 네이티브 IO서비스를 제공해주는 채널 도입
 - 채널은 단방향 뿐만이 아니라 양방향 통신도 가능하다.
 - 채널을 이용해서 시스템 메모리인 버퍼에 직접 읽거나 쓸 수 있다. 또한 Scatter/Gather를 구현하였다.

3) 셀렉터 도입
 - 기존에는 클라이언트 하나당 스레드 하나를 생성해서 처리해야 했다.
 - 셀렉터를 이용함으로써 단 한개의 스레드만으로 수천, 수만명의 동시 사용자를 처리할 수 있다.



+ Recent posts