본문 바로가기

Dot ./개인 공부 기록용

Numbers Everyone Should Know 개발자가 알아야 하는 숫자 - Jeff Dean (제프 딘)

Numbers Everyone Should Know

이러한 숫자를 이해하면 특히 데이터에 액세스하거나 조작해야 하는 작업을 처리할 때 소프트웨어 설계에 대한 선택에 도움이 될 수 있다.

Numbers Everyone Should Know (https://colin-scott.github.io/personal_website/research/interactive_latency.html)

 

2020년 기준

L1 cache reference 1 ns  
Branch mispredict 3 ns  
L2 cache reference 4 ns  
Mutex lock/unlock 17 ns  
Main memory reference 100 ns  
Compress 1K bytes with Zippy 2,000 ns 2 μs
Read 1 MB sequentially from memory 3,000 ns 3 μs
SSD random read 16,000 ns 16 μs
Round trip within same datacenter 500,000 ns 500 μs
Read 1 MB sequentially from disk 825,000 ns 825 μs
Disk seek 2,000,000 ns 2 ms
Send packet CA->Netherlands->CA 150,000,000 ns 150 ms

 

 

How long to generate image results page (30 thumbnails)?

이미지 썸네일 30개가 있는 웹페이지를 생성하는 경우 처리하는 속도를 계산해보자. (컴퓨터 이미지 읽기 속도 100MB/s라고 가정)

 

Design 1: Read serially, thumbnail 256K images on the fly

이 프로세스는 순차적으로 데이터를 검색하고 256K 이미지 썸네일을 읽는 작업 과정으로 약 136.8ms가 소요된다.

  • 30 seeks * 2 ms/seek + 30 * 256K / 100 MB/s = 136.8 ms

 

여기서 병목 현상은 디스크 검색과 디스크에서 데이터를 읽는 데 걸리는 시간이다.

 

Design 2: Issue reads in parallel

병렬 읽기를 구현하면 썸네일 생성에 필요한 시간을 크게 줄일 수 있다. 

  • 2 ms/seek + 256K read / 100 MB/s = 4.56 ms (다른 변수들은 고려하지 않음)

 

이는 네트워크 지연과 같은 다른 요인을 고려하지 않은 수치이지만 병렬 처리의 힘을 느낄 수 있다. (단일 이미지 또는 전체 썸네일 셋 캐싱 및 썸네일과 사전 계산과 같은 전략을 포함하여 이러한 설계에는 여러 가지 변형이 있다.) 이 Design1, Design2와 같은 간단한 비교로도 설계 능력이 소프트웨어의 성능에 얼마나 큰 영향을 미치는지 잘 보여준다. 

 

Design for Low Latency

Jeff는 지연 시간을 낮추기 위한 설계가 매우 중요하다고 말한다. 평균 시간을 낮추는 것뿐만 아니라 P90 및 P99 시간도 마찬가지로 중요하다. 사용자 만족도는 일관된 성능에 달려 있기 때문이다.

 

지연 시간을 개선하는 방법

  1. 캐싱을 효과적으로 사용하고 인터랙티브한 요청에 더 높은 우선순위를 부여하는 것이다.
  2. 두 번째로 중요한 요소는 병렬 처리이다. 최신 컴퓨터에서 점점 더 표준이 되고 있는 다중 코어의 성능을 활용하면 처리량과 지연 시간을 모두 크게 개선할 수 있다.

 

Threads

멀티코어 머신이 확산됨에 따라 스레딩의 중요성이 점점 더 커지고 있다. 스레드를 사용하지 않는다면 컴퓨터의 잠재력을 충분히 활용하지 못하는 것이다. 멀티 스레드 프로그래밍은 어렵게 느껴질 수 있지만 처음부터 스레드를 고려하면 훨씬 더 쉽게 컨트롤할 수 있다. 멀티 쓰레딩은 처리량과 지연 시간 모두에서 윈윈 구조이다. 다만, race condition은 주의해야 한다.

 

Data Access, RPCs, and Encoding

데이터 액세스 패턴을 이해하는 것은 중요하다. 디스크 읽기든 메모리 참조든, 이러한 측면을 파악하면 보다 효율적인 시스템을 구축하는 데 도움이 된다. 마찬가지로 원격 프로시저 호출(RPC)의 경우, 송수신하는 데이터의 양과 네트워크에 미치는 영향을 파악해야 한다.

데이터를 효과적으로 인코딩하는 것도 또 다른 중요한 포인트이다. CPU는 빠른 반면 메모리와 대역폭은 귀한 자원이므로 가능한 경우 가변 길이 인코딩, 압축, 압축된 인메모리 표현들을 사용하는 것이 좋다.

 

예를 들어 가변 길이 인코딩을 사용하여 애플리케이션에서 정수를 표현한다고 가정해 보자. 가변 길이 인코딩은 더 적은 바이트를 사용하여 더 작은 숫자를 위한 공간을 절약할 수 있으며, 대부분의 정수가 상대적으로 작은 경우 특히 유용할 수 있다.

 

또한 대량의 데이터를 처리하는 애플리케이션의 경우 Zippy와 같은 데이터 압축 알고리즘을 구현하는 것이 유용할 수 있다. 이러한 기술은 데이터의 크기를 줄여 디스크에 데이터를 읽거나 쓰거나 네트워크를 통해 전송하는 데 필요한 시간을 줄이는 데 도움이 된다. 압축된 인메모리 표현은 데이터에 액세스하는 시간을 더욱 단축하여 전반적인 성능을 향상시킬 수 있다.

 

분산 시스템에서는 원격 프로시저 호출(RPC)과 관련된 지연 시간을 이해하는 것이 매우 중요하다. 데이터 센터 내 왕복 시간(Round trip within same datacenter)은 최대 500μs에 달할 수 있으며, 이는 로컬 작업보다 훨씬 더 큰 규모이다. 따라서 각 호출에서 전송되는 데이터의 양을 최적화하고 RPC의 수를 줄이면 전체 지연 시간을 줄이는 데 도움이 될 수 있다.

 

End

Jeff Dean의 프레젠테이션은 소프트웨어 설계 및 개발 프로세스를 최적화하는 데 적용할 수 있는 인사이트를 제공한다. 짧은 지연 시간을 위한 설계, 스레드 활용, 효과적인 데이터 액세스 패턴 관리, RPC 이해, 효율적인 데이터 인코딩 등 이러한 원칙은 높은 퍼포먼스를 갖춘 사용자 친화적인 애플리케이션을 만드는 데 도움이 될 것이다.

 

지금까지 논의한 수치는 성능의 벤치마크 역할을 해야 한다. 애플리케이션을 개발할 때 의사 결정 과정을 위한 로드맵을 제공한다. 데이터를 읽는 방법, 스레드 관리, 짧은 지연 시간을 위한 설계, 데이터 인코딩 등 각 선택 사항은 애플리케이션의 전반적인 성능에 영향을 미친다.

 

핵심은 지속적으로 학습하고, 새로운 지식을 적용하고, 설계를 반복하는 것이다. 아주 작은 최적화도 상당한 성능 향상으로 이어져 더 나은 사용자 경험과 더 효율적인 시스템으로 이어질 수 있다는 점을 항상 기억하자. 

 

Refs

http://brenocon.com/dean_perf.html

https://gist.github.com/jboner/2841832

https://colin-scott.github.io/personal_website/research/interactive_latency.html