วิธีการวัดเวลาที่ผ่านไปใน Python


1207

สิ่งที่ฉันต้องการคือการเริ่มต้นการนับเวลาที่ไหนสักแห่งในรหัสของฉันแล้วรับเวลาที่ผ่านไปเพื่อวัดเวลาที่ใช้ในการประมวลผลฟังก์ชั่นบางอย่าง ฉันคิดว่าฉันใช้โมดูล timeit ผิด แต่เอกสารนั้นทำให้ฉันสับสน

import timeit

start = timeit.timeit()
print("hello")
end = timeit.timeit()
print(end - start)

คำตอบ:


1453

หากคุณต้องการวัดเวลานาฬิกาแขวนที่ผ่านไประหว่างสองจุดคุณสามารถใช้ time.time():

import time

start = time.time()
print("hello")
end = time.time()
print(end - start)

สิ่งนี้ให้เวลาดำเนินการเป็นวินาที

ตัวเลือกอื่นตั้งแต่ 3.3 อาจใช้perf_counterหรือprocess_timeขึ้นอยู่กับความต้องการของคุณ ก่อน 3.3 ขอแนะนำให้ใช้time.clock(ขอบคุณแอมเบอร์ ) อย่างไรก็ตามปัจจุบันไม่ได้รับการสนับสนุน:

บน Unix ให้ส่งคืนเวลาตัวประมวลผลปัจจุบันเป็นหมายเลขทศนิยมที่แสดงในหน่วยวินาที ความแม่นยำและในความเป็นจริงคำจำกัดความของความหมายของ“ เวลาตัวประมวลผล” นั้นขึ้นอยู่กับฟังก์ชัน C ในชื่อเดียวกัน

บน Windows, QueryPerformanceCounter()ฟังก์ชั่นนี้ส่งกลับวินาทีผนังนาฬิกาผ่านไปนับตั้งแต่สายแรกที่ฟังก์ชั่นนี้เป็นจำนวนจุดลอยอยู่บนพื้นฐานของฟังก์ชัน โดยทั่วไปความละเอียดจะดีกว่าหนึ่งไมโครวินาที

เลิกใช้ตั้งแต่รุ่น 3.3 : การทำงานของฟังก์ชั่นนี้ขึ้นอยู่กับแพลตฟอร์ม: การใช้งานperf_counter()หรือprocess_time()แทนทั้งนี้ขึ้นอยู่กับความต้องการของคุณที่จะมีพฤติกรรมที่กำหนดไว้อย่างดี


17
และสำหรับ microseconds ให้ใช้ datetime.time ()
Inca

110
(สำหรับการวัดประสิทธิภาพtime.clock()เป็นที่ต้องการจริง ๆ แล้วเนื่องจากไม่สามารถแทรกแซงได้หากนาฬิการะบบยุ่ง แต่.time()ส่วนใหญ่จะทำสิ่งเดียวกันให้สำเร็จ)
Amber

4
ฉันคิดว่า python -mtimeit นั้นดีกว่าเพราะมันทำงานได้มากกว่าเดิมและมันก็ถูกสร้างขึ้นเป็นวิธีดั้งเดิมในการวัดเวลาในไพ
ธ อน

4
มีวิธีที่ดีในการแปลงเวลา execturion เป็นวินาทีเช่น HH: MM :: SS
Danijel

12
print(timedelta(seconds=execution_time))@Danijel: แม้ว่ามันจะเป็นคำถามแยกต่างหาก
jfs

688

ใช้แทนtimeit.default_timer timeit.timeitอดีตมอบนาฬิกาที่ดีที่สุดบนแพลตฟอร์มและเวอร์ชันของ Python ของคุณโดยอัตโนมัติ:

from timeit import default_timer as timer

start = timer()
# ...
end = timer()
print(end - start) # Time in seconds, e.g. 5.38091952400282

timeit.default_timerถูกกำหนดให้กับ time.time () หรือ time.clock () ขึ้นอยู่กับระบบปฏิบัติการ ใน Python 3.3+ default_timerคือtime.perf_counter ()บนทุกแพลตฟอร์ม ดูPython - time.clock () กับ time.time () - ความแม่นยำ?

ดูสิ่งนี้ด้วย:


28
คำตอบที่ยอดเยี่ยม - การใช้timeitจะให้ผลลัพธ์ที่แม่นยำมากขึ้นเนื่องจากมันจะอธิบายถึงสิ่งต่าง ๆ เช่นการรวบรวมขยะและความแตกต่างของระบบปฏิบัติการโดยอัตโนมัติ
lkgarrison

1
มันให้เวลาเป็นมิลลิวินาทีหรือไม่?
เคธี่

