JIT를 인식하는 프로파일러¶
목표: PyPy JIT을 인식하고, 어느 루프에서 얼마만큼의 시간 비율이 소비되었는지 보여주는 프로파일러를 만드는 것입니다.
장기 목표: 프로파일러가 수집한 데이터를 jitviewer와 통합합니다.
이 아이디어는 루프(loop)나 브리지(bridge)에 진입하고 빠져나갈 때마다 PYPYLOG에 이벤트를 기록하는 것입니다.
예상 출력¶
[100] {jit-profile-enter loop1 # 예: 진입 브릿지 [101] jit-profile-enter} … [200] {jit-profile-enter loop0 # loop1에서 loop0로 JUMP [201] jit-profile-enter} … [500] {jit-profile-exit loop0 # 예: 가드(guard) 실패로 인해 [501] jit-profile-exit}
이 예제에서 loop1에서의 탈출은 암시적인데, loop0으로 진입하고 있기 때문입니다. 따라서 진입 브리지에서 200-100=100틱을, 실제 루프에서 500-200=300틱을 소비했습니다.
“내부(inner)” 브리지는 어떻게 처리할 것인가?¶
“내부 브리지(Inner bridges)”는 자신이 시작된 루프로 다시 점프하는 브리지를 말합니다. 이를 처리하는 방법에는 두 가지가 있습니다:
- 이들을 무시합니다: 루프에 진입할 때는 기록하지만, 컴파일된 내부 브리지로 점프할 때는 기록하지 않습니다. 종료 이벤트는 컴파일되지 않은 가드(guard) 실패나 다른 루프로의 JUMP인 경우에만 기록됩니다.
- 우리는 각 내부 브리지(bridge)의 진입/종료를 기록합니다
해결책 (2)의 단점은 매 반복마다 브리지를 타는 특정 루프들이 있다는 것입니다. 따라서 이 경우 방대한 수의 이벤트를 기록하게 되어, 상당한 오버헤드가 추가될 수 있고 결국 프로파일링된 데이터를 쓸모없게 만들 수 있습니다.
루프 진입/탈출 감지¶
참여 방법:
- 트레이싱/컴파일 직후
- 인터프리터로부터, 루프가 이미 컴파일되어 있다면
- 다른 루프로부터, JUMP 연산을 통해
- 핫 가드(guard) 실패로부터 (해결책을 선택하는 경우 우리가 무시하는) (1) 위 참조)
- XXX: 빠진 것이 있나요?
종료 방법:
- 가드(guard) 실패(블랙홀 진입)
- 가드(guard) 실패(브릿지로 점프) (해결책 (1)의 경우 무시됨)
- 다른 루프로 점프
- XXX: 제가 놓친 것이 있을까요?
call_assembler에 대해: 처음에는 call_assembler를 그냥 무시해야 한다고 생각합니다. 호출 내부에서 소요된 시간은 그것을 호출하는 루프에 귀속될 것입니다.