요약
- 프로덕션 API 서비스를 x86_64에서 ARM64로 옮기고 시간대를 맞춰 비교했더니, 평균 CPU는 34.6% → 34.0%로 거의 그대로인데 태스크 간 Max−Min 폭이 39.3%p → 28.8%p로 26.7% 줄었다.
- Max가 12.4% 내려가고 Min이 21.2% 올라간 모양이다. 전체가 내려간 게 아니라 유독 느린 태스크가 사라진 것이다.
- 그래서 ARM 전환의 효과를 평균 CPU나 평균 응답시간으로만 보면 "차이 없음"으로 읽힌다. 봐야 할 지표는 태스크 간 분산이다.
본문
왜 편차를 보나
같은 태스크 정의로 띄운 Fargate 태스크의 물리 CPU 세대는 뽑기이고, x86에서는 2017년 Skylake부터 2025년 Xeon 6까지 섞여 나온다(Fargate는 물리 CPU 세대를 고를 수 없어 같은 태스크 정의라도 성능이 1.5~2배 갈린다). 반면 ARM64 쪽은 64회 관찰에서 Graviton3 아니면 Graviton4만 나왔고, 최악의 뽑기인 Graviton3가 x86의 최빈값보다 빨랐다(Fargate에서 서브넷을 한 AZ로 묶어도 CPU 세대는 못 고른다).
세대 폭이 좁으면 태스크마다 처리 능력이 덜 갈린다. 로드밸런서가 요청을 고르게 나눠주는 상황에서 처리 능력만 다르면, 그 차이는 태스크별 CPU 사용률의 분산으로 드러난다. 그래서 "ARM으로 옮기면 편차가 줄어들 것"은 전환 전에 세울 수 있는 예측이고, 아래는 그 예측을 프로덕션에서 재본 것이다.
측정 방법
- 전환 시점은 태스크 정의 리비전으로 특정한다.
describe-task-definition의runtimePlatform.cpuArchitecture를 리비전별로 훑으면 어느 리비전에서X86_64→ARM64로 바뀌었는지, 그게 언제 등록됐는지가 나온다. vCPU·메모리는 2048/4096으로 양쪽 동일했다. - 지표는
AWS/ECS의CPUUtilization을 5분 주기로Minimum/Maximum/Average세 통계로 받는다. 이 세 값이 곧 "그 5분 동안 태스크들 중 가장 한가한 놈 / 가장 바쁜 놈 / 평균"이라 Max−Min이 태스크 간 편차가 된다. - 트래픽에 하루 주기가 있으므로 단순 전후 평균 대신 시간대(hour-of-day)를 맞춰 비교한다. 24개 시간대 각각에서 전/후 평균을 구하고 그 24쌍을 다시 평균했다. 전: 전환 전 47시간, 후: 전환 후 40시간.
- 배포·오토스케일로 태스크가 새로 뜨는 5분 구간은 Minimum이 0 근처로 찍혀 폭을 부풀린다.
Minimum >= 5로 걸러낸 값도 같이 본다.
결과
| 지표 | 전(x86_64) | 후(ARM64) | 변화 |
|---|---|---|---|
| Average | 34.6 | 34.0 | −1.9% |
| Maximum | 56.0 | 49.1 | −12.4% |
| Minimum | 16.7 | 20.2 | +21.2% |
| Max−Min | 39.3 | 28.8 | −26.7% |
기동 구간을 걸러도 Max−Min은 35.6 → 26.2로 −26.4%, 사실상 같은 결론이다. 24개 시간대 중 Max−Min이 늘어난 시간대는 하나도 없었다.
교란 요인 배제
- 태스크 수: 6.48 → 6.54로 사실상 같다. 태스크가 늘어 부하가 분산돼서 폭이 준 게 아니다.
- AZ: 전환 며칠 전부터 서비스를 단일 AZ에 고정해둔 상태라 전·후 구간 모두에 같이 적용된다. 이번 차이의 원인이 아니다.
- 트래픽: 타깃당 요청 수가 6.2% 줄었다. 다만 트래픽이 일률로 6% 줄면 Min도 같이 내려가야 하는데 오히려 21% 올랐다. 폭이 줄어든 방향을 트래픽 감소로는 설명할 수 없다.
해석과, 아직 확인 못 한 것
관찰된 사실은 "평균은 그대로인데 상단이 내려오고 하단이 올라왔다"까지다. 원인을 CPU 세대 균질화로 돌리는 것은 위 두 노트의 사전 측정에 기댄 해석이고, 이번 전환 이후 실제로 뜬 태스크들의 칩을 직접 읽어 확인하지는 않았다. 확인하려면 enable_execute_command가 켜진 상태에서 태스크마다 아래를 찍고 MIDR로 세대를 판별하면 된다. aarch64에는 model name이 없다.
aws ecs execute-command --cluster <cluster> --task <task-arn> \
--container <container> --interactive \
--command "grep -m1 'CPU part' /proc/cpuinfo"
이 측정의 한계
전 구간은 월·화, 후 구간은 수·목이라 시간대는 맞췄지만 요일은 안 맞는다. 전환 후 관측이 아직 이틀이 안 된다. 요일까지 맞춰 한 주 뒤 다시 재는 게 남았다.
관련 노트
- Fargate는 물리 CPU 세대를 고를 수 없어 같은 태스크 정의라도 성능이 1.5~2배 갈린다
- Fargate에서 서브넷을 한 AZ로 묶어도 CPU 세대는 못 고른다
- 처리 속도가 제각각인 서버에는 round robin 대신 least outstanding requests를 쓴다
- 변수 하나만 바꾼 카나리를 같은 타깃그룹에 동시 투입하면 부하 교란 없이 회귀 원인을 격리한다
- 하이퍼스케일러가 ARM으로 간 이유는 성능이 아니라 x86에 라이선스 창구가 없어서다
참고
- https://docs.aws.amazon.com/AmazonECS/latest/developerguide/available-metrics.html
- https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html
- https://docs.aws.amazon.com/AmazonECS/latest/userguide/ecs-exec.html
- https://github.com/torvalds/linux/blob/master/arch/arm64/include/asm/cputype.h