3
@KushushooTiwari ในเสี้ยววินาที
jfs

5
ฉันคิดว่าต้องเพิ่มบันทึกย่อนี้จากเอกสารราชการdefault_timer() measurations can be affected by other programs running on the same machine, so the best thing to do when accurate timing is necessary is to repeat the timing a few times and use the best time. The -r option is good for this; the default of 3 repetitions is probably enough in most cases. On Unix, you can use time.clock() to measure CPU time.
KGS

1
@KGS: การวัดประสิทธิภาพนั้นซับซ้อนมาก ๆ (มันง่ายที่จะทำให้เข้าใจผิด) มีข้อสังเกตอื่น ๆ อีกมากมายที่อาจเกี่ยวข้องกันที่นี่ ติดตามลิงก์ในคำตอบ คุณอาจสนใจperfโมดูล (ไม่มีอยู่ในเวลาที่ตอบ)ที่มีอินเตอร์เฟสเดียวกัน แต่บางครั้งมันก็แตกต่างจากการtimeitตัดสินใจของโมดูลเกี่ยวกับวิธีการวัดประสิทธิภาพของเวลา
jfs

129

Python 3 เท่านั้น:

เนื่องจาก time.clock () ถูกเลิกใช้ตั้งแต่ Python 3.3คุณจะต้องใช้time.perf_counter()สำหรับช่วงเวลาของระบบหรือtime.process_time()สำหรับช่วงเวลาของกระบวนการเพียงวิธีที่คุณใช้time.clock():

import time

t = time.process_time()
#do some stuff
elapsed_time = time.process_time() - t

ฟังก์ชั่นใหม่process_timeจะไม่รวมเวลาที่ผ่านไประหว่างการนอนหลับ


28
ใช้timeit.default_timertime.perf_counterแทน อดีตจะเลือกตัวจับเวลาที่เหมาะสมเพื่อวัดประสิทธิภาพเวลาที่ปรับสำหรับแพลตฟอร์มและเวอร์ชัน Python ของคุณ process_time()ไม่ได้รวมถึงเวลาระหว่างการนอนหลับและดังนั้นจึงไม่เหมาะสมที่จะวัดเวลาที่ผ่านไป
jfs

2
ฉันกำลังใช้การนำไปใช้งานที่แนะนำโดยปิแอร์เป็นค่าที่กำหนดในไม่กี่วินาที
ugotchi

คำตอบนี้ดูเหมือนจะไม่เป็นไปตามที่คาดหวัง (คำถามก็ไม่เจาะจงมากนัก) มีการวัดสอง "เวลา": เวลานาฬิกาแขวนระหว่างสองจุดของการใช้ cpu ของกระบวนการ
Franklin Piat

87

ฟังก์ชั่นที่คุณต้องการเวลา

test.py:

def foo(): 
    # print "hello"   
    return "hello"

วิธีที่ง่ายที่สุดในการใช้timeitคือโทรจากบรรทัดคำสั่ง:

% python -mtimeit -s'import test' 'test.foo()'
1000000 loops, best of 3: 0.254 usec per loop

อย่าพยายามใช้time.timeหรือtime.clock(ไร้เดียงสา) เพื่อเปรียบเทียบความเร็วของฟังก์ชั่น พวกเขาสามารถให้ผลที่ทำให้เข้าใจผิด

PS อย่าวางคำสั่งการพิมพ์ไว้ในฟังก์ชันที่คุณต้องการ มิฉะนั้นเวลาที่วัดได้จะขึ้นอยู่กับความเร็วของเครื่อง


65

การทำเช่นนี้สนุกกับผู้จัดการบริบทที่จดจำเวลาเริ่มต้นโดยอัตโนมัติเมื่อเข้าสู่withบล็อกจากนั้นหยุดเวลาสิ้นสุดเมื่อออกจากบล็อก ด้วยการใช้เล่ห์เหลี่ยมเล็ก ๆ น้อย ๆ คุณสามารถรับจำนวนครั้งที่ผ่านไปในบล็อกจากฟังก์ชันตัวจัดการบริบทเดียวกันได้

ไลบรารีหลักไม่มีสิ่งนี้ (แต่น่าจะควร) คุณสามารถทำสิ่งต่าง ๆ เช่น:

with elapsed_timer() as elapsed:
    # some lengthy code
    print( "midpoint at %.2f seconds" % elapsed() )  # time so far
    # other lengthy code

print( "all done at %.2f seconds" % elapsed() )

นี่คือรหัสบริบทที่เพียงพอที่จะทำเคล็ดลับ:

from contextlib import contextmanager
from timeit import default_timer

