2.6 OProfile
2.6.1 Introduction
OProfile은 낮은 오버헤드로 실행 중인 모든 코드를 프로파일링할 수 있는 시스템 전체 프로파일러이다.
OProfile은 커널 드라이버, 샘플 데이터 수집을 위한 데몬, 데이터를 정보로 변환하기 위한 여러 포스트 프로파일링 도구로 구성된다.
2.6.1.1 Overview
OProfile은 CPU의 하드웨어 성능 카운터를 활용하여 흥미있는 통계의 다양한 프로파일링을 가능하게 하며, 기본적인 소요 시간 프로파일링에도 사용할 수 있다.
하드웨어와 소프트웨어 인터럽트 핸들러, 커널 모듈, 커널, 공유 라이브러리와 애플리케이션과 같은 모든 코드가 프로파일된다.
2.6.1.2 Features
OProfile에는 다음과 같은 기능이 있다.
- Unobtrusive(눈에 거슬리지 않는) - 특별한 재컴파일이나 래퍼 라이브러리가 필요하지 않다. 사용자가 주석이 달인 소스를 생성하려는 경우가 아니면, 디버그 기호(gcc에서 -g 옵션)도 필요하지 않다. 커널 패치가 필요하지 않다. 모듈을 삽입하기만 하면 된다.
- System-wide profiling(시스템 전체 프로파일링) - 시스템에서 실행되는 모든 코드는 프로파일링되어, 시스템 성능을 분석할 수 있다.
- Performance counter support(성능 카운터 지원) - 다양한 하위 레벨 데이터를 수집하고 코드의 특정 섹션에 연결할 수 있다.
- Call-graph support(호출 그래프 지원) - OProfile은 gprof 스타일의 호출 그래프 프로파일링 데이터를 제공할 수 있다.
- Low overhead (낮은 오버헤드) - OProfile은 샘플링 빈도와 작업 부하에 따라 1~8%의 일반적인 오버헤드가 있다.
- Post-profile analysis(포스트 프로파일 분석) - 프로파일 데이터는 기능(function) 레벨이나 명령(instruction) 레벨의 세부 사항에 대해 생성할 수 있다.
- System support(시스템 지원) - 모든 i.MX 지원 커널과 함께 작동한다.
2.6.1.3 Hardware Operation
OProfile은 연속적인 통계 프로파일러이다.
프로파일은 각 CPU의 현재 레지스터를 정기적으로 샘플링(인터럽트 핸들러에서, 인터럽트시 저장되어 있는 PC 값이 저장됨)하고 해당 런타임 PC 값을 프로그래머에게 의미 있는 것으로 변환하여 생성된다.
OProfile은 샘플링된 PC 값의 스트림을 인터럽트 시점에 어떤 작업이 실행 중이였는지에 대한 세부 정보와 함께 가져와서, 이 값을 특정 바이너리 파일에 대한 파일 오프셋으로 변환하여 이를 달성한다. 따라서 각 PC 값은 바이너리 이미지 오프셋의 튜플(그룹이나 집합)로 변환된다. 사용자 공간의 도구는 이 데이터를 사용하여 특정 어셈블리 명령, 심볼과 소스 라인(있는 경우, 바이너리 디버그 정보로)을 포함하여 코드의 출처를 재구성할 수 있다.
실제로 실행되는 어떤것과 얼마나 자주, 보다 더 자주 이와 같은 PC 값을 정기적으로 샘플링하면, 이 통계적 근사치는 현실을 반영하기에 충분하다. 공통 작업에서, 각 샘플 인터럽트 사이의 시간은 고정된 수의 클럭 사이클로 조정된다. 이는 결과적으로 CPU가 가장 많은 시간을 소비하는 위치를 반영함을 의미한다. 이는 성능 분석에 매우 유용한 정보 소스이다.
Arm CPU는 하드웨어 레벨에서 이러한 이벤트를 측정할 수 있는 하드웨어 성능 카운터를 제공한다. 일반적으로, 이러한 카운터는 각 이벤트마다 한 번씩 증가하고 미리 정의된 이벤트 수에 도달하면 인터럽트를 생성한다. OProfile은 이러한 인터럽트를 사용하여 샘플을 생성할 수 있으며, 프로파일 결과는 주어진 이벤트의 인스턴스 수를 발생시킨 코드에 대한 통계적 근사치이다.
2.6.1.4 Architecture-specific Components
OProfile은 특정 아키텍처에서 사용할 수 있는 하드웨어 성능 카운터를 지원한다. 이러한 카운터의 설정과 관리에 대한 세부 사항을 관리하는 코드는 관련 arch/arm/oprofile 디렉토리의 커널 소스 트리에서 찾을 수 있다. 아키텍처별 구현은 초기화 시 oprofile_operations 구조체를 채우는 방식으로 작동한다. 이는 setup(), start(), stop() 등과 같은 작업의 세트를 제공하여 성능 카운터 레지스터가 하드웨어별 세부 사항을 관리한다.
아키텍처 코드에 사용할 수 있는 다른 중요한 기능은 oprofile_add_sample()이다. 이는 인터럽트 시점에 취한 특정 샘플이 일반 OProfile 드라이버 코드로 공급되는 곳이다.
2.6.1.5 oprofilefs Pseudo Filesystem
OProfile은 사용자 공간 /dev/oprofile에 마운트되는 oprofilefs로 알려진 pseudo 파일 시스템을 구현한다. 이는 사용자 공간에서 구성을 보고하고 수신하기 위한 작은 파일뿐만 아니라 OProfile 사용자 공간에서 샘플을 받는 실제 문자(character) 디바이스로 구성된다. setup() 시점에, 아키텍처별 코드는 성능 카운터의 세부 사항과 관련된 추가적인 구성 파일을 추가할 수 있다. 파일 시스템에는 다양한 OProfile 이벤트에 대한 유용한 카운터가 있는 stats 디렉토리도 포함되어 있다.
2.6.1.6 Generic Kernel Driver
일반 커널 드라이버는 drivers/oprofile에 있으며, 커널에서 OProfile이 작동하는 방식의 핵심을 형성한다. 일반 커널 드라이버는 아키텍처별 코드(oprofile_add_sample()를 통해)에서 전달된 샘플을 가져와서, /dev/oprofile/buffer 문자 디바이스로 사용자 공간 데몬에 데이터를 릴리스할 때까지 이 데이터(변환된 구성으로)를 버퍼링한다.
2.6.1.7 OProfile Daemon
OProfile 사용자 공간 데몬은 커널에서 제공하는 로우 데이터를 가져와서 디스크에 저장한다. 커널에서 단일 데이터 스트림을 가져오고, 여러 샘플 파일(var/lib/oprofile/samples/current/ 에서 사용가능)에 대한 샘플 데이터를 기록한다. 개별 기능의 이점을 위해, 이런 샘플 파일의 이름과 경로는 샘플의 출처를 반영하도록 변경된다. 여기에는 스레드 ID, 바이너리 파일 경로, 사용된 이벤트 유형 등이 포함될 수 있다.
인터럽트에서 디스크 파일로의 마지막 단계 후, 데이터는 이제 영구적이다(즉, 시스템 실행 시 변경 사항이 저장된 데이터를 무효화하지 않음). 이렇게 하면 언제든지 이 데이터에서 포스트 프로파일링 도구를 실행할 수 있다(원본 바이너리 파일이 여전히 사용 가능하고 변경되지 않는다고 가정).
2.6.1.8 Post Profiling Tools
수집된 데이터는 유용한 형식으로 사용자에게 제공되어야 한다. 이는 포스트 프로파일링 도구의 역할이다. 일반적으로, 사용 가능한 샘플 파일의 하위 집합을 취합하고, 관련된 바이너리 파일과 상관관계에 있는 각 파일을 로드하고 처리하며, 사용자가 읽을 수 있는 정보를 생성한다.
2.6.1.9 Interrupt Requirements
OProfile 드라이버와 관련하여 생성되는 인터럽트의 수는 많이 있다. 레이턴시 요구 사항은 필요하지 않다. 인터럽트가 생성되는 속도는 이벤트에 따라 다르다.
2.6.2 Software Operation
Cortex-A7 i.MX의 경우, Oprofile은 Cortex-A7 Event Monitor를 추가해야 한다.
2.6.2.1 Source Code Structure
Oprofile 플랫폼별 소스 파일은 arch/arm/oprofile에서 사용할 수 있다.
Table 17. OProfile Source Files
File | Description |
---|---|
common.c | 모든 플랫폼에 필요한 구현이 포함된 소스 파일 |
2.6.2.2 Menu Configuration Options
이 모듈에 대해 다음 Linux 커널 구성이 제공된다.
메뉴 구성에서 다음 모듈을 활성화한다:
- CONFIG_OPROFILE - oprofile 드라이버에 대한 구성 옵션이다. menuconfig에서 이 옵션은 아래에서 사용할 수 있다.
- General Setup > Profiling support (EXPERIMENTAL) > OProfile system profiling (EXPERIMENTAL)
2.6.2.3 Programming Interface
이 드라이버는 PMU와 L2 캐시 EVTMON 카운터를 구성하고 컨트롤하는 데 필요한 모든 방법을 구현한다.
자세한 내용은 build: make htmldocs에서 생성된 Linux 문서를 참조한다.
2.6.2.4 Example Software Configuration
다음 단계는 OProfile을 구성하는 방법의 예를 보여준다:
- bitbake linux-imx -c menuconfig 커맨드를 사용한다. 먼저 화면에서 Package 목록으로 이동하여 Oprofile을 선택한다.
- 그런 다음, 첫 번째 화면으로 돌아가서 Configure Kernel을 선택하고 섹션 2.6.2.2의 지침에 따라 커널 공간에서 Oprofile을 활성화한다.
- 구성을 저장하고 빌드를 시작한다.
- Oprofile 바이너리를 대상 rootfs에 복사한다. vmlinux를 /boot 디렉토리에 복사하고 Oprofile을 실행한다.
root@ubuntu:/boot# opcontrol --separate=kernel --vmlinux=/boot/
vmlinux
root@ubuntu:/boot# opcontrol --reset
Signalling daemon... done
root@ubuntu:/boot# opcontrol --setup --event=CPU_CYCLES:100000
root@ubuntu:/boot# opcontrol --start
Profiler running.
root@ubuntu:/boot# opcontrol --dump
root@ubuntu:/boot# opreport
Overflow stats not available
CPU: ARM V7 PMNC, speed 0 MHz (estimated)
Counted CPU_CYCLES events (Number of CPU cycles) with a unit
mask of 0x00 (No un
it mask) count 100000
CPU_CYCLES:100000|
samples| %|
------------------
4 22.2222 grep
CPU_CYCLES:100000|
samples| %|
------------------
4 100.000 libc-2.9.so
2 11.1111 cat
CPU_CYCLES:100000|
samples| %|
------------------
1 50.0000 ld-2.9.so
1 50.0000 libc-2.9.so
...
root@ubuntu:/boot# opcontrol --stop
Stopping profiling.