개요
메인 페이지에 노출되는 스터디 조회 API와 관련된 3가지 쿼리에 대한 튜닝을 진행함으로써 기존에 구현한 로직과 비교해서 꽤 괜찮은 성능 향상을 이루어 냈다
- 등록날짜 기준
- 좋아요 개수 기준
- 리뷰 개수 기준
이번에는 ThreadPool & HikariCP 튜닝을 진행해서 최적의 값을 도출해보려고 한다
참고 포스팅
튜닝 진행
- Tomcat의 maxConnections & acceptCount는 기본값으로 고정 (8192 & 100)
- Tomcat의 maxThreads & HikariCP의 maximumPoolSize의 케이스별 부하 테스트 진행
1) maxThreads 50 기준
등록날짜 기준 | 좋아요 개수 기준 | 리뷰 개수 기준 | |
maximumPoolSize 5 | TPS = 222.0 (max 268.5) Response Time = 452.80 Executed Test = 12489 Errors = 1 |
TPS = 230.3 (max 261.5) Response Time = 440.54 Executed Test = 12961 Errors = 0 |
TPS = 260.3 (max 315.5) Response Time = 387.89 Executed Test = 14645 Errors = 0 |
maximumPoolSize 10 | TPS = 237.8 (max 276.0) Response Time = 423.51 Executed Test = 13382 Errors = 1 |
TPS = 239.8 (max 274.5) Response Time = 416.99 Executed Test = 13488 Errors = 1 |
TPS = 270.5 (max 327.5) Response Time = 370.75 Executed Test = 15207 Errors = 1 |
maximumPoolSize 15 | TPS = 219.0 (max 266.0) Response Time = 458.61 Executed Test = 12324 Errors = 0 |
TPS = 247.6 (max 323.5) Response Time = 409.22 Executed Test = 13933 Errors = 0 |
TPS = 253.8 (max 292.0) Response Time = 395.06 Executed Test = 14281 Errors = 0 |
maximumPoolSize 20 | TPS = 224.9 (max 265.5) Response Time = 447.61 Executed Test = 12652 Errors = 1 |
TPS = 230.8 (max 278.0) Response Time = 437.70 Executed Test = 12988 Errors = 0 |
TPS = 278.3 (max 394.5) Response Time = 362.84 Executed Test = 15661 Errors = 0 |
maximumPoolSize 25 | TPS = 224.0 (max 278.0) Response Time = 450.40 Executed Test = 12603 Errors = 1 |
TPS = 228.1 (max 274.0) Response Time = 441.34 Executed Test = 12826 Errors = 1 |
TPS = 265.3 (max 328.0) Response Time = 377.95 Executed Test = 14912 Errors = 1 |
2) maxThreads 100 기준
등록날짜 기준 | 좋아요 개수 기준 | 리뷰 개수 기준 | |
maximumPoolSize 5 | TPS = 231.6 (max 272.5) Response Time = 440.23 Executed Test = 13031 Errors = 0 |
TPS = 266.3 (max 321.0) Response Time = 376.17 Executed Test = 14970 Errors = 1 |
TPS = 288.4 (max 342.5) Response Time = 349.64 Executed Test = 16225 Errors = 1 |
maximumPoolSize 10 | TPS = 231.7 (max 271.5) Response Time = 435.68 Executed Test = 13036 Errors = 1 |
TPS = 241.0 (max 283.5) Response Time = 418.60 Executed Test = 13561 Errors = 1 |
TPS = 269.5 (max 313.5) Response Time = 374.64 Executed Test = 15161 Errors = 1 |
maximumPoolSize 15 | TPS = 247.0 (max 297.0) Response Time = 406.52 Executed Test = 13892 Errors = 0 |
TPS = 240.7 (max 288.5) Response Time = 420.21 Executed Test = 13549 Errors = 0 |
TPS = 277.0 (max 338.0) Response Time = 364.27 Executed Test = 15577 Errors = 1 |
maximumPoolSize 20 | TPS = 216.1 (max 278.0) Response Time = 467.92 Executed Test = 12155 Errors = 0 |
TPS = 239.5 (max 292.5) Response Time = 418.64 Executed Test = 13470 Errors = 0 |
TPS = 266.7 (max 317.5) Response Time = 378.94 Executed Test = 15008 Errors = 0 |
maximumPoolSize 25 | TPS = 196.4 (max 249.0) Response Time = 512.43 Executed Test = 11051 Errors = 0 |
TPS = 234.6 (max 278.5) Response Time = 428.02 Executed Test = 13189 Errors = 0 |
TPS = 254.8 (max 298.0) Response Time = 396.74 Executed Test = 14338 Errors = 0 |
3) maxThreads 150 기준
등록날짜 기준 | 좋아요 개수 기준 | 리뷰 개수 기준 | |
maximumPoolSize 5 | TPS = 237.7 (max 276.0) Response Time = 423.12 Executed Test = 13367 Errors = 1 |
TPS = 246.2 (max 301.5) Response Time = 409.17 Executed Test = 13848 Errors = 1 |
TPS = 299.9 (max 349.5) Response Time = 336.64 Executed Test = 16868 Errors = 1 |
maximumPoolSize 10 | TPS = 218.6 (max 248.5) Response Time = 463.02 Executed Test = 12292 Errors = 0 |
TPS = 232.6 (max 265.0) Response Time = 423.96 Executed Test = 13094 Errors = 1 |
TPS = 271.5 (max 320.5) Response Time = 371.76 Executed Test = 15280 Errors = 1 |
maximumPoolSize 15 | TPS = 223.4 (max 287.0) Response Time = 453.00 Executed Test = 12570 Errors = 0 |
TPS = 247.7 (max 296.0) Response Time = 404.27 Executed Test = 13929 Errors = 0 |
TPS = 267.2 (max 343.5) Response Time = 375.18 Executed Test = 15037 Errors = 0 |
maximumPoolSize 20 | TPS = 213.1 (max 249.5) Response Time = 469.93 Executed Test = 11980 Errors = 1 |
TPS = 247.4 (max 312.0) Response Time = 406.60 Executed Test = 13915 Errors = 1 |
TPS = 258.9 (max 299.0) Response Time = 388.49 Executed Test = 14571 Errors = 0 |
maximumPoolSize 25 | TPS = 219.5 (max 295.5) Response Time = 459.09 Executed Test = 12356 Errors = 1 |
TPS = 239.8 (max 270.0) Response Time = 419.79 Executed Test = 13485 Errors = 1 |
TPS = 263.2 (max 297.5) Response Time = 382.44 Executed Test = 14817 Errors = 1 |
4) maxThreads 200 기준
등록날짜 기준 | 좋아요 개수 기준 | 리뷰 개수 기준 | |
maximumPoolSize 5 | TPS = 240.4 (max 322.5) Response Time = 418.80 Executed Test = 13529 Errors = 0 |
TPS = 239.4 (max 293.0) Response Time = 419.76 Executed Test = 13454 Errors = 0 |
TPS = 291.8 (max 335.0) Response Time = 347.42 Executed Test = 16418 Errors = 0 |
maximumPoolSize 10 | TPS = 243.8 (max 282.0) Response Time = 410.73 Executed Test = 13709 Errors = 1 |
TPS = 251.0 (max 292.0) Response Time = 402.37 Executed Test = 14122 Errors = 1 |
TPS = 277.2 (max 345.5) Response Time = 363.70 Executed Test = 15598 Errors = 1 |
maximumPoolSize 15 | TPS = 228.0 (max 271.0) Response Time = 443.59 Executed Test = 12829 Errors = 0 |
TPS = 231.3 (max 281.0) Response Time = 436.02 Executed Test = 13019 Errors = 0 |
TPS = 259.5 (max 307.0) Response Time = 386.16 Executed Test = 14597 Errors = 1 |
maximumPoolSize 20 | TPS = 228.9 (max 286.5) Response Time = 438.13 Executed Test = 12873 Errors = 0 |
TPS = 226.5 (max 272.0) Response Time = 446.23 Executed Test = 12732 Errors = 0 |
TPS = 255.8 (max 316.0) Response Time = 393.36 Executed Test = 14374 Errors = 0 |
maximumPoolSize 25 | TPS = 205.8 (max 243.0) Response Time = 491.12 Executed Test = 11586 Errors = 0 |
TPS = 223.5 (max 267.5) Response Time = 452.20 Executed Test = 12280 Errors = 0 |
TPS = 251.2 (max 328.5) Response Time = 399.46 Executed Test = 14128 Errors = 0 |
5) maxThreads 250 기준
등록날짜 기준 | 좋아요 개수 기준 | 리뷰 개수 기준 | |
maximumPoolSize 5 | TPS = 257.2 (max 302.5) Response Time = 391.91 Executed Test = 14473 Errors = 1 |
TPS = 279.7 (max 334.0) Response Time = 361.43 Executed Test = 15721 Errors = 1 |
TPS = 309.5 (max 374.0) Response Time = 324.01 Executed Test = 17414 Errors = 1 |
maximumPoolSize 10 | TPS = 224.0 (max 316.5) Response Time = 449.75 Executed Test = 12606 Errors = 0 |
TPS = 245.4 (max 298.0) Response Time = 412.11 Executed Test = 13797 Errors = 0 |
TPS = 286.7 (max 352.5) Response Time = 349.92 Executed Test = 16126 Errors = 0 |
maximumPoolSize 15 | TPS = 228.5 (max 258.0) Response Time = 442.32 Executed Test = 12849 Errors = 0 |
TPS = 227.9 (max 266.0) Response Time = 443.33 Executed Test = 12820 Errors = 0 |
TPS = 275.3 (max 334.5) Response Time = 368.32 Executed Test = 15489 Errors = 0 |
maximumPoolSize 20 | TPS = 218.1 (max 261.0) Response Time = 462.14 Executed Test = 12270 Errors = 1 |
TPS = 246.1 (max 277.5) Response Time = 410.51 Executed Test = 13844 Errors = 0 |
TPS = 257.2 (max 309.5) Response Time = 391.01 Executed Test = 14484 Errors = 0 |
maximumPoolSize 25 | TPS = 214.5 (max 264.5) Response Time = 468.49 Executed Test = 12073 Errors = 1 |
TPS = 240.0 (max 285.0) Response Time = 418.74 Executed Test = 13499 Errors = 1 |
TPS = 260.8 (max 345.5) Response Time = 383.18 Executed Test = 14680 Errors = 1 |
6) maxThreads 300 기준
등록날짜 기준 | 좋아요 개수 기준 | 리뷰 개수 기준 | |
maximumPoolSize 5 | TPS = 222.0 (max 267.5) Response Time = 450.57 Executed Test = 12494 Errors = 0 |
TPS = 266.0 (max 296.5) Response Time = 379.46 Executed Test = 14966 Errors = 1 |
TPS = 295.7 (max 349.5) Response Time = 340.11 Executed Test = 16632 Errors = 0 |
maximumPoolSize 10 | TPS = 226.7 (max 261.5) Response Time = 444.77 Executed Test = 12757 Errors = 1 |
TPS = 233.4 (max 276.0) Response Time = 431.53 Executed Test = 13138 Errors = 1 |
TPS = 270.6 (max 325.0) Response Time = 372.30 Executed Test = 15233 Errors = 1 |
maximumPoolSize 15 | TPS = 218.0 (max 250.0) Response Time = 461.66 Executed Test = 12277 Errors = 1 |
TPS = 243.5 (max 311.0) Response Time = 414.29 Executed Test = 13696 Errors = 1 |
TPS = 280.2 (max 326.5) Response Time = 360.37 Executed Test = 15764 Errors = 1 |
maximumPoolSize 20 | TPS = 255.2 (max 303.0) Response Time = 395.12 Executed Test = 14360 Errors = 0 |
TPS = 266.9 (max 304.5) Response Time = 376.01 Executed Test = 15007 Errors = 0 |
TPS = 269.0 (max 308.5) Response Time = 373.01 Executed Test = 15127 Errors = 0 |
maximumPoolSize 25 | TPS = 206.6 (max 249.0) Response Time = 487.26 Executed Test = 11624 Errors = 1 |
TPS = 230.3 (max 267.0) Response Time = 436.71 Executed Test = 12967 Errors = 1 |
TPS = 262.4 (max 303.5) Response Time = 385.40 Executed Test = 14764 Errors = 0 |
여러 케이스별로 부하테스트를 진행해봄으로써 현재 프로젝트상에서 가장 최적의 조합은 Tomcat maxThreads 250 & HikariCP maximumPoolSize 5로 도출되었다
의문점
maxThreads & maxConnections이 많아지면 오히려 성능이 왜 떨어지는걸까?
일단 Thread도 리소스이고 각 쓰레드별로 Stack, PC Register, ..등이 별도로 할당된다
따라서 Thread가 점차 많아진다고 하면 결국 메모리도 그만큼 사용하게 되는 것이다
그리고 Thread가 점차 많아지면 Thread간의 Context Switching이 굉장히 빈번하게 발생할 수 있고 이러한 Context Switching에 대한 비용이 오버헤드가 될 수 있다
돈 때려박아서 메모리 늘리면 안됨?
RAM을 늘린다고 해도 CPU Core에 한계가 존재하기 떄문에 동시에 처리할 수 있는 Task역시 한계가 존재한다
- CPU Core가 8개라면 최대 8개의 Thread만 동시에 처리할 수 있다
- 우리 눈에 여러 Task가 진짜 동시에 실행되는것처럼 보이는 이유는 굉장히 짧은 Time Quantum에 의해 여러 Thread간의 Context Switching이 발생하기 때문이다
그리고 단순히 ThreadPool만 고려하는게 아니라 DBCP Connection또한 고려해야 한다
- 물론 외부 Network I/O가 존재한다면 그에 대한 병목도 당연히 고려 대상
따라서 결론적으로 Thread, Connection수가 점차 많아진다고 하더라도 성능이 그에 비례적으로 좋아지는게 아니라 오히려 저하될 수 있다