💋 인트로
안녕하세요. 우아한테크코스 5기 깃짱이라고 합니다.
이번 포스팅에서는 DB Connection Pool Size를 줄일 수록 오히려 성능이 개선될 수 있는 이유에 대해서 작성했습니다.
아래 내용은 HikariCP에서 작성한 깃허브 Wiki의 내용을 토대로 작성했습니다.
💋 커넥션 풀의 크기를 결정할 때, 얼마나 작게 하는지가 더 중요하다?
커넥션 풀을 설정하는 것은 개발자들이 자주 실수하는 부분입니다. 커넥션 풀을 구성할 때 이해해야 할 몇 가지 원칙이 있습니다.
동시에 10,000명의 사용자가 있는 서비스를 상상해보세요.
아마도 페이스북처럼 대규모는 아니더라도 10,000명의 사용자가 동시에 데이터베이스 요청을 하는 경우입니다. 이는 초당 약 20,000개의 트랜잭션을 의미합니다.
이때 커넥션 풀의 크기는 얼마나 커야 할까요?
놀랍게도, 얼마나 커야 할 지가 아니라 오히려 얼마나 작아야 할 지를 고민해야 한다고 합니다.
💋 실습을 통한 비교
유튜브에 올라온 오라클 실제 성능 그룹에서 제공한 영상에서 아래와 같이 커넥션 풀 사이즈만을 변경해가면서 CPU 사용량, 대기 시간, Run 시간, Wait Event를 확인합니다.
✔️ Case 1: 커넥션 풀 사이즈를 2048개로 설정한 경우
쓰레드 9600개에서 550ms 간격으로 하나씩 요청을 보내고 있습니다.
결과적으로, 1초에 처리해야 하는 트랜잭션(TPS
)은 15994개입니다.
각각의 트랜잭션은 평균적으로 Queue-ms
인 37ms 동안 커넥션 풀에서 커넥션을 받기를 기다리고, Run-ms
인 77ms 동안 실제로 커넥션을 통해서 데이터베이스로부터 정보를 가져옵니다.
아래 Sessions를 살펴보면, 우리가 현재 2048개의 커넥션을 커넥션 풀에 담아두고 있다는 것을 알 수 있습니다.
현재 CPU는 엄청나게 바쁘게 일하고 있는데, 82%는 User, 11%는 System을 위해서 일하고 있습니다.
데이터베이스에서는 상당히 많은 Wait Event가 발생하고 있습니다.
현재 데이터베이스의 커넥션 풀 설정이 제대로 되어 있지 않은 탓에 CPU 사용량도, Wait Event도 좋지 않은 성능을 보여주고 있습니다.
일반적으로, 이런 경우에 개발자들은 주로 scale out을 생각합니다.
자연스럽게 커넥션 풀에 커넥션 수도 많아지면 더 성능적으로 개선이 될 것이라고 생각합니다.
하지만, 오히려 커넥션의 개수를 줄이는 것이 성능 개선에 도움이 될 수 있습니다.
오히려 중간 계층에 더 많은 대기열을 도입하면 더 도움이 될 수 있습니다.
딱 절반으로 줄여봅시다.
✔️ Case 2: 커넥션 풀 사이즈를 1024개로 설정한 경우
이전 상황에 비해서 Run-msrk 30ms로 크게 개선되기는 했지만, Queue-ms에서 큰 차이를 보이지 못하고 있습니다.
성능이 조금 개선되었고, 커넥션 풀의 사이즈를 줄였지만, 놀랍게도 Queue 시간이 크게 늘어나지는 않았습니다.
조금 줄어들긴 했지만 여전히 Wait Event는 발생하고 있고, 따라서 조금 개선되었지만 크게 개선되었다고 보기는 어려울 것 같습니다.
더 눈에 띄게 성능을 개선하려면, 커넥션 풀의 사이즈를 더 극단적으로 줄여보면 좋을 것 같습니다.
기초적인 CS 지식의 Time Sharing Theory에 따르면 프로세스 2개가 동시에 동작하는 것은, 1개가 동작하고 나서 1개가 동작하는 것보다 항상
더 느립니다.
이 이론을 믿어보고 이번엔 진짜 확 사이즈를 줄여봅시다.
✔️ Case 3: 커넥션 풀 사이즈를 96개로 설정한 경우
이번엔 진짜 극단적으로 100개보다 적은 96개를 선택해 봤습니다.
진짜 놀랍게도, Queue 시간은 1ms이고, Run 시간은 2ms로 정말 크게 줄어들었습니다.
딱 JDBC 커넥션 풀의 개수만 바꿨을 뿐인데, CPU 사용량도 정말 크게 떨어뜨렸습니다.
또한 다양하게 발생하던 Wait Event도 모두 사라지고, CPU 영역의 이벤트만 발생하는 것으로 보아, 성능이 크게 개선되었습니다.
💋 왜 커넥션 풀 사이즈를 줄일수록 성능이 개선될까?
✔️ 멀티 쓰레딩은 운영 체제의 시간 분할 기술을 통해 이루어지는 단순한 트릭이다.
이 글에서는 커넥션 풀 크기를 줄이는 것만으로 응용 프로그램의 응답 시간이 약 100ms
에서 약 3ms
로 향상되었다는 것을 확인할 수 있습니다. 하지만 왜 그런지 궁금합니다.
비슷하게, 왜 4개의 스레드만 있는 nginx
웹 서버가 100개의 프로세스를 가진 Apache
웹 서버보다 훨씬 우수한 성능을 발휘할 수 있는 걸까요? 이건 컴퓨터 과학의 기본으로 돌아가서 생각하면 명백합니다. 심지어 하나의 CPU 코어를 가진 컴퓨터도 수십 개 또는 수백 개의 스레드를 "동시에" 지원할 수 있습니다. 하지만 우리는 모두 이것이 운영 체제의 시간 분할 기술을 통해 이루어지는 단순한 트릭임을 알고 있어야 합니다.
실제로는 그 하나의 코어는 한 번에 하나의 스레드만 실행할 수 있습니다. 그리고 운영 체제는 문맥을 전환하고 그 코어가 다른 스레드의 코드를 실행하게 합니다. 이는 순차적으로 A와 B를 실행하는 것이 A와 B를 "동시에" 실행하는 것보다 항상 빠르다는 컴퓨팅의 기본 법칙입니다. CPU 코어의 수를 초과하는 스레드의 수가 되면, 더 많은 스레드를 추가함으로써 더 느려질 뿐이죠.
✔️ 데이터베이스의 3대 병목
데이터베이스의 3대 병목은 아래와 같습니다.
- CPU
- 디스크
- 네트워크
메모리를 추가할 수도 있지만, 디스크와 네트워크와 비교하면 대역폭에서 수십 배의 차이가 있어서 제외했습니다.
디스크와 네트워크로 인한 병목 효과는 일정하다고 생각하고, CPU만을 생각해 봅시다. 8개의 컴퓨팅 코어를 가진 서버에서 연결 수를 8로 설정하면 최적의 성능을 제공하고, 이를 초과하는 어떤 것이라도 컨텍스트 전환의 오버헤드로 인해 느려질 것입니다.
하지만 우리는 디스크와 네트워크를 무시할 수 없습니다. 데이터베이스는 일반적으로 디스크에 데이터를 저장하며, 전통적으로 회전하는 금속 판과 이를 구동하는 스테퍼 모터로 구성된 디스크로 구성됩니다. 읽기/쓰기 헤드를 실제로 움직여서 입력과 출력을 해야 하기 때문에, 물리적으로 헤드가 움직이는 데 긴 시간이 소요됩니다.
✔️ SSD는 디스크 I/O 속도가 빨라서 오히려 멀티 쓰레딩에 불리하다.
디스크 I/O를 기다리는 동안, connection, query, thread는 단순히 디스크를 기다리는 blocked
상태입니다. 그리고 이 시간에 OS는 그 CPU 리소스를 더 나은 성능을 위해 다른 스레드를 실행함으로써 더 많은 작업을 수행할 수 있습니다. 따라서 스레드가 I/O에서 차단되므로, 물리적인 컴퓨팅 코어 수보다 더 많은 연결/스레드를 가지는 것으로 실제로 더 많은 작업을 수행할 수 있습니다.
그럼 얼마나 더 많이 할 수 있을까요?
SSD는 HHD에 비해서 더 빠르게 디스크 I/O를 할 수 있습니다.
하지만, 그렇다고 해서 SSD는 더 빠르기 때문에 더 많은 스레드를 가질 수 있다고 생각하면 안된다.
오히려 더 빠르고 찾기가 없고 회전 지연이 없는 것은 block
된 시간이 적어진다는 것을 의미합니다.
차단으로 인해 실행 기회가 생기는 경우에만 더 많은 스레드가 더 나은 성능을 발휘하기 때문에, 더 빠른 SSD는 오히려 코어 수에 가까운 적은 쓰레드의 수가 더 나은 성능을 보여준다.
💋 참고자료
- https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
- https://www.youtube.com/watch?v=_C77sBcAtSQ
도움이 되었다면, 공감/댓글을 달아주면 깃짱에게 큰 힘이 됩니다!🌟
'Computer Science > Operating System' 카테고리의 다른 글
[OS] 동기화 메커니즘(Synchronization Mechanisms)(1): 스핀락(Spinlock), 뮤텍스(Mutex), 세마포어(Semaphore) (0) | 2023.11.20 |
---|---|
[OS] 동기화(synchronization)의 필요성: 경쟁 조건(race condition), 임계 영역(critical section) (0) | 2023.11.12 |
[OS] CPU Bound VS IO Bound: 스레드는 몇 개가 좋을까? (0) | 2023.11.10 |
[OS] 컨텍스트 스위칭: 프로세스 컨텍스트 스위칭 VS 스레드 컨텍스트 스위칭 (0) | 2023.11.09 |
[OS] 프로세스/스레드의 개념: 멀티태스킹, 멀티스레딩, 멀티프로세싱, 멀티프로그래밍을 구분하자! (2) | 2023.11.09 |