นี่คือสิ่งที่ฉันค้นพบหลังจากผ่านคำตอบที่ดีมากมายที่นี่และบทความอื่น ๆ
ขั้นแรกหากคุณกำลังโต้วาทีระหว่างtimeit
และtime.time
ที่timeit
มีสองข้อดี:
timeit
เลือกตัวจับเวลาที่ดีที่สุดสำหรับ OS และ Python เวอร์ชั่นของคุณ
timeit
ปิดใช้งานการรวบรวมขยะอย่างไรก็ตามนี่ไม่ใช่สิ่งที่คุณอาจต้องการหรือไม่ต้องการ
ตอนนี้ปัญหาคือtimeit
ไม่ง่ายอย่างนั้นเพราะมันต้องมีการตั้งค่าและสิ่งต่าง ๆ น่าเกลียดเมื่อคุณมีการนำเข้ามากมาย เป็นการดีที่คุณเพียงต้องการมัณฑนากรหรือใช้with
บล็อกและวัดเวลา น่าเสียดายที่ไม่มีสิ่งใดในตัวสำหรับสิ่งนี้คุณจึงมีสองตัวเลือก:
ตัวเลือก 1: ใช้ไลบรารี timebudget
timebudgetเป็นห้องสมุดที่หลากหลายและง่ายมากที่คุณสามารถใช้เพียงแค่ในหนึ่งบรรทัดของรหัสหลังจาก pip ติดตั้ง
@timebudget # Record how long this function takes
def my_method():
# my code
ตัวเลือกที่ 2: ใช้โมดูลรหัสโดยตรง
ฉันสร้างโมดูลยูทิลิตี้เล็ก ๆ ด้านล่าง
# utils.py
from functools import wraps
import gc
import timeit
def MeasureTime(f, no_print=False, disable_gc=False):
@wraps(f)
def _wrapper(*args, **kwargs):
gcold = gc.isenabled()
if disable_gc:
gc.disable()
start_time = timeit.default_timer()
try:
result = f(*args, **kwargs)
finally:
elapsed = timeit.default_timer() - start_time
if disable_gc and gcold:
gc.enable()
if not no_print:
print('"{}": {}s'.format(f.__name__, elapsed))
return result
return _wrapper
class MeasureBlockTime:
def __init__(self,name="(block)", no_print=False, disable_gc=False):
self.name = name
self.no_print = no_print
self.disable_gc = disable_gc
def __enter__(self):
self.gcold = gc.isenabled()
if self.disable_gc:
gc.disable()
self.start_time = timeit.default_timer()
def __exit__(self,ty,val,tb):
self.elapsed = timeit.default_timer() - self.start_time
if self.disable_gc and self.gcold:
gc.enable()
if not self.no_print:
print('Function "{}": {}s'.format(self.name, self.elapsed))
return False #re-raise any exceptions
ตอนนี้คุณสามารถจับเวลาฟังก์ชั่นใด ๆ เพียงแค่ใส่มัณฑนากรไว้ข้างหน้า:
import utils
@utils.MeasureTime
def MyBigFunc():
#do something time consuming
for i in range(10000):
print(i)
หากคุณต้องการเวลาส่วนหนึ่งของรหัสแล้วเพียงแค่วางมันลงในwith
บล็อก:
import utils
#somewhere in my code
with utils.MeasureBlockTime("MyBlock"):
#do something time consuming
for i in range(10000):
print(i)
# rest of my code
ข้อดี:
มีเวอร์ชันที่สำรองไว้หลายรุ่นที่ลอยอยู่รอบ ๆ ดังนั้นฉันต้องการเน้นจุดเด่นบางประการ:
- ใช้ตัวจับเวลาจาก timeit แทน time.time ด้วยเหตุผลที่อธิบายไว้ก่อนหน้านี้
- คุณสามารถปิดใช้งาน GC ในช่วงเวลาได้หากต้องการ
- มัณฑนากรยอมรับฟังก์ชั่นที่มีชื่อหรือพารามิเตอร์ที่ไม่มีชื่อ
- ความสามารถในการปิดการใช้งานการพิมพ์ในช่วงเวลาบล็อก (ใช้
with utils.MeasureBlockTime() as t
แล้วt.elapsed
)
- ความสามารถในการทำให้ gc เปิดใช้งานสำหรับช่วงเวลาบล็อก