@contextmanager
def elapsed_timer():
    start = default_timer()
    elapser = lambda: default_timer() - start
    yield lambda: elapser()
    end = default_timer()
    elapser = lambda: end-start

และรหัสตัวอย่างบางส่วนที่ทำงานได้:

import time

with elapsed_timer() as elapsed:
    time.sleep(1)
    print(elapsed())
    time.sleep(2)
    print(elapsed())
    time.sleep(3)

โปรดทราบว่าด้วยการออกแบบฟังก์ชั่นนี้ค่าส่งคืนของelapsed()จะถูกตรึงเมื่อออกจากบล็อกและการโทรเพิ่มเติมจะส่งกลับช่วงเวลาเดียวกัน (ประมาณ 6 วินาทีในตัวอย่างของเล่นนี้)


2
ตัวอย่างผู้จัดการบริบทอื่น ๆ : dabeaz.blogspot.fr/2010/02/…
Jérôme

1
@ Jérômeเป็นตัวอย่างที่ดี - ฉันปรับมันเป็นคำตอบอื่น - stackoverflow.com/a/41408510/243392
Brian Burns

62

การวัดเวลาในไม่กี่วินาที:

from timeit import default_timer as timer
from datetime import timedelta

start = timer()
end = timer()
print(timedelta(seconds=end-start))

ผลผลิต :

0:00:01.946339

1
นี่คือคำตอบที่กระชับที่สุดกับผลลัพธ์ที่สะอาดที่สุด
Dave Liu

56

ฉันชอบสิ่งนี้ timeitเอกสารทำให้เกิดความสับสนมากเกินไป

from datetime import datetime 

start_time = datetime.now() 

# INSERT YOUR CODE 

time_elapsed = datetime.now() - start_time 

print('Time elapsed (hh:mm:ss.ms) {}'.format(time_elapsed))

โปรดทราบว่าไม่มีการจัดรูปแบบใด ๆ เกิดขึ้นที่นี่ฉันเพิ่งเขียนhh:mm:ssลงในผลงานพิมพ์เพื่อให้สามารถตีความได้time_elapsed


ฉันถูกบอกว่า timeit คำนวณเวลาของ CPU, วันที่และเวลาจะคำนึงถึงเวลาของ CPU ที่ใช้หรือไม่ สิ่งเหล่านี้เป็นสิ่งเดียวกันหรือไม่
Sreehari R

3
มีความเสี่ยงที่จะวัดเวลาที่ผ่านไปด้วยวิธีนี้เนื่องจาก datetime.now () สามารถเปลี่ยนแปลงได้ระหว่างการโทรสองครั้งด้วยเหตุผลต่างๆเช่นการซิงค์เวลาเครือข่ายการสลับการประหยัดเวลากลางวันหรือผู้ใช้ twiddling นาฬิกา
user1318499

45

นี่เป็นอีกวิธีในการทำสิ่งนี้:

>> from pytictoc import TicToc
>> t = TicToc() # create TicToc instance
>> t.tic() # Start timer
>> # do something
>> t.toc() # Print elapsed time
Elapsed time is 2.612231 seconds.

เปรียบเทียบกับวิธีดั้งเดิม:

>> from time import time
>> t1 = time()
>> # do something
>> t2 = time()
>> elapsed = t2 - t1
>> print('Elapsed time is %f seconds.' % elapsed)
Elapsed time is 2.612231 seconds.

การติดตั้ง:

pip install pytictoc

อ้างถึงหน้า PyPiสำหรับรายละเอียดเพิ่มเติม


13
เป็นการดีที่จะอธิบายข้อดีของการใช้ไลบรารีนี้เหนือแนวทางอื่น ๆ
hlg

ฟังก์ชั่นที่ซ้อนกันเสียจริง ฉันเปิดปัญหาที่อธิบายว่าปัญหาของรหัสอยู่ที่ไหน แต่ repo ไม่ได้รับการปรับปรุงภายในหนึ่งปีดังนั้นฉันจึงไม่คาดหวังว่าจะมีการเปลี่ยนแปลง
PetarMI

ฉันพบว่าการทำรังค่อนข้างสับสน ถ้าฉันต้องเจอt.tic()โค้ดที่ฝังไว้มันขึ้นอยู่กับฉันว่านักพัฒนาจะเก็บรายชื่อของซีรีส์ที่ฉันควรจะคาดหวัง คุณพบว่าตัวเองติดตั้งรังหรือมี tictocs หลายอันหรือเปล่า?
ScottieB

1
@PetarMI: FYI ttictocฉันเพียงแค่การแก้ไขปัญหาด้วย ค่อนข้างยุ่งฉันมี แต่ตอนนี้ควรจะดี
H. Sánchez

