이번 게시글에서는 Debian 기반의 컨테이너와 Alpine 기반의 컨테이너 간 성능을 비교해보도록 하겠습니다.
지난 게시글의 소개와는 다르게, 구동 시간이 너무 오래걸려 본 게시글에는 테스트 방안을 “소개”하고, 글을 수정하여 보강할 예정입니다. 벌써부터 이렇게 말씀드리는 점 양해 부탁드립니다. 🙇🙇
아래와 같이 변경될 예정입니다:
그렇다면, 목표와 가설을 세우고, 준비 후 직접 실험해봅시다!
파이썬으로 작성한 cpu bound task와 io bound task 를 각각 컨테이너화 했을 때, glibc, musl 구현체의 성능 벤치마킹을 통해 적절한 구현체가 무엇인지 파악해봅시다.
이번 실험을 통해 세운 가설은 아래와 같습니다.
glibc
C 라이브러리 기반의 운영체제 이미지musl
C 라이브러리 기반의 운영체제 이밎6
개를, memory는 최대 8GB
를 할당CPU bound 태스크를 테스트하기 위해, 랜덤 포레스트와 K-means clustering을 각각 구동해보기로 했습니다. 선정한 이유는 아래와 같습니다:
따라서, 이에 맞게 각종 머신러닝 기법을 진짜 “맛만보는” 코드를 작성했습니다. 아래는 각 내용에 대한 간략한 설명입니다:
아래와 같이 테이블 구성을 구성합니다.
여기서부터는 작성한 코드를 참고해주세요. 코드는 이 github 링크 에 준비되어 있습니다.
하지만 작업 중간에, 아래와 같은 리뷰사항을 받고 태스크의 내용을 한 번 수정했습니다. 확실히 조사가 필요한 부분 및 보강이 가능한 부분에 대해 다듬었습니다.
cpu bound task 보완
n_jobs
파라미터 만으로 처리가능한지io bound task 보완
실험 결과는 아래와 같으며, CPU bound 부터 소개하고 이어서 IO bound 를 소개합니다.
아래와 같은 전제조건을 취했습니다. 코드는 여기를 살펴봐주세요.
데이터셋 조건
모델 설정
측정 항목
재현성 보장
Alpine 기반의 컨테이너로 K-means clustering 로직을 구동해본 결과는 아래와 같았습니다:
🍅 disclaimer
scikit-learn
의 공식 지원이 3.12 까지라, Alpine 리눅스에서는 3.13 베이스 이미지에서 구동이 어려웠습니다.
Version | Samples | Clusters | Execution Time (s) |
---|---|---|---|
3.12 |
1,000,000 | 3 | 5.50 |
3.12 |
1,000,000 | 5 | 4.81 |
3.12 |
5,000,000 | 3 | 11.90 |
3.12 |
5,000,000 | 5 | 12.71 |
Debian 기반의 컨테이너로 K-means clustering 로직을 구동해본 결과는 아래와 같았습니다:
Version | Samples | Clusters | Execution Time (s) |
---|---|---|---|
3.12 |
1,000,000 | 3 | 4.72 |
3.12 |
1,000,000 | 5 | 4.90 |
3.12 |
5,000,000 | 3 | 10.37 |
3.12 |
5,000,000 | 5 | 12.18 |
3.13 |
100,000 | 5 | 2.74 |
3.13 |
100,000 | 7 | 3.50 |
3.13 |
500,000 | 5 | 6.92 |
3.13 |
500,000 | 7 | 6.92 |
Running benchmark for 1000000 samples, 3 clusters...
Execution time: 5.50 seconds
Iterations: 2
Inertia: 128018685.50
Average CPU Usage: 801.99%
Average Memory Usage: 12.59%
Peak CPU Usage: 1261.70%
Peak Memory Usage: 17.07%
Running benchmark for 1000000 samples, 5 clusters...
Execution time: 4.81 seconds
Iterations: 2
Inertia: 128018441.10
Average CPU Usage: 1014.51%
Average Memory Usage: 23.78%
Peak CPU Usage: 1206.10%
Peak Memory Usage: 28.70%
Running benchmark for 5000000 samples, 3 clusters...
Execution time: 11.90 seconds
Iterations: 2
Inertia: 640003227.45
Average CPU Usage: 723.35%
Average Memory Usage: 69.71%
Peak CPU Usage: 1208.10%
Peak Memory Usage: 92.17%
Running benchmark for 5000000 samples, 5 clusters...
Execution time: 12.71 seconds
Iterations: 2
Inertia: 640002946.03
Average CPU Usage: 945.65%
Average Memory Usage: 64.20%
Peak CPU Usage: 1206.70%
Peak Memory Usage: 90.08%
Plotting Data Summary:
Dataset Size: 1000000, Clusters: 3
Execution Time: 5.50s
CPU Usage: 52 points, Range: [0.0, 1261.7]
Memory Usage: 52 points, Range: [6.5, 17.1]
Dataset Size: 1000000, Clusters: 5
Execution Time: 4.81s
CPU Usage: 47 points, Range: [93.4, 1206.1]
Memory Usage: 47 points, Range: [18.0, 28.7]
Dataset Size: 5000000, Clusters: 3
Execution Time: 11.90s
CPU Usage: 112 points, Range: [47.9, 1208.1]
Memory Usage: 112 points, Range: [37.9, 92.2]
Dataset Size: 5000000, Clusters: 5
Execution Time: 12.71s
CPU Usage: 121 points, Range: [86.0, 1206.7]
Memory Usage: 121 points, Range: [35.7, 90.1]
구동 불가!
Running benchmark for 1000000 samples, 3 clusters...
Execution time: 4.72 seconds
Iterations: 2
Inertia: 128018685.50
Average CPU Usage: 907.44%
Average Memory Usage: 12.71%
Peak CPU Usage: 1199.30%
Peak Memory Usage: 17.33%
Running benchmark for 1000000 samples, 5 clusters...
Execution time: 4.90 seconds
Iterations: 2
Inertia: 128018441.10
Average CPU Usage: 1044.18%
Average Memory Usage: 12.94%
Peak CPU Usage: 1218.20%
Peak Memory Usage: 18.36%
Running benchmark for 5000000 samples, 3 clusters...
Execution time: 10.37 seconds
Iterations: 2
Inertia: 640003227.45
Average CPU Usage: 793.64%
Average Memory Usage: 59.11%
Peak CPU Usage: 1208.20%
Peak Memory Usage: 83.59%
Running benchmark for 5000000 samples, 5 clusters...
Execution time: 12.18 seconds
Iterations: 2
Inertia: 640002946.03
Average CPU Usage: 959.31%
Average Memory Usage: 57.18%
Peak CPU Usage: 1210.40%
Peak Memory Usage: 83.59%
Plotting Data Summary:
Dataset Size: 1000000, Clusters: 3
Execution Time: 4.72s
CPU Usage: 46 points, Range: [0.0, 1199.3]
Memory Usage: 46 points, Range: [6.5, 17.3]
Dataset Size: 1000000, Clusters: 5
Execution Time: 4.90s
CPU Usage: 48 points, Range: [93.4, 1218.2]
Memory Usage: 48 points, Range: [7.5, 18.4]
Dataset Size: 5000000, Clusters: 3
Execution Time: 10.37s
CPU Usage: 100 points, Range: [96.5, 1208.2]
Memory Usage: 100 points, Range: [29.2, 83.6]
Dataset Size: 5000000, Clusters: 5
Execution Time: 12.18s
CPU Usage: 118 points, Range: [88.9, 1210.4]
Memory Usage: 118 points, Range: [29.2, 83.6]
Running benchmark for 100000 samples, 5 clusters...
Execution time: 2.74 seconds
Iterations: 2
Inertia: 12800855.22
Average CPU Usage: 392.67%
Average Memory Usage: 2.48%
Peak CPU Usage: 536.20%
Peak Memory Usage: 2.52%
Running benchmark for 100000 samples, 7 clusters...
Execution time: 3.50 seconds
Iterations: 2
Inertia: 12800608.95
Average CPU Usage: 400.08%
Average Memory Usage: 2.50%
Peak CPU Usage: 564.40%
Peak Memory Usage: 2.52%
Running benchmark for 500000 samples, 5 clusters...
Execution time: 6.92 seconds
Iterations: 2
Inertia: 64009635.94
Average CPU Usage: 366.32%
Average Memory Usage: 7.00%
Peak CPU Usage: 671.20%
Peak Memory Usage: 9.58%
Running benchmark for 500000 samples, 7 clusters...
Execution time: 6.92 seconds
Iterations: 2
Inertia: 64009455.56
Average CPU Usage: 382.56%
Average Memory Usage: 6.93%
Peak CPU Usage: 601.80%
Peak Memory Usage: 7.32%
Plotting Data Summary:
Dataset Size: 100000, Clusters: 5
Execution Time: 2.74s
CPU Usage: 26 points, Range: [0.0, 536.2]
Memory Usage: 26 points, Range: [1.7, 2.5]
Dataset Size: 100000, Clusters: 7
Execution Time: 3.50s
CPU Usage: 33 points, Range: [157.3, 564.4]
Memory Usage: 33 points, Range: [2.0, 2.5]
Dataset Size: 500000, Clusters: 5
Execution Time: 6.92s
CPU Usage: 64 points, Range: [97.0, 671.2]
Memory Usage: 64 points, Range: [4.1, 9.6]
Dataset Size: 500000, Clusters: 7
Execution Time: 6.92s
CPU Usage: 65 points, Range: [95.2, 601.8]
Memory Usage: 65 points, Range: [4.3, 7.3]
아래와 같은 전제조건을 취했습니다. 코드는 여기를 살펴봐주세요.
Alpine 기반의 컨테이너로 Random forest 로직을 구동해본 결과는 아래와 같았습니다:
Version | Trees | Training (s) | Prediction (s) | Total (s) |
---|---|---|---|---|
3.12 |
1 | 1.87 | 0.02 | 1.89 |
3.12 |
10 | 5.98 | 0.06 | 6.04 |
3.12 |
100 | 46.62 | 0.44 | 47.06 |
3.13 |
1 | 2.40 | 0.03 | 2.43 |
3.13 |
10 | 6.16 | 0.07 | 6.23 |
3.13 |
100 | 48.25 | 0.53 | 48.78 |
Debian 기반의 컨테이너로 Random forest 로직을 구동해본 결과는 아래와 같았습니다:
Version | Trees | Training (s) | Prediction (s) | Total (s) |
---|---|---|---|---|
3.12 |
1 | 1.93 | 0.02 | 1.96 |
3.12 |
10 | 5.93 | 0.07 | 6.00 |
3.12 |
100 | 46.82 | 0.42 | 47.24 |
3.13 |
1 | 2.35 | 0.03 | 2.38 |
3.13 |
10 | 6.34 | 0.10 | 6.44 |
3.13 |
100 | 49.17 | 0.49 | 49.66 |
Dataset generated: 100000 samples with 100 features
Testing RandomForest with 1 trees...
Training time: 1.87 seconds
Prediction time: 0.02 seconds
Total time: 1.89 seconds
Testing RandomForest with 2 trees...
Training time: 1.92 seconds
Prediction time: 0.03 seconds
Total time: 1.95 seconds
Testing RandomForest with 5 trees...
Training time: 3.51 seconds
Prediction time: 0.05 seconds
Total time: 3.56 seconds
Testing RandomForest with 10 trees...
Training time: 5.98 seconds
Prediction time: 0.06 seconds
Total time: 6.04 seconds
Testing RandomForest with 25 trees...
Training time: 11.93 seconds
Prediction time: 0.14 seconds
Total time: 12.07 seconds
Testing RandomForest with 50 trees...
Training time: 22.90 seconds
Prediction time: 0.24 seconds
Total time: 23.14 seconds
Testing RandomForest with 100 trees...
Training time: 46.62 seconds
Prediction time: 0.44 seconds
Total time: 47.06 seconds
Summary:
Trees Train(s) Predict(s) Total(s)
----------------------------------------
1 1.87 0.02 1.89
2 1.92 0.03 1.95
5 3.51 0.05 3.56
10 5.98 0.06 6.04
25 11.93 0.14 12.07
50 22.90 0.24 23.14
100 46.62 0.44 47.06
Dataset generated: 100000 samples with 100 features
Testing RandomForest with 1 trees...
Training time: 2.40 seconds
Prediction time: 0.03 seconds
Total time: 2.43 seconds
Testing RandomForest with 2 trees...
Training time: 2.32 seconds
Prediction time: 0.05 seconds
Total time: 2.37 seconds
Testing RandomForest with 5 trees...
Training time: 4.15 seconds
Prediction time: 0.08 seconds
Total time: 4.23 seconds
Testing RandomForest with 10 trees...
Training time: 6.16 seconds
Prediction time: 0.07 seconds
Total time: 6.23 seconds
Testing RandomForest with 25 trees...
Training time: 12.64 seconds
Prediction time: 0.15 seconds
Total time: 12.80 seconds
Testing RandomForest with 50 trees...
Training time: 24.41 seconds
Prediction time: 0.27 seconds
Total time: 24.68 seconds
Testing RandomForest with 100 trees...
Training time: 48.25 seconds
Prediction time: 0.53 seconds
Total time: 48.78 seconds
Summary:
Trees Train(s) Predict(s) Total(s)
----------------------------------------
1 2.40 0.03 2.43
2 2.32 0.05 2.37
5 4.15 0.08 4.23
10 6.16 0.07 6.23
25 12.64 0.15 12.80
50 24.41 0.27 24.68
100 48.25 0.53 48.78
Dataset generated: 100000 samples with 100 features
Testing RandomForest with 1 trees...
Training time: 1.93 seconds
Prediction time: 0.02 seconds
Total time: 1.96 seconds
Testing RandomForest with 2 trees...
Training time: 2.01 seconds
Prediction time: 0.03 seconds
Total time: 2.04 seconds
Testing RandomForest with 5 trees...
Training time: 3.83 seconds
Prediction time: 0.05 seconds
Total time: 3.88 seconds
Testing RandomForest with 10 trees...
Training time: 5.93 seconds
Prediction time: 0.07 seconds
Total time: 6.00 seconds
Testing RandomForest with 25 trees...
Training time: 12.12 seconds
Prediction time: 0.12 seconds
Total time: 12.24 seconds
Testing RandomForest with 50 trees...
Training time: 23.62 seconds
Prediction time: 0.27 seconds
Total time: 23.89 seconds
Testing RandomForest with 100 trees...
Training time: 46.82 seconds
Prediction time: 0.42 seconds
Total time: 47.24 seconds
Summary:
Trees Train(s) Predict(s) Total(s)
----------------------------------------
1 1.93 0.02 1.96
2 2.01 0.03 2.04
5 3.83 0.05 3.88
10 5.93 0.07 6.00
25 12.12 0.12 12.24
50 23.62 0.27 23.89
100 46.82 0.42 47.24
Dataset generated: 100000 samples with 100 features
Testing RandomForest with 1 trees...
Training time: 2.35 seconds
Prediction time: 0.03 seconds
Total time: 2.38 seconds
Testing RandomForest with 2 trees...
Training time: 2.21 seconds
Prediction time: 0.05 seconds
Total time: 2.26 seconds
Testing RandomForest with 5 trees...
Training time: 4.18 seconds
Prediction time: 0.05 seconds
Total time: 4.23 seconds
Testing RandomForest with 10 trees...
Training time: 6.34 seconds
Prediction time: 0.10 seconds
Total time: 6.44 seconds
Testing RandomForest with 25 trees...
Training time: 12.59 seconds
Prediction time: 0.13 seconds
Total time: 12.72 seconds
Testing RandomForest with 50 trees...
Training time: 25.04 seconds
Prediction time: 0.27 seconds
Total time: 25.30 seconds
Testing RandomForest with 100 trees...
Training time: 49.17 seconds
Prediction time: 0.49 seconds
Total time: 49.66 seconds
Summary:
Trees Train(s) Predict(s) Total(s)
----------------------------------------
1 2.35 0.03 2.38
2 2.21 0.05 2.26
5 4.18 0.05 4.23
10 6.34 0.10 6.44
25 12.59 0.13 12.72
50 25.04 0.27 25.30
100 49.17 0.49 49.66
Debian 기반의 컨테이너로 IO bound 태스크를 구동해본 결과는 아래와 같았습니다:
Alpine 기반의 컨테이너로 IO bound 태스크를 구동해본 결과는 아래와 같았습니다:
의외로, 미미한 차이가 있었고 심지어는 Alpine 기반 컨테이너가 근소하게나마 빨랐습니다.
CPU bound task에서 의외로 미미한 차이로 Alpine이 앞섰다는 점에서 놀라웠습니다.
이 시리즈를 통하여 아래 접근방안을 보여드렸습니다:
이 시리즈를 통해, 여러분들의 업무나 벤치마킹 및 PoC 에 작게나마 도움이 되었으면 좋겠습니다.
긴 글 읽어주셔서 감사합니다.