본문 바로가기
Python

[Python] Class로 수행시간 측정 decorator 만들기

by ds31x 2023. 8. 18.

 

decorator가 유용하게 사용되는 경우 중 하나가 특정 function 등의 수행시간 측정이다.

 

function으로 decorator를 만드는 경우에 대한 정리는 이전에 했기 때문에 여기선 class로 작성한다.

 

해당 decorator는 arguments를 통해

  • 어떤 단위로 측정할지와
  • cpu시간만을 측정할지 등을 선택할 수 있게 구성함.

code는 다음과 같음.

import time

class DsElapsedTime:

  def __init__(self, is_sec=True, only_cpu=False):
    # decorator가 동작 방식을 정의하는 변수 초기화.
    self.is_sec = is_sec
    self.only_cpu = only_cpu

  def __call__(self, func): #decorate할 func 을 argument로 받음.
    def wrap_func(*args, **kargs):

      if self.only_cpu == False:
        start_t = time.perf_counter_ns()
        mode = 'real time'
      else:
        start_t = time.process_time_ns()
        mode = 'cpu time'

      # func 수행.
      ret_v = func(*args, **kargs)

      if self.only_cpu == False:
        end_t = time.perf_counter_ns()
      else:
        end_t = time.process_time_ns()

      elapsed_t = end_t - start_t
      unit = 'nano-sec'
      if self.is_sec:
        elapsed_t = elapsed_t/1000_000_000
        unit = 'sec'

      print(f'{func.__name__} elapsed: {elapsed_t: .4f} sec ({mode})')
      return ret_v

    return wrap_func

@DsElapsedTime()
def test_func():
  time.sleep(10)

test_func()

@DsElapsedTime(only_cpu=True)
def test_func():
  time.sleep(10)

test_func()
  • time.perf_counter_ns : time.time_ns과 유사하지만 보다 높은 time resolution을 지원함. 실제 수행시간을 nano-second 단위로 반환.
  • time.process_time_ns : 실제 cpu에서 처리된 시간만을 반환함. 역시 nano-second 단위임.

_ns 만 떼어내면 second 단위로 반환이 이루어짐.

결과는 다음과 같음.

test_func elapsed:  10.0075 sec (real time)
test_func elapsed:  0.0545 sec (cpu time)

 

위의 예에서는 생성자에서 parameter를 가지고 있기 때문에, decorator부분에서 parenthesis가 기재되어야 함.
즉, @DsElapsedTime로만 처리하면 에러가 발생한다.

 

Parameter가 필요없는 경우엔 다음과 같이 구현하면 된다.

  • 생성자에서 감싸줄 함수를 argument로 받음.
  • __call__에서 감싸줄 함수와 같은 parameters를 가지면 됨.
import time

class DsElapsedTime:

  def __init__(self, func):
    # decorate 할 func을 생성자에서 받음.
    self.func = func 

  def __call__(self, *args, **kargs): #decorate할 func의 argument와 같아야함. 
    start_t = time.perf_counter()
    mode = 'real time'

    # func 수행.
    ret_v = self.func(*args, **kargs) 
    end_t = time.perf_counter()
    elapsed_t = end_t - start_t
    unit = 'sec'
    print(f'{self.func.__name__} elapsed: {elapsed_t: .4f} sec ({mode})')
    return ret_v

@DsElapsedTime
def test_func():
  time.sleep(10)

test_func()
  • second단위로 실제 수행시간을 반환하도록 수정함.(parameter로 변경이 안됨. 고정형.)

결과는 다음과 같음.

test_func elapsed:  10.0108 sec (real time)

더 읽어보면 좋은 자료.

https://mebadong.tistory.com/106

 

[Python] Python 코드 실행시간 측정하기

Python 코드 실행시간을 측정하는 방법도 Java와 크게 다르지 않다. 1. time.time() 이용하기 가장 간단한 방법이다. time.time()을 사용하여 시작 시간과 종료 시간을 저장해 그 차이를 계산하는 방법이다

mebadong.tistory.com

http://abh0518.net/tok/?p=604 

 

Python, Decorator 써본 이야기 | 아브의 꿀오분

어쩌다 python-django 로 웹 어플리케이션 하나를 만들게 되었는데 이거 은근 신세계다. django 같은 프레임워크야 뭐 많으니까 놀랄게 없더라도 python의 decorator는 나에게 뭔가 신세계를 보여줬다. java

abh0518.net

 

728x90