33

นี่คือสิ่งที่ฉันค้นพบหลังจากผ่านคำตอบที่ดีมากมายที่นี่และบทความอื่น ๆ

ขั้นแรกหากคุณกำลังโต้วาทีระหว่างtimeitและtime.timeที่timeitมีสองข้อดี:

  1. timeit เลือกตัวจับเวลาที่ดีที่สุดสำหรับ OS และ Python เวอร์ชั่นของคุณ
  2. 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

ข้อดี:

มีเวอร์ชันที่สำรองไว้หลายรุ่นที่ลอยอยู่รอบ ๆ ดังนั้นฉันต้องการเน้นจุดเด่นบางประการ:

  1. ใช้ตัวจับเวลาจาก timeit แทน time.time ด้วยเหตุผลที่อธิบายไว้ก่อนหน้านี้
  2. คุณสามารถปิดใช้งาน GC ในช่วงเวลาได้หากต้องการ
  3. มัณฑนากรยอมรับฟังก์ชั่นที่มีชื่อหรือพารามิเตอร์ที่ไม่มีชื่อ
  4. ความสามารถในการปิดการใช้งานการพิมพ์ในช่วงเวลาบล็อก (ใช้with utils.MeasureBlockTime() as tแล้วt.elapsed)
  5. ความสามารถในการทำให้ gc เปิดใช้งานสำหรับช่วงเวลาบล็อก

28

การใช้time.timeเพื่อวัดการประมวลผลจะให้เวลาประมวลผลโดยรวมของคำสั่งของคุณรวมถึงเวลาทำงานที่ใช้โดยกระบวนการอื่น ๆ ในคอมพิวเตอร์ของคุณ ถึงเวลาที่ผู้ใช้จะสังเกตเห็น แต่ไม่ดีถ้าคุณต้องการเปรียบเทียบตัวอย่างโค้ด / อัลกอริทึม / ฟังก์ชั่น / ...

ข้อมูลเพิ่มเติมเกี่ยวกับtimeit:

หากคุณต้องการข้อมูลเชิงลึกที่ลึกซึ้งยิ่งขึ้นเกี่ยวกับการทำโปรไฟล์:

อัปเดต : ฉันใช้http://pythonhosted.org/line_profiler/บ่อยครั้งมากในช่วงปีที่แล้วและพบว่ามีประโยชน์มากและแนะนำให้ใช้แทนโมดูลโปรไฟล์ Pythons


19

นี่คือคลาสตัวจับเวลาเล็ก ๆ ที่ส่งคืนสตริง "hh: mm: ss":

class Timer:
  def __init__(self):
    self.start = time.time()

  def restart(self):
    self.start = time.time()

  def get_time_hhmmss(self):
    end = time.time()
    m, s = divmod(end - self.start, 60)
    h, m = divmod(m, 60)
    time_str = "%02d:%02d:%02d" % (h, m, s)
    return time_str

การใช้งาน:

# Start timer
my_timer = Timer()

# ... do something

# Get time string:
time_hhmmss = my_timer.get_time_hhmmss()
print("Time elapsed: %s" % time_hhmmss )

# ... use the timer again
my_timer.restart()

# ... do something

# Get time:
time_hhmmss = my_timer.get_time_hhmmss()

# ... etc

17

โมดูล cProfile ของ python และ pstats ให้การสนับสนุนที่ดีเยี่ยมสำหรับการวัดเวลาที่ผ่านไปในฟังก์ชั่นบางอย่างโดยไม่ต้องเพิ่มโค้ดใด ๆ รอบฟังก์ชั่นที่มีอยู่

ตัวอย่างเช่นถ้าคุณมีสคริปต์ python timeFunctions.py:

import time

def hello():
    print "Hello :)"
    time.sleep(0.1)

def thankyou():
    print "Thank you!"
    time.sleep(0.05)

for idx in range(10):
    hello()

for idx in range(100):
    thankyou()

หากต้องการรัน profiler และสร้างสถิติสำหรับไฟล์คุณสามารถรัน:

python -m cProfile -o timeStats.profile timeFunctions.py

สิ่งนี้กำลังทำอยู่คือการใช้โมดูล cProfile เพื่อทำโปรไฟล์ฟังก์ชั่นทั้งหมดใน timeFunctions.py และรวบรวมสถิติในไฟล์ timeStats.profile โปรดทราบว่าเราไม่จำเป็นต้องเพิ่มรหัสใด ๆ ในโมดูลที่มีอยู่ (timeFunctions.py) และสามารถทำได้กับโมดูลใด ๆ

