PERF_COUNT_SW_TASK_CLOCK을 사용하면 약 8ns 수준의 측정도 가능함 perf_event_mmap_page를 통해 공유 페이지에서 읽고, rdtsc 호출로 델타를 계산하는 방식임
문서화가 잘 안 되어 있고 오픈소스 구현도 거의 없음
정말 멋진 트릭임. 다만 perf_event 설정과 권한 요구가 크기 때문에 긴 수명의 스레드에 적합해 보임
seqlock이 필요한 이유를 물음. 페이지 값과 rdtsc 사이에서 컨텍스트 스위치가 일어나지 않도록 하기 위함인지 궁금함
아마 rdtsc 후 페이지 값을 다시 확인해 바뀌었으면 재시도하는 구조로 보임
참고로 clock_gettime도 vdso 기반 가상 syscall임
clock_gettime은 syscall이 아니라 vdso를 사용함
Flamegraph는 정말 훌륭한 도구임
코드만 봤을 땐 괜찮아 보이지만, flamegraph를 보면 “이게 뭐야?!” 싶을 때가 많음
정적 초기화가 아닌 초기화, 한 줄짜리 로거 호출이 비싼 직렬화를 유발하는 등 여러 문제를 발견했음
나는 icicle graph도 좋아함. flamegraph의 반대 방향으로 누적되어, 여러 경로가 공통 라이브러리를 호출할 때 병목을 보기 쉬움
Hacker News 의견들
“이 스레드의 CPU 사용 시간은 얼마인가?”라는 질문이 생각보다 너무 비싼 연산이라는 걸 알게 되었음
원자시계 수준의 기준이 없다면 절대적인 수치를 주장하기 어렵다고 생각함
clock_gettime()은 vDSO를 통해 컨텍스트 스위치를 피함. 그래서 flamegraph에서도 그 흔적이 보임CLOCK_VIRT나CLOCK_SCHED같은 경우는 여전히 syscall 호출이 필요함CLOCK_THREAD_CPUTIME_ID는 결국 커널로 넘어감. task struct를 참조해야 하기 때문임관련 커널 소스는 posix-cpu-timers.c,
cputime.c,
gettimeofday.c 참고
PERF_COUNT_SW_TASK_CLOCK을 사용하면 약 8ns 수준의 측정도 가능함perf_event_mmap_page를 통해 공유 페이지에서 읽고,rdtsc호출로 델타를 계산하는 방식임문서화가 잘 안 되어 있고 오픈소스 구현도 거의 없음
perf_event설정과 권한 요구가 크기 때문에 긴 수명의 스레드에 적합해 보임seqlock이 필요한 이유를 물음. 페이지 값과rdtsc사이에서 컨텍스트 스위치가 일어나지 않도록 하기 위함인지 궁금함아마
rdtsc후 페이지 값을 다시 확인해 바뀌었으면 재시도하는 구조로 보임참고로
clock_gettime도 vdso 기반 가상 syscall임clock_gettime은 syscall이 아니라 vdso를 사용함코드만 봤을 땐 괜찮아 보이지만, flamegraph를 보면 “이게 뭐야?!” 싶을 때가 많음
정적 초기화가 아닌 초기화, 한 줄짜리 로거 호출이 비싼 직렬화를 유발하는 등 여러 문제를 발견했음
평소엔 async-profiler의 HTML 생성기를 쓰지만, 이번엔 단일 SVG를 위해 Brendan의 도구를 사용했음
/proc을 읽을 때의 메모리 오버헤드와 eBPF 프로파일링, 그리고 문서화가 부족한 user-space ABI의 역사를 다뤘음자세한 내용은 내 블로그 글에 정리했음
출처 트윗
Jaromir의 블로그도 정말 멋졌음