Tachyon 샘플링 프로파일러를 사용해 free-threading 성능 병목을 찾아내고, 추상화가 멀티스레딩 성능에 미치는 영향을 살펴봅니다.
비록 이전 글에서 살펴본 최적화가 있었지만, free-threading 성능을 달성하는 데에는 여전히 많은 장애물이 있습니다.
한 가지 구체적인 문제는, 흔히 무해해 보이는 코드 추상화가 멀티스레딩 성능을 해칠 수 있다는 점입니다. 이것은 얼마 전 지금 Python에서 스레드는 얼마나 자유로운가?에서 살펴본 내용이기도 합니다.
다음 코드는 __getitem__을 호출할 때마다 grid 객체를 잠가야 했기 때문에 병목 지점이 됩니다. 이는 내부의 튜플에 직접 접근하는 것보다 여러 배 느린 것으로 드러났습니다. 그리고 이 결과는 최신 Python 3.15.0a6t 버전에서도 여전히 사실입니다. (정말 길기도 하네요!)
class Grid:
tiles: tuple[tuple[bool, ...], ...]
...
def __getitem__(self, key: Pair) -> bool:
return self.tiles[key[0]][key[1]]
Python은 다방면의 분야에 쓰이는 언어이지만 OOP는 분명히 장려되므로, 여기서 제가 만든 이 추상화는 일반적인 기준으로는 'Pythonic'하다고 여겨집니다. 이는 코드가 스레드에서 실행될 것으로 예상되는지 여부에 따라 모범 사례가 달라질 수 있다는 괴리를 만들어 냅니다.
이는 Python이 멀티스레딩 성능 손실 없이 추상화를 가능하게 해 주는 몇몇 최적화를 아직 갖추지 못했음을 시사합니다.
더 나쁜 것은, 이런 종류의 성능 문제를 디버깅할 실질적인 방법이 없었다는 점입니다. 프로파일러는 free-threading을 제대로 지원하지 않았고, 과정은 그저 많은 추측에 의존할 수밖에 없었습니다.
다행히도, Tachyon이라는 샘플링 프로파일러가 도입되면서 이 모든 것이 3.15에서 바뀔 예정입니다.
이 새로운 프로파일러는 다양한 기능을 갖추고 있습니다.
하지만 가장 중요한 점은 여러 스레드를 네이티브하게 지원한다는 것입니다. 저는 원래의 추상화된 버전 코드를 이 프로파일러로 실행해 보았습니다.
sudo -E uv run -p 3.15.0a6t python -m profiling.sampling run -a --flamegraph -o profile.html -r 20khz d6.py
다음 사항에 유의하세요.
-a는 모든 스레드를 프로파일링하기 위해 필요하며, 기본값으로는 메인 스레드만 프로파일링됩니다.
플레임 그래프를 보면 큰 빨간 기둥들이 보입니다. 빨간색은 hot path를 뜻하며, 코드가 가장 많은 시간을 소비하는 구간을 나타냅니다.
특히 시간의 75%가 __getitem__을 통해 grid에 접근하는 다음 줄에서 소비되고 있습니다.
if grid[curr] or curr == obstruction:
일반적으로 어느 정도의 hot path는 예상할 수 있지만, 이 한 줄이 이렇게 큰 비중의 시간을 차지하는 것은 예상 밖입니다. 이것은 문제가 어디에 있을지에 대한 좋은 단서를 제공합니다.
이제 우리는 이미 해결 방법을 알고 있습니다. __getitem__ 호출을 우회하고 내부 튜플에 직접 접근합니다.
if tiles[r][c] or (r, c) == obstruction:
결과는 다음과 같습니다.

새로운 줄은 이제 파란색(cold path)이며 실행 시간의 5.32%만 차지합니다. 이는 병목이 이제 제거되었음을 보여 줍니다.
Tachyon은 이 외에도 훨씬 더 많은 것을 제공하며, free-threading에만 유용한 것도 아닙니다. 예를 들어 저는 asyncio 프로그램에 이것을 적용해 보고 싶습니다.
벤치마킹이 제공하는 것은 일반 개발자들이 free-threading을 활용하고 성능을 추론할 수 있는 경로입니다. 저는 이것을 통해 이런 성능 함정을 더 많이 드러내고 해결할 수 있으며, 어쩌면 pure Python 개발자들에게 free-threading이 더 자연스러운 것이 될 수 있다고 생각합니다.
Pelican의 지원을 받아 자랑스럽게 구동됩니다. Python의 장점을 크게 활용합니다. 테마는 Smashing Magazine의 것입니다. 감사합니다!