เมื่อคุณมีไฟล์สถิติคุณสามารถเรียกใช้โมดูล pstats ดังนี้:

python -m pstats timeStats.profile

นี่เป็นการเรียกใช้เบราว์เซอร์สถิติเชิงโต้ตอบซึ่งให้ฟังก์ชันการทำงานที่ดีมากมาย สำหรับกรณีการใช้งานเฉพาะของคุณคุณสามารถตรวจสอบสถิติการทำงานของคุณได้ ในตัวอย่างการตรวจสอบสถิติของทั้งสองฟังก์ชั่นแสดงให้เราทราบดังต่อไปนี้:

Welcome to the profile statistics browser.
timeStats.profile% stats hello
<timestamp>    timeStats.profile

         224 function calls in 6.014 seconds

   Random listing order was used
   List reduced from 6 to 1 due to restriction <'hello'>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       10    0.000    0.000    1.001    0.100 timeFunctions.py:3(hello)

timeStats.profile% stats thankyou
<timestamp>    timeStats.profile

         224 function calls in 6.014 seconds

   Random listing order was used
   List reduced from 6 to 1 due to restriction <'thankyou'>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      100    0.002    0.000    5.012    0.050 timeFunctions.py:7(thankyou)

ตัวอย่างหุ่นจำลองไม่ได้ทำอะไรมาก แต่ให้ความคิดในสิ่งที่สามารถทำได้ ส่วนที่ดีที่สุดเกี่ยวกับวิธีการนี้คือฉันไม่ต้องแก้ไขรหัสที่มีอยู่ของฉันเพื่อรับหมายเลขเหล่านี้และช่วยในการทำโปรไฟล์


ทั้งหมดนี้ใช้ได้ แต่ AFAICT ยังคงวัดเวลา CPU ไม่ใช่เวลานาฬิกาแขวน
ShreevatsaR

1
จริงๆแล้วมีความสับสนอยู่บ้าง ดูเหมือนว่า cProfile จะดูเวลานาฬิกาตามค่าเริ่มต้น ฉันตอบคำถามของคุณแล้ว
ShreevatsaR

FYI: หากคุณได้รับการpython -m pstats timeStats.profile ValueError: bad marshal data (unknown type code)ตรวจสอบเวอร์ชั่นของหลามที่คุณใช้งานอยู่ ผมได้รับนี้เมื่อฉันวิ่งและpython3 -m cProfile... python -m pstatsความผิดพลาดของฉัน don't forget consistencyแต่มีฉันเป็นครั้งที่สองดังนั้นผมอยากจะแบ่งปัน =)
JayRizzo

17

นี่เป็นอีกหนึ่งผู้จัดการบริบทสำหรับรหัสเวลา -

การใช้งาน:

from benchmark import benchmark

with benchmark("Test 1+1"):
    1+1
=>
Test 1+1 : 1.41e-06 seconds

หรือถ้าคุณต้องการค่าเวลา

with benchmark("Test 1+1") as b:
    1+1
print(b.time)
=>
Test 1+1 : 7.05e-07 seconds
7.05233786763e-07

benchmark.py :

from timeit import default_timer as timer

class benchmark(object):

    def __init__(self, msg, fmt="%0.3g"):
        self.msg = msg
        self.fmt = fmt

    def __enter__(self):
        self.start = timer()
        return self

    def __exit__(self, *args):
        t = timer() - self.start
        print(("%s : " + self.fmt + " seconds") % (self.msg, t))
        self.time = t

ดัดแปลงมาจากhttp://dabeaz.blogspot.fr/2010/02/context-manager-for-timing-benchmarks.html


17

ใช้โมดูลตัวสร้างโปรไฟล์ มันให้รายละเอียดที่ละเอียดมาก

import profile
profile.run('main()')

มันแสดงผลเหมือน:

          5 function calls in 0.047 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 :0(exec)
        1    0.047    0.047    0.047    0.047 :0(setprofile)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        0    0.000             0.000          profile:0(profiler)
        1    0.000    0.000    0.047    0.047 profile:0(main())
        1    0.000    0.000    0.000    0.000 two_sum.py:2(twoSum)

ฉันพบว่ามีข้อมูลมาก


1
คือmain()อะไร จะมีประโยชน์มากขึ้นถ้าคุณสามารถให้ตัวอย่างโค้ดแบบง่าย
not2qubit

15

ฉันชอบมันง่าย (python 3):

from timeit import timeit

timeit(lambda: print("hello"))

เอาต์พุตเป็นไมโครวินาทีสำหรับการประมวลผลครั้งเดียว:

2.430883963010274

