간헐적 많은 양 쓰기, 빈번하게 읽기의 동기화
2015/06/11
배경
- 멀티프로세스다.
- 프로세스간 IPC는 공유메모리를 쓴다.
- 공유메모리에 있는 내용은 각 프로세스가 엄청 빈번하게 읽어댄다.
- 단, 공유메모리의 내용은 가끔만 쓰기가 발생한다.
잘못된 처리방법
- 공유메모리에 읽고 쓰는 동안 락을 통으로 잡는다. 물론 try 먼저 해보는 다양한 스킴을 통해서 통락의 비용을 아낄 순 있겠지만.. 아마도 try 스핀이나 관련 명령어들은 CSW를 일으킬 확률이 매우 높을 것이라고 추정해 볼 수 있다.
결과
- 공유메모리에 쓸 것이 많아서 락잡힌 시간이 길다. 성능저하!
개선하기
- 공유메모리에 쓸 내용에 대해, 같은 내용을 여러벌을 기록할 공간을 준비한다.
- 각 공간은 인덱스 번호를 갖는다.
- 락은 인덱스만 잡는다.
- 현재 활성 인덱스가 1번이면 프로세스들은 1번 공유메모리를 겁나 읽는다.
- 쓰기가 발생하면 2번 공간에 락없이 쓴다.
- 현재 읽기 인덱스를 2로 바꾼다.
결과
- 활성 인덱스 변수 하나 읽고 쓰기만 락을 사용하므로 빠르다.
내가 이 패턴을 보았을 때, 이 코드를 짠 분은 최고수 중 한 분이라고 들었다. 그러고보니 사실 이 방식은 대부분의 그래픽 시스템에서 사용하는 프레임버퍼, 오버레이 처리와 방식이 같다. 더블 버퍼링, 3중 버퍼링이 다 이런 원리다. 이 패턴을 본 코드에서는 심지어 index에도 락을 안 잡았다. 쓰기 빈도가 간헐적이라고 해서 경험적으로 갠찬타고.. 뭐, 엄밀히 gnu, linux용 atomic inc 함수가 따로 있으므로 이 정도는 락을 써도 좋겠다.
4~8바이트 Inc 정도이므로 간단히는 스핀락을 쓰는 쪽이 가장 빠를 것 같다.
끗~
[t:/] is not "technology - root". dawnsea, rss