책 소개
소스 코드 파일은 여기에서 내려 받으실 수 있습니다.
https://github.com/AcornPublishing/software-dynamics
요약
소프트웨어 엔지니어라면 누구나 마주할 수 있는 예기치 못한 성능 문제를 발견하고, 평가하며 해결하는 방법을 설명하는 책이다. 저자가 수많은 세월을 걸쳐 겪어온 문제들과 이를 정확히 간파하는 방법을 제시하고 도구들을 설명한다. 4가지 근본이 되는 하드웨어 자원을 설명하고 이들의 상호작용을 이해하며 다양한 도구와 함께 분석한다. 이 책을 끝까지 읽은 후에는 모호했던 문제를 더욱 정확히 이해하고 해결 방법을 스스로 찾을 힘을 얻게 될 것이다.
추천의 글
저자는 요즘 거의 볼 수 없을 만큼 놀라운 방법으로 문제를 해결한다. 단순히 추측만 하는 것은 좋아하지 않으며 문제 해결의 모든 현상을 이해해야 한다고 늘 주장한다. 하드웨어와 소프트웨어가 포함된 현대의 컴퓨터 시스템의 복잡한 문제를 마주할 때, 대부분의 프로그래머는 무슨 일이 발생하는지 대강 짐작하며 성능 디버깅을 시작할 뿐 아니라 손쉽게 해결할 수 있다는 희망을 품고 “이것도 시도해보고, 저것도 시도해보며” 문제에 접근한다. 이런 방법을 사용하는 사람들은 프로그램의 성능을 저하하는 복잡한 상호 작용을 진짜로 찾을 가능성은 암묵적으로 외면해버린다. 컴퓨터와 관련된 어떤 것이든 이해하는 것보다 더 중요할 수 있다는 생각은 저자에게는 통하지 않는다. 때로 프로그램의 동작을 측정할 수 있는 기본적인 도구가 없는 경우가 더러 있다. 그럴 때 저자는 프로그램의 동적인 동작을 잘 관찰할 수 있도록 실행에 필수적인 정보를 모아 시각화하는 프레임워크와 함께 관찰 도구를 구축한다.
저자의 놀라운 경력을 살펴보면 복잡한 컴퓨팅 시스템을 이해하는 능력을 자신하는 이유를 분명히 알 수 있다. 그는 1959년, 10세에 프로그래머가 됐고 컴퓨팅에 관한 호기심으로 프랜 앨런(Fran Allen), 프레드 브룩스(Fred Brooks), 존 코크(John Cocke), 돈 크누스(Don Knuth), 척 세이츠(Chuck Seitz) 같은 거물들과 긴밀하게 협력하며 연구해왔다. 이 산업에서 그가 이룬 업적들은 매우 광범위하다. DEC 알파 아키텍처를 공동 설계하는 일부터 어도비의 포토샵 작업, 지메일과 같은 구글 웹 서비스의 속도 향상에도 기여해왔다.
1995년 DEC에 합류하면서 내가 저자와 만났을 때 그는 이미 우리 분야에서 전설이었다. 저자가 구글에서 재임하는 동안 나는 그와 함께 하며 특별한 즐거움을 느껴왔을 뿐 아니라 그의 문제 해결 방식을 직접 지켜볼 수 있었다. 이 책의 독자들은 글의 명료함과 함께 하드웨어와 소프트웨어 상호작용에 관한 지식, 프로그램이 실행하며 남기는 상세한 흔적을 관찰하며 드러난 단서들로 어떻게 성능 디버깅 문제를 설명하는지 지켜보며 즐거워할 것이다. 이 책과 비교할 수 있는 다른 책이 없기 때문에 프로그래머와 컴퓨터 설계자 모두에게 아주 유용할 것이다. 이 책은 작가만큼이나 유일무이한 책이다.
이 책에서 다루는 내용
◆ CPU와 메모리, 디스크/SSD, 네트워크 그리고 자원들간의 간섭과 관련된 문제를 측정하고 해결한다.
◆ 항상 느리게 동작하는 프로그램을 수정하고 뚜렷한 이유 없이 간헐적으로 지연되는 프로그램을 수정한다.
◆ 기대치와 성능 데이터의 차이가 발생하는 이유를 확인한다.
◆ 과도한 실행과 느린 명령어의 실행, 자원 사용을 대기하고 소프트웨어 락 등으로 발생한 문제를 규명한다.
이 책의 대상 독자
프로그래밍 과제를 수행하며 설명된 소프트웨어 관찰 도구를 구현하고자 하는 독자에게 특히 권장되는 책이다. 이 책 전반에 걸쳐 현대의 복잡한 프로세서와 성능 향상 메커니즘에 관한 설명이 등장한다. 실수로 이런 메커니즘을 무력화한다면 더 큰 지연이 발생할 수 있다. 독자는 이 모든 것과 함께 컴퓨터 아키텍처와 마이크로 아키텍처에 대해 더 깊이 이해할 수 있을 것이다. 이 책은 소프트웨어 전문가와 수준 높은 학생을 위한 교과서다. 뿐만 아니라 컴퓨터 하드웨어 설계자, 운영체제 개발자, 시스템 아키텍처 IT 전문가, 실시간 시스템 설계자 및 게임 개발자가 관심을 가질 만한 내용도 다룬다. 사용자가 직면한 대기 시간에 집중해서 모든 프로그래머의 경력을 향상할 수 있는 기술을 얻게 될 것이다.
목차
목차
- 1부. 측정
- 1장. 너무 느린 내 프로그램
- 1.1 데이터 센터의 측면
- 1.2 데이터 센터 하드웨어
- 1.3 데이터 센터 소프트웨어
- 1.4 긴 꼬리 지연시간
- 1.5 프레임워크에 관한 고찰
- 1.6 크기 정도 산정
- 1.7 트랜잭션이 느린 이유
- 1.8 5가지 기본적인 자원들
- 1.9 요약
- 2장. CPU 측정
- 2.1 과거에서 지금까지의 발자취
- 2.2 지금의 위치
- 2.3 add 명령어의 지연시간 측정
- 2.4 직선형 코드의 실수
- 2.5 간단한 반복문, 반복문 오버헤드 실수, 컴파일러 최적화 실수
- 2.6 사용되지 않는 변수로 인한 실패
- 2.7 향상된 반복문
- 2.8 의존적인 변수들
- 2.9 실제 실행 지연시간
- 2.10 몇 가지 추가 차이점
- 2.11 요약
- 연습
- 3장. 메모리 측정
- 3.1 메모리 타이밍
- 3.2 메모리
- 3.3 캐시 구조
- 3.4 데이터 정렬
- 3.5 변환 색인 버퍼 구조
- 3.6 측정
- 3.7 캐시 라인 크기 측정
- 3.8 문제: N+1 프리패칭
- 3.9 종속적인 로드
- 3.10 무작위가 아닌 DRAM
- 3.11 캐시 계층별 크기 측정
- 3.12 캐시 계층별 접근도 측정
- 3.13 변환 버퍼 시간
- 3.14 활용도 낮은 캐시
- 3.15 요약
- 연습
- 4장. CPU와 메모리의 상호작용
- 4.1 캐시 상호작용
- 4.2 간단한 행렬 곱셈의 다양성
- 4.3 예측
- 4.4 초기화, 크로스 체크 그리고 관찰
- 4.5 초기의 결과
- 4.6 더 빠른 행렬 곱셈, 전치 방법
- 4.7 더 빠른 행렬 곱셈과 하위 블록 방법
- 4.8 캐시 인지 계산
- 4.9 요약
- 연습
- 5장. 디스크/SSD 측정
- 5.1 하드 디스크
- 5.2 SSD
- 5.3 소프트웨어 디스크 접근과 디스크 버퍼링
- 5.4 디스크를 빠르게 읽는 방법
- 5.5 대략적인 계산
- 5.6 디스크 쓰기는 얼마나 빠른가
- 5.7 결과
- 5.8 디스크 읽기
- 5.9 디스크에 쓰기
- 5.10 SSD 읽기
- 5.11 SSD에 쓰기
- 5.12 다중 전송
- 5.13 요약
- 연습
- 6장. 네트워크 측정
- 6.1 이더넷
- 6.2 허브, 스위치, 라우터
- 6.3 TCP/IP
- 6.4 패킷
- 6.5 원격 프로시저 호출(RPC)
- 6.6 슬롭
- 6.7 네트워크 트래픽 관찰
- 6.8 간단한 RPC 메시지 정의
- 6.9 샘플 로깅 설계
- 6.10 샘플 RPC를 이용한 클라이언트 서버 시스템
- 6.11 간단한 서버 프로그램
- 6.12 스핀 락
- 6.13 샘플 클라이언트 프로그램
- 6.14 하나의 샘플 클라이언트 서버 RPC 측정
- 6.15 RPC 로그 후처리
- 6.16 관찰
- 6.17 요약
- 연습
- 7장. 디스크와 네트워크 데이터베이스의 상호작용
- 7.1 시간 정렬
- 7.2 다중 클라이언트
- 7.3 스핀 락
- 7.4 실험 1
- 7.5 디스크 기반 데이터베이스
- 7.6 실험 2
- 7.7 실험 3
- 7.8 로깅
- 7.9 트랜잭션 지연시간의 다양성 이해
- 7.10 요약
- 연습
- 2부. 관찰
- 8장. 로깅
- 8.1 관찰 도구
- 8.2 로깅
- 8.3 기본적인 로깅
- 8.4 확장된 로깅
- 8.5 타임스탬프
- 8.6 RPC ID
- 8.7 로그 파일 포맷
- 8.8 로그 파일 관리
- 8.9 요약
- 9장. 측정 결과의 통합
- 9.1 균일한 속도와 버스트 이벤트
- 9.2 측정 간격
- 9.3 타임라인
- 9.4 타임라인의 더 많은 요약
- 9.5 시간 규모 히스토그램
- 9.6 이벤트별 측정 집계
- 9.7 시간에 따른 값의 패턴
- 9.8 시간 간격 업데이트
- 9.9 트랜잭션 예제
- 9.10 결론
- 10장. 대시보드
- 10.1 샘플 서비스
- 10.2 샘플 대시보드
- 10.3 마스터 대시보드
- 10.4 인스턴스별 대시보드
- 10.5 서버별 대시보드
- 10.6 정상 상태 검사
- 10.7 요약
- 연습
- 11장. 다른 도구들
- 11.1 관찰 도구의 종류
- 11.2 관찰 데이터
- 11.3 top 명령어
- 11.4 /proc과 /sys 수도 파일
- 11.5 time 명령어
- 11.6 perf 명령어
- 11.7 oprofile, CPU 프로파일러
- 11.8 strace, 시스템 콜
- 11.9 ltrace, CPU C 라이브러리 호출
- 11.10 ftrace, CPU 추적
- 11.11 mtrace, 메모리 할당/해제
- 11.12 blktrace, 디스크 추적
- 11.13 tcpdump와 와이어 샤크, 네트워크 추적
- 11.14 locktrace, 임계 구역 락
- 11.15 부하, 외부 호출, 그리고 트랜잭션 지연시간
- 11.16 요약
- 연습
- 12장. 추적
- 12.1 추적의 장점
- 12.2 추적의 단점
- 12.3 시작하며 묻는 세 가지 질문
- 12.4 예제: 초기의 프로그램 카운터 추적
- 12.5 예제 : 함수별 카운트와 시간
- 12.6 사례 연구 : 지메일의 함수별 추적
- 12.7 요약
- 13장. 관찰 도구 설계 원칙
- 13.1 관찰의 대상
- 13.2 관찰의 정도
- 13.3 오버헤드의 정도
- 13.4 설계 결과
- 13.5 사례 연구 : 히스토그램 버킷
- 13.6 데이터 디스플레이 설계
- 13.7 요약
- 3부. 커널-사용자 추적
- 14장. KUtrace: 목적, 설계, 구현
- 14.1 개요
- 14.2 목표
- 14.3 설계
- 14.4 구현
- 14.5 커널 패치와 모듈
- 14.6 컨트롤 프로그램
- 14.7 후처리
- 14.8 보안
- 14.9 요약
- 15장. KUtrace: 리눅스 커널 패치
- 15.1 추적 버퍼 데이터 구조
- 15.2 가공되지 않은 추적 블록 형태
- 15.3 추적 항목
- 15.4 IPC 추적 항목
- 15.5 타임스탬프
- 15.6 이벤트 번호
- 15.7 중첩된 추적 항목
- 15.8 코드
- 15.9 패킷 추적
- 15.10 AMD/인텔 x86-64 패치
- 15.11 요약
- 연습
- 16장. KUtrace: 리눅스 커널 모듈
- 16.1 커널 인터페이스 데이터 구조
- 16.2 모듈 로드/언로드
- 16.3 초기화와 추적 제어
- 16.4 추적 요청 구현
- 16.5 Insert1
- 16.6 InsertN
- 16.7 새로운 커널블록으로 전환
- 16.8 요약
- 17장. KUtrace: 사용자 모드 런타임 제어
- 17.1 추적 제어
- 17.2 홀로 동작하는 kutrace_control 프로그램
- 17.3 kutrace_lib 라이브러리
- 17.4 커널 모듈을 제어하는 인터페이스
- 17.5 요약
- 18장. KUtrace: 후처리
- 18.1 후처리 상세보기
- 18.2 rawtoevent 프로그램
- 18.3 eventtospan 프로그램
- 18.4 spantotrim 프로그램
- 18.5 spantospan 프로그램
- 18.6 samptonamek와 samptonameu 프로그램
- 18.7 makeself 프로그램
- 18.8 KUtrace JSON 형태
- 18.9 요약
- 19장. KUtrace: 소프트웨어 역동성 디스플레이
- 19.1 개요
- 19.2 1구역, 제어
- 19.3 2구역, Y축
- 19.4 3구역, 타임라인
- 19.5 4구역, IPC 범례
- 19.6 5구역, X축
- 19.7 6구역, 저장/복구
- 19.8 보조 제어
- 19.9 요약
- 4부. 추론
- 20장. 찾고자 하는 것
- 20.1 개요
- 21장. 너무 많은 실행
- 21.1 개요
- 21.2 프로그램
- 21.3 미스터리
- 21.4 탐구 및 추론
- 21.5 미스터리 이해
- 21.6 요약
- 22장. 느린 실행
- 22.1 개요
- 22.2 프로그램
- 22.3 미스터리
- 22.4 부동 소수점 방해 프로그램
- 22.5 메모리 방해 프로그램
- 22.6 미스터리의 이해
- 22.7 요약
- 23장. CPU 대기
- 23.1 프로그램
- 23.2 미스터리
- 23.3 탐구와 추론
- 23.4 미스터리2
- 23.5 미스터리2의 이해
- 23.6 보너스 미스터리
- 23.7 요약
- 연습
- 24장. 메모리 대기
- 24.1 프로그램
- 24.2 미스터리
- 24.3 탐구와 추론
- 24.4 미스터리 2 : 페이지 테이블 접근
- 24.5 미스터리 2의 이해
- 24.6 요약
- 연습
- 25장. 디스크 대기
- 25.1 프로그램
- 25.2 미스터리
- 25.3 탐구와 추론
- 25.4 40MB 읽기
- 25.5 순차적 4KB 블록 읽기
- 25.6 임의의 4KB 블록 읽기
- 25.7 SSD의 40MB 쓰기와 동기화
- 25.8 SSD의 40MB 읽기
- 25.9 한 번에 두 파일에 접근하는 두 프로그램
- 25.10 미스터리의 이해
- 25.11 요약
- 연습
- 26장. 네트워크 대기
- 26.1 개요
- 26.2 프로그램
- 26.3 실험 1
- 26.4 실험 1의 미스터리
- 26.5 실험 1 탐구와 추론
- 26.6 실험 1의 RPC 소요 시간
- 26.7 실험 2
- 26.8 실험 3
- 26.9 실험 4
- 26.10 미스터리의 이해
- 26.11 추가 이상 현상
- 26.12 요약
- 27장. 락 대기
- 27.1 개요
- 27.2 프로그램
- 27.3 실험 1 : 오랜 락 유지 시간
- 27.3.1 간단한 락
- 27.3.2 락 포화
- 27.4 실험 1의 미스터리
- 27.5 실험 1의 탐구와 추론
- 27.5.1 락 캡처
- 27.5.2 락 기아
- 27.6 실험 2 : 락 캡처 수정
- 27.7 실험 3 : 다중 락에 의한 락 경합 수정
- 27.8 실험 4 : 더 적은 락을 통한 락 경합 수정
- 27.9 실험 5 : 대시보드를 위한 RCU를 이용한 락 경합 수정
- 27.10 요약
- 28장. 시간 대기
- 28.1 주기적인 작업
- 28.2 타임아웃
- 28.3 타임 슬라이싱
- 28.4 인라인 실행 지연
- 28.5 요약
- 29장. 큐 지연
- 29.1 개요
- 29.2 요청 분포
- 29.3 큐 구조
- 29.4 작업 테스크
- 29.5 프라이머리 테스크
- 29.6 디큐
- 29.7 인큐
- 29.8 스핀 락
- 29.9 “작업” 루틴
- 29.10 간단한 예제
- 29.11 가능성 있는 문제
- 29.12 CPU 빈도수
- 29.13 복잡한 예제
- 29.14 CPU 대기 : RPC 로그
- 29.15 CPU 대기 : KUtrace
- 29.16 PlainSpinLock 결함
- 29.17 근본 원인
- 29.18 PlainSpinLock 수정 : 가시성
- 29.19 부하 분산
- 29.20 큐 길이 : 가시성
- 29.21 마지막 스핀
- 29.22 추가 결함
- 29.23 크로스 체크
- 29.24 요약
- 연습
- 30장. 정리
- 30.1 배운 것
- 30.2 배우지 못한 것
- 30.3 다음 단계
- 30.4 전체 책 요약
- 부록 A. 샘플 서버
- A.1 샘플 서버 하드웨어
- A.2 서버 연결
- 부록 B. 추적 항목
- B.1 고정 길이의 추적 항목
- B.2 가변 길이의 추적 항목
- B.3 이벤트 번호
- B.3.1 커널 모드 KUtrace 패치로 삽입된 이벤트
- B.3.2 유저 모드 코드로 삽입된 이벤트
- B.3.3 후처리 코드로 삽입된 이벤트
도서 오류 신고
정오표
정오표
[ p.39: 박스 ]
데이터 센터에서는 보통 꼬리 지연시간이 짧고 평균 지연시간이 긴 것보다 평균 지연시간이 짧고 꼬리 지연시간이 긴 것을 더 선호한다.
->
데이터 센터에서는 보통 평균 지연시간이 짧고 꼬리 지연시간은 긴 것보다 평균 지연시간이 길고 꼬리 지연시간이 짧은 것을 더 선호한다.