คำอธิบาย : timeit รันฟังก์ชั่นที่ไม่ระบุชื่อ1 ล้านคนครั้งโดยค่าเริ่มต้นและผลที่จะได้รับในไม่กี่วินาที ดังนั้นผลลัพธ์สำหรับการประมวลผลเดี่ยว 1รายการมีจำนวนเท่ากัน แต่โดยเฉลี่ยเป็นไมโครวินาที


สำหรับการทำงานที่ช้าเพิ่มจำนวนการวนซ้ำที่น้อยลงหรือคุณอาจรอตลอดไป:

import time

timeit(lambda: time.sleep(1.5), number=1)

เอาต์พุตอยู่เสมอในไม่กี่วินาทีสำหรับจำนวนการวนซ้ำทั้งหมด:

1.5015795179999714

14

(ด้วย Ipython เท่านั้น) คุณสามารถใช้% timeitเพื่อวัดเวลาประมวลผลเฉลี่ย:

def foo():
    print "hello"

แล้ว:

%timeit foo()

ผลลัพธ์ที่ได้คือ:

10000 loops, best of 3: 27 µs per loop

4
มันมีค่าควรพูดถึงมันเป็นไปได้ที่จะส่งผ่านธงไปยัง% timeit ตัวอย่างเช่น -n ระบุจำนวนครั้งที่ควรจะทำซ้ำรหัส
แข่ง



9

เป็นคำตอบที่ยอดเยี่ยมในภายหลัง แต่บางทีมันอาจมีจุดประสงค์สำหรับบางคน นี่เป็นวิธีที่จะทำซึ่งฉันคิดว่าสะอาดสุด ๆ

import time

def timed(fun, *args):
    s = time.time()
    r = fun(*args)
    print('{} execution took {} seconds.'.format(fun.__name__, time.time()-s))
    return(r)

timed(print, "Hello")

โปรดทราบว่า "print" เป็นฟังก์ชันใน Python 3 ไม่ใช่ Python 2.7 อย่างไรก็ตามมันใช้งานได้กับฟังก์ชั่นอื่น ๆ ไชโย!


ฉันจะพิมพ์เวลาน้อยมากได้อย่างไร ฉันได้รับ 0.0sec เสมอ
Rowland Mtetezi

คุณสามารถทำให้สิ่งนี้กลายเป็นมัณฑนากรได้ มันดูดีขึ้นสำหรับฉัน
Daniel Moskovich

8

คุณสามารถใช้ timeit

นี่คือตัวอย่างเกี่ยวกับวิธีทดสอบ naive_func ที่รับพารามิเตอร์โดยใช้ Python REPL:

>>> import timeit                                                                                         

>>> def naive_func(x):                                                                                    
...     a = 0                                                                                             
...     for i in range(a):                                                                                
...         a += i                                                                                        
...     return a                                                                                          

>>> def wrapper(func, *args, **kwargs):                                                                   
...     def wrapper():                                                                                    
...         return func(*args, **kwargs)                                                                  
...     return wrapper                                                                                    

>>> wrapped = wrapper(naive_func, 1_000)                                                                  

>>> timeit.timeit(wrapped, number=1_000_000)                                                              
0.4458435332577161  

คุณไม่จำเป็นต้องใช้ฟังก์ชั่น wrapper ถ้าฟังก์ชั่นไม่มีพารามิเตอร์ใด ๆ


1
lambdaจะรวบรัดเพิ่มเติมได้ที่:print(timeit.timeit(lambda: naive_func(1_000), number=1_000_000))
Ciro Santilli冠状病毒审查六四事件法轮功

7

เรายังสามารถแปลงเวลาเป็นเวลาที่มนุษย์อ่านได้

import time, datetime

start = time.clock()

def num_multi1(max):
    result = 0
    for num in range(0, 1000):
        if (num % 3 == 0 or num % 5 == 0):
            result += num

    print "Sum is %d " % result

num_multi1(1000)

end = time.clock()
value = end - start
timestamp = datetime.datetime.fromtimestamp(value)
print timestamp.strftime('%Y-%m-%d %H:%M:%S')

6

ฉันสร้างห้องสมุดสำหรับสิ่งนี้ถ้าคุณต้องการวัดฟังก์ชั่นที่คุณสามารถทำได้เช่นนี้


from pythonbenchmark import compare, measure
import time

a,b,c,d,e = 10,10,10,10,10
something = [a,b,c,d,e]

@measure
def myFunction(something):
    time.sleep(0.4)

@measure
def myOptimizedFunction(something):
    time.sleep(0.2)

myFunction(input)
myOptimizedFunction(input)

