3,200% CPU 사용률

2 weeks ago 4

  • 과거에 내 시스템의 CPU 사용률이 3,200%에 달해 32코어가 모두 가득 찼음
  • Java 17 런타임을 사용하고 있었고, 스레드 덤프에서 CPU 시간을 확인하여 CPU 시간으로 정렬하니 유사한 스레드들이 다수 발견
  • 문제의 코드 분석
    • 스택 트레이스를 통해 BusinessLogic 클래스의 29번째 줄을 확인
    • 해당 코드는 unrelatedObjects 리스트를 반복하면서 relatedObject의 값을 treeMap에 삽입하는 형태
    • 이는 반복문 내부에서 unrelatedObject를 사용하지 않는 비효율적인 코드

코드 수정 및 테스트

  • 불필요한 반복문을 제거하고 treeMap.put(relatedObject.a(), relatedObject.b()); 한 줄로 수정
  • 수정 전후로 단위 테스트를 수행하였으나, 문제를 재현할 수 없었음
  • treeMap과 unrelatedObjects의 크기가 각각 1,000,000개 이상이어도 문제가 발생하지 않음

문제의 원인 발견

  • treeMap이 여러 스레드에서 동시 접근되고 있었으며, 동기화가 되어 있지 않았음
  • 이는 여러 스레드가 TreeMap을 동시에 수정하면서 발생하는 문제였음

실험을 통한 문제 재현

  • 여러 스레드가 공유된 TreeMap을 무작위로 업데이트하는 실험을 진행
  • try-catch 블록을 사용하여 NullPointerException을 무시하도록 설정
  • 실험 결과, CPU 사용률이 500%까지 상승하는 현상을 확인

결론

  • 동기화되지 않은 TreeMap의 동시 수정은 심각한 성능 문제를 야기할 수 있음
  • 이러한 문제를 방지하기 위해 TreeMap을 동기화하거나 ConcurrentMap과 같은 스레드 안전한 컬렉션을 사용하는 것이 권장됨

Read Entire Article