파이썬

[Python 프로파일링] py-spy와 yappi로 파이썬 코드 성능 분석하기

코샵 2024. 12. 2. 09:54
반응형

소개

파이썬 프로그램의 성능을 분석하고 최적화하기 위해서는 프로파일링 도구가 필수적입니다. py-spy와 yappi는 각각 다른 특징을 가진 강력한 프로파일링 도구입니다. 이번 글에서는 두 도구의 사용법과 활용 방법을 자세히 알아보겠습니다.

py-spy 란?

py-spy는 파이썬 프로그램을 중단하지 않고도 실시간으로 프로파일링할 수 있는 샘플링 프로파일러입니다.

설치 방법

pip install py-spy

기본 사용법

# 프로파일링할 예제 코드
# example.py
import time

def slow_function():
    time.sleep(2)
    return "Done"

def main():
    for _ in range(3):
        slow_function()

if __name__ == "__main__":
    main()

# 프로파일링 실행
# 터미널에서:
py-spy record -o profile.svg python example.py

실시간 모니터링

# Top 형태의 실시간 모니터링
py-spy top python example.py

# 특정 프로세스 모니터링
py-spy top --pid 12345

yappi 란?

yappi는 멀티스레드 프로그램을 위한 프로파일러로, 스레드별 상세한 프로파일링 정보를 제공합니다.

설치 방법

pip install yappi

기본 사용법

import yappi
import time

def function_to_profile():
    time.sleep(1)
    return sum(i * i for i in range(1000))

# 프로파일링 시작
yappi.start()

# 코드 실행
function_to_profile()

# 프로파일링 종료
yappi.stop()

# 결과 출력
stats = yappi.get_func_stats()
stats.print_all()

# 결과를 파일로 저장
stats.save('callgrind.out', 'callgrind')

스레드 프로파일링

import yappi
import threading
import time

def worker():
    for _ in range(3):
        time.sleep(0.1)

def profile_threads():
    yappi.set_clock_type("wall")  # 실제 경과 시간 측정
    yappi.start()

    # 여러 스레드 생성
    threads = [
        threading.Thread(target=worker)
        for _ in range(3)
    ]

    # 스레드 실행
    for thread in threads:
        thread.start()

    # 스레드 종료 대기
    for thread in threads:
        thread.join()

    yappi.stop()

    # 스레드별 통계 출력
    threads_stats = yappi.get_thread_stats()
    for thread in threads_stats:
        print(
            f"Thread {thread.id}: {thread.name}, "
            f"CPU: {thread.cpu_time}, "
            f"Real: {thread.wall_time}"
        )

콜백 함수 프로파일링

import yappi

def profile_callback(func_stats, path):
    """프로파일링 결과를 처리하는 콜백"""
    with open(path, 'w') as f:
        for stat in func_stats:
            f.write(f"{stat.name}: {stat.ttot}\n")

yappi.start()

# 프로파일링할 코드 실행
your_function()

yappi.stop()

# 콜백으로 결과 처리
stats = yappi.get_func_stats()
profile_callback(stats, 'profile_results.txt')

메모리 프로파일링

import yappi
import memory_tracker

@memory_tracker.track_memory
def memory_intensive_function():
    large_list = [i for i in range(1000000)]
    return sum(large_list)

yappi.start()
memory_intensive_function()
yappi.stop()

# 메모리 사용량 통계
stats = yappi.get_func_stats()
stats.print_all(columns={
    "name": 40,
    "ncall": 5,
    "tsub": 8,
    "ttot": 8,
    "tavg": 8
})

실전 활용 예제

웹 애플리케이션 프로파일링

from flask import Flask
import yappi

app = Flask(__name__)

def profile_request(func):
    """요청 프로파일링 데코레이터"""
    def wrapper(*args, **kwargs):
        yappi.start()
        result = func(*args, **kwargs)
        yappi.stop()

        stats = yappi.get_func_stats()
        stats.save(f'profile_{func.__name__}.prof', 'pstat')
        yappi.clear_stats()

        return result
    return wrapper

@app.route('/')
@profile_request
def index():
    # 시간이 걸리는 작업 시뮬레이션
    time.sleep(0.1)
    return "Hello, World!"

병렬 처리 프로파일링

import yappi
from multiprocessing import Pool
import time

def worker_function(x):
    time.sleep(0.1)
    return x * x

def profile_parallel_processing():
    yappi.start()

    with Pool(4) as p:
        result = p.map(worker_function, range(10))

    yappi.stop()

    # 프로세스별 통계
    stats = yappi.get_func_stats()
    stats.print_all()

성능 비교 분석

import yappi
import time

def compare_implementations():
    implementations = {
        'method1': lambda: sum(i * i for i in range(10000)),
        'method2': lambda: sum(map(lambda x: x * x, range(10000)))
    }

    results = {}

    for name, impl in implementations.items():
        yappi.clear_stats()
        yappi.start()

        impl()

        yappi.stop()
        stats = yappi.get_func_stats()
        results[name] = stats[0].ttot

    return results

마치며

py-spy와 yappi는 각각의 장점이 있는 강력한 프로파일링 도구입니다. py-spy는 실시간 모니터링과 시각화에 강점이 있고, yappi는 스레드별 상세 분석에 특화되어 있습니다. 프로그램의 특성과 분석하고자 하는 성능 지표에 따라 적절한 도구를 선택하여 사용하면 효과적인 성능 최적화가 가능합니다.