https://github.com/Karlheinzniebuhr/pythonbenchmark


6

ในการรับข้อมูลเชิงลึกเกี่ยวกับการเรียกใช้ฟังก์ชั่นซ้ำ ๆ ให้ทำ:

%load_ext snakeviz
%%snakeviz

มันใช้โค้ด 2 บรรทัดในสมุดบันทึก Jupyterและสร้างไดอะแกรมแบบโต้ตอบที่ดี ตัวอย่างเช่น:

ป้อนคำอธิบายรูปภาพที่นี่

นี่คือรหัส อีกครั้งบรรทัดที่ 2 ที่ขึ้นต้นด้วย%เป็นบรรทัดเพิ่มเติมของรหัสเท่านั้นที่จำเป็นในการใช้ snakeviz:

# !pip install snakeviz
%load_ext snakeviz
import glob
import hashlib

%%snakeviz

files = glob.glob('*.txt')
def print_files_hashed(files):
    for file in files:
        with open(file) as f:
            print(hashlib.md5(f.read().encode('utf-8')).hexdigest())
print_files_hashed(files)

ดูเหมือนว่าเป็นไปได้ที่จะเรียกใช้ snakeviz นอกโน้ตบุ๊ก ข้อมูลเพิ่มเติมเกี่ยวกับเว็บไซต์ snakeviz


2
import time

def getElapsedTime(startTime, units):
    elapsedInSeconds = time.time() - startTime
    if units == 'sec':
        return elapsedInSeconds
    if units == 'min':
        return elapsedInSeconds/60
    if units == 'hour':
        return elapsedInSeconds/(60*60)

2

วิธีการตามคลาสที่ไม่เหมือนใครนี้นำเสนอการพิมพ์สตริงการปัดเศษที่ปรับแต่งได้และการเข้าถึงเวลาที่ผ่านไปอย่างสะดวกสบายเป็นสตริงหรือทุ่น มันได้รับการพัฒนาด้วย Python 3.7

import datetime
import timeit


class Timer:
    """Measure time used."""
    # Ref: https://stackoverflow.com/a/57931660/

    def __init__(self, round_ndigits: int = 0):
        self._round_ndigits = round_ndigits
        self._start_time = timeit.default_timer()

    def __call__(self) -> float:
        return timeit.default_timer() - self._start_time

    def __str__(self) -> str:
        return str(datetime.timedelta(seconds=round(self(), self._round_ndigits)))

การใช้งาน:

# Setup timer
>>> timer = Timer()

# Access as a string
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:03.
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:04.

# Access as a float
>>> timer()
6.841332235
>>> timer()
7.970274425

1

วัดเวลาดำเนินการของตัวอย่างโค้ดขนาดเล็ก

หน่วยเวลา : วัดในหน่วยวินาทีเป็นแบบลอย

import timeit
t = timeit.Timer('li = list(map(lambda x:x*2,[1,2,3,4,5]))')
t.timeit()
t.repeat()
>[1.2934070999999676, 1.3335035000000062, 1.422568500000125]

ซ้ำ () วิธีการที่สะดวกในการโทร timeit () หลายครั้งและกลับรายการผลลัพธ์

