프로파일링으로 병목지점찾기
시스템 정확히 파악하기
어느부분이 느린지, 어느 RAM을 많이 쓰는지,
디스크 I/0 나 네트워크 I/O 를 과도하게 발생시키는 부분이 어디인지 확인
1. 시간측정(time.time(), decorator)
2. 어떤 함수가 오래걸리는지 측정(cProfile -> snakeviz 로 시각화)
3. 선택 함수를 한줄씩 프로파일링(line_profiler)
4. CPU에서 실행된 명령의수, CPU 캐시가 효율적으로 활용되었는지 검사(perf stat)
5. RAM 사용량 측정(memory_profiler, psutil)
파이썬은 문장을 왼쪽에서 오른쪽으로 검사하며 기회주의적이기 때문에 빨리 긑나는 검사를 등식의 왼쪽에 두는게 좋다
성능 향상을 위한 가설설정
1. 쉽게 검증할수 있는 가설 성립
2. 그 가설을 검증할수 있도록 코드수정, 한번에 한가지만 검사
3. 결론을 뒷받침할 근거 수집
접근 방법에 따라 달라지는 복잡도
def fn_expressive(upper = 1_000_000) :
total = 0
for n in range(upper):
total += n
return total
def fn_terse(upper = 1_000_000):
return sum(range(upper))
%timeit fn_expressive()
%timeit fn_terse() # 두배 더 빠르게 작동 => 더 적은 파이썬 바이트코드 생성
바이트코드 명령어 확인 (fn_expressive vs fn_terse)
fn_expressive : 1. 지역변수 2,
2. for 문 : 리스트 순회 , StopIteration 예외 발생 검사, n 의 타입 검사하는 total.__add__ 호출
fn_terse : C 리스트 표현식 함수 호출로 바로 최종 결과 생성 but still 객체 타입 검사
최적화 중에 단위 테스트하기
coverage.py 를 통하여 테스트한 부분 안한 부분 파악
line_profiler 나 memory_profiler 에서 @profile 을 사용하면 단위테스트에서 NameError 발생
@profile 데커레이터를 지역 네임 스페이스에 추가 안하기 때문 -> 아무일도 하지 않는 @profile 데커레이터 이용
import time
if 'line_profiler' not in dir() and 'profile' not in dir() :
def profile(func):
return func
def test_some_fn():
assert some_fn(2) == 4
assert some_fn(1) == 1
assert some_fn(-1) == 1
@profile
def some_fn(useful_input):
time.sleep(1)
return useful_input ** 2
if __name__ == "__main__" :
print(f"Example call 'some_fn(2)' == {some_fn(2)}")
'컴퓨터 공부 > 파이썬 공부' 카테고리의 다른 글
고성능 파이썬(6) (0) | 2021.07.05 |
---|---|
고성능 파이썬(5) (0) | 2021.07.04 |
고성능 파이썬(4) (0) | 2021.06.28 |
고성능 파이썬(3) (0) | 2021.06.27 |
고성능 파이썬(1) (0) | 2021.06.26 |