Top 10 Performance Mistakes라는 글이 있어 독자 여러분에게 간략하게 요즘을 소개해드리겠다. 내용은 다름이 아니라 우리가 자주 저지르는 성능 관련 실무 목록이다.
- 10. 업그레이드하지 않음: 많은 회사들이 시스템이 충분히 빠르지 않다고 불평을 하며, 더 나은 알고리즘과 자료 구조를 찾지만, 실제로는 "업그레이드"가 필요한 경우가 많다. 운영체제, JVM이나 CLR 등을 업그레이드해야 하는데, "새로운 버전에 버그가 있을지도 모른다"며 변명을 댄다.
- 9. 중복된 작업: 웹 페이지를 서비스하는 시스템이 아주 느린 바람에, 개발자들이 데이터베이스 문제로 생각해서 실제로 튜닝 작업에 들어갔다. 하지만 프로파일러를 돌려보니 ORM을 7000번 호출하는 루프가 존재했기에 페이지 읽기가 느렸다. 루프를 수정하고 나니 시스템이 정상으로 돌아왔다.
- 8. 데이터 적재: 메모리 관련 연산은 유형에 따라 다르다. 다양한 자료 구조의 성능에 대한 기초 지식이 있어야 한다. 예를 들어, 2GB 이상의 자료인 경우 자바의 HashMap이 .Net의 Dictionary보다 10배 이상 느리다. 물론 .Net이 자바보다 느린 경우도 있다.
- 7. 너무 많은 할당: 메모리를 너무 많이 할당할 경우 가베지 컬렉터가 대규모 데이터 집합을 처리하느라 상당한 시간을 소비한다.
- 6. 병행 프로그래밍: 특정 알고리즘에서는 병행 프로그래밍이 아주 매력적이지만, 한계와 부하가 존재한다. 암달의 법칙과 USL(Universal Scalability Law)를 생각해야 한다. 특히 병행 시스템에서 구성 요소 사이의 통신과 관련한 성능에 특히 주의해야 한다.
- 5. TCP에 대한 이해 부족: TCP를 제대로 이해하지 못한 상태에서 마이크로서비스를 고려하는 실수가 의외로 많다. Nagle 알고리즘을 비활성화하기 위해 TCP_NODELAY를 고려하고, 여러 작은 패킷을 차례로 전송하자.
- 4. 동기식 통신: 클라이언트와 서버 사이의 동기식 통신은 빠른 통신이 필요한 시스템에서 문제로 등장한다. 더 비싸고 빠른 하드웨어 대신 비동기식 통신을 고려하자.
- 3. 텍스트 인코딩: JSON이나 XML과 같은 텍스트 인코딩 형식을 사용해 데이터를 전송하는 방법을 택하는 이유는 "인간이 읽을 수 있기" 때문이다. 하지만, 두 시스템 사이에서 통신이 일어날 때 사람이 읽는 경우는 없다. 물론 텍스트 편집기로 디버깅은 편하겠지만, CPU를 많이 소비하게 된다. 이진 형식을 고려하자.
- 2. API 설계: 성능에 가장 부정적인 영향을 주는 몇 가지 실수는 API와 관련이 있다. API만 제대로 설계되더라도 불필요한 메모리 복사와 추가 처리가 필요하지 않다.
- 1. 로깅: #1 성능 문제의 주범은 로깅에 소비되는 시간이다. 스레드를 아무리 많이 사용하더라도 로깅에 필요한 시간은 선형적으로 증가한다. 로거는 시스템에서 찾을 수 있는 최고 병목 중 하나다. 해법은 비동기식 로거 사용이다. 또한 동일한 오류를 계속해서 저장하는 방법도 피해야 한다. 처음 오류가 발생했을 때 한 번만 찍는 방안을 고안하자.