repeat(repeat=3

ด้วยรายการนี้เราสามารถใช้เวลาทั้งหมด

โดยค่าเริ่มต้น timeit () จะปิดการเก็บรวบรวมขยะชั่วคราวระหว่างเวลา time.Timer () แก้ปัญหานี้

ข้อดี:

timeit.Timer () ทำให้การจับเวลาอิสระเปรียบได้มากขึ้น gc อาจเป็นองค์ประกอบสำคัญของประสิทธิภาพการทำงานของฟังก์ชั่นที่วัด หากเป็นเช่นนั้น gc (ตัวรวบรวมขยะ) สามารถเปิดใช้งานอีกครั้งเป็นคำสั่งแรกในสตริงการตั้งค่า ตัวอย่างเช่น:

timeit.Timer('li = list(map(lambda x:x*2,[1,2,3,4,5]))',setup='gc.enable()')

เอกสาร Pythonแหล่งที่มา!


1

หากคุณต้องการให้เวลาทำงานได้อย่างสะดวกคุณสามารถใช้มัณฑนากรง่ายๆ

def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        original_return_val = func(*args, **kwargs)
        end = time.time()
        print("time elapsed in ", func.__name__, ": ", end - start, sep='')
        return original_return_val

    return wrapper

คุณสามารถใช้มันในฟังก์ชั่นที่คุณต้องการเวลาเช่นนี้:

@timing_decorator
def function_to_time():
    time.sleep(1)

จากนั้นทุกครั้งที่คุณโทรfunction_to_timeมันจะพิมพ์ระยะเวลาที่ใช้และชื่อของฟังก์ชันที่กำหนดเวลาไว้


1

ขึ้นอยู่กับการแก้ปัญหา contextmanager ที่ได้รับจากhttps://stackoverflow.com/a/30024601/5095636ซึ่งเป็นเวอร์ชั่นฟรีของแลมบ์ดาตามที่ flake8 แจ้งเตือนการใช้แลมบ์ดาตามE731 :

from contextlib import contextmanager
from timeit import default_timer

@contextmanager
def elapsed_timer():
    start_time = default_timer()

    class _Timer():
      start = start_time
      end = default_timer()
      duration = end - start

    yield _Timer

    end_time = default_timer()
    _Timer.end = end_time
    _Timer.duration = end_time - start_time

ทดสอบ:

from time import sleep

with elapsed_timer() as t:
    print("start:", t.start)
    sleep(1)
    print("end:", t.end)

t.start
t.end
t.duration

1

นี่คือมัณฑนากรตกแต่งสวย ๆ ที่มีเอกสารและพิมพ์อย่างดีที่ฉันใช้เป็นยูทิลิตี้ทั่วไป:

from functools import wraps
from time import perf_counter
from typing import Any, Callable, Optional, TypeVar, cast

F = TypeVar("F", bound=Callable[..., Any])


def timer(prefix: Optional[str] = None, precision: int = 6) -> Callable[[F], F]:
    """Use as a decorator to time the execution of any function.

    Args:
        prefix: String to print before the time taken.
            Default is the name of the function.
        precision: How many decimals to include in the seconds value.

    Examples:
        >>> @timer()
        ... def foo(x):
        ...     return x
        >>> foo(123)
        foo: 0.000...s
        123
        >>> @timer("Time taken: ", 2)
        ... def foo(x):
        ...     return x
        >>> foo(123)
        Time taken: 0.00s
        123

    """
    def decorator(func: F) -> F:
        @wraps(func)
        def wrapper(*args: Any, **kwargs: Any) -> Any:
            nonlocal prefix
            prefix = prefix if prefix is not None else f"{func.__name__}: "
            start = perf_counter()
            result = func(*args, **kwargs)
            end = perf_counter()
            print(f"{prefix}{end - start:.{precision}f}s")
            return result
        return cast(F, wrapper)
    return decorator

ตัวอย่างการใช้งาน:

from timer import timer


@timer(precision=9)
def takes_long(x: int) -> bool:
    return x in (i for i in range(x + 1))


print(takes_long(10**8))

เอาท์พุท:

takes_long: 4.942629056s
True

สามารถตรวจสอบคำสอนด้วย:

$ python3 -m doctest --verbose -o=ELLIPSIS timer.py

และคำใบ้ประเภทด้วย:

$ mypy timer.py

1
นี่สุดยอดมากขอบคุณสำหรับการแบ่งปัน ฉันยังไม่พบไลบรารีการพิมพ์หรือคำหลักที่ไม่เกี่ยวกับท้องถิ่น - สนุกกับการค้นหาสิ่งใหม่ ๆ เพื่อเรียนรู้ Callable[[AnyF], AnyF]ฉันมีปัญหาในการตัดหัวของฉันรอบนี้: มันหมายความว่าอะไร?
แดนนี่

1
@Danny ด้านบนฉันได้กำหนดประเภทนามแฝงที่AnyFจะหมายถึงCallable[..., Any]จึงAnyFเป็นฟังก์ชั่นที่สามารถใช้จำนวนอาร์กิวเมนต์ประเภทใด ๆ และคืนสิ่งใด ๆ ดังนั้นจะขยายตัวออกไปCallable[[AnyF], AnyF] Callable[[Callable[..., Any]], Callable[..., Any]]นี่คือประเภทของค่าตอบแทนของอาคาชนิดเต็มรูปแบบของtimer decoratorมันเป็นฟังก์ชั่นที่รับฟังก์ชั่นทุกชนิดเป็นอาร์กิวเมนต์เท่านั้นและส่งคืนฟังก์ชันประเภทใด ๆ
ruohola

1
ขอบคุณสำหรับคำอธิบาย! ฉันยังคงพยายามห่อหัวของฉันให้เต็มไปทั่วภายในของนักตกแต่ง สิ่งนี้ช่วยได้มาก!
แดนนี่

0

time.time()วิธีเดียวที่ฉันสามารถคิดจะใช้

import time
start = time.time()
sleep(5) #just to give it some delay to show it working
finish = time.time()
elapsed = finish - start
print(elapsed)

หวังว่าจะช่วยได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.