Bagaimana mengukur waktu yang telah berlalu dalam Python?


1211

Yang saya inginkan adalah mulai menghitung waktu di suatu tempat dalam kode saya dan kemudian mendapatkan waktu yang berlalu, untuk mengukur waktu yang diperlukan untuk menjalankan beberapa fungsi. Saya pikir saya menggunakan modul timeit yang salah, tetapi dokumen hanya membingungkan bagi saya.

import timeit

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

Jawaban:


1456

Jika Anda hanya ingin mengukur waktu jam dinding yang telah berlalu antara dua titik, Anda dapat menggunakan time.time():

import time

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

Ini memberikan waktu eksekusi dalam hitungan detik.

Opsi lain karena 3.3 mungkin untuk menggunakan perf_counteratau process_time, tergantung pada kebutuhan Anda. Sebelum 3.3 disarankan untuk digunakan time.clock(terima kasih Amber ). Namun, saat ini sudah usang:

Pada Unix, kembalikan waktu prosesor saat ini sebagai angka titik mengambang yang dinyatakan dalam detik. Ketepatannya, dan pada kenyataannya, definisi sesungguhnya dari "waktu prosesor", tergantung pada fungsi C dari nama yang sama.

Pada Windows, fungsi ini mengembalikan detik jam dinding yang berlalu sejak panggilan pertama ke fungsi ini, sebagai angka titik mengambang, berdasarkan pada fungsi Win32 QueryPerformanceCounter(). Resolusi biasanya lebih baik dari satu mikrodetik.

Sudah tidak digunakan lagi sejak versi 3.3 : Perilaku fungsi ini tergantung pada platform: gunakan perf_counter()atau process_time()sebaliknya , tergantung pada kebutuhan Anda, untuk memiliki perilaku yang terdefinisi dengan baik.


17
dan untuk mikrodetik, gunakan datetime.time ()
Inca

110
(Untuk pengukuran kinerja, time.clock()sebenarnya lebih disukai, karena tidak dapat diganggu jika jam sistem menjadi kacau, tetapi .time()sebagian besar mencapai tujuan yang sama.)
Amber

4
Saya pikir python -mtimeit jauh lebih baik karena berjalan lebih banyak dan ini dibangun sebagai cara asli untuk mengukur waktu dalam python
Visgean Skeloru

4
Apakah ada cara yang bagus untuk mengkonversi waktu execturion yang dihasilkan dalam hitungan detik menjadi sesuatu seperti HH: MM :: SS?
Danijel

12
@Danijel: print(timedelta(seconds=execution_time)). Padahal itu pertanyaan tersendiri.
jfs

689

Gunakan timeit.default_timersebagai ganti timeit.timeit. Yang pertama menyediakan jam terbaik yang tersedia di platform dan versi Python Anda secara otomatis:

from timeit import default_timer as timer

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

timeit.default_timer ditugaskan ke time.time () atau time.clock () tergantung pada OS Pada Python 3.3+ default_timer adalah time.perf_counter () di semua platform. Lihat Python - time.clock () vs time.time () - akurasi?

Lihat juga:


29
Jawaban luar biasa - menggunakan timeit akan menghasilkan hasil yang jauh lebih akurat karena secara otomatis akan menghitung hal-hal seperti pengumpulan sampah dan perbedaan OS
lkgarrison

1
Ini memberi waktu dalam ms atau detik?
Katie

3
@KhushbooTiwari dalam hitungan detik.
jfs

5
Saya pikir catatan ini dari dokumentasi resmi perlu ditambahkandefault_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: Pengukuran kinerja sangat rumit dengan cara yang halus (mudah untuk menyesatkan diri sendiri). Ada banyak komentar lain yang mungkin relevan di sini. Ikuti tautan dalam jawabannya. Anda mungkin juga tertarik pada perfmodul (tidak ada pada saat jawaban) yang menyediakan antarmuka yang sama tetapi kadang-kadang membuat berbeda dari timeitkeputusan modul tentang bagaimana mengukur kinerja waktu.
jfs

129

Hanya Python 3:

Karena time.clock () sudah tidak digunakan lagi di Python 3.3 , Anda akan ingin menggunakan time.perf_counter()untuk pengaturan waktu seluruh sistem, atau time.process_time()untuk pengaturan waktu seluruh proses, persis seperti yang Anda gunakan time.clock():

import time

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

Fungsi baru process_timetidak akan mencakup waktu yang berlalu selama tidur.


28
Gunakantimeit.default_timer sebagai ganti time.perf_counter. Yang pertama akan memilih timer yang sesuai untuk mengukur kinerja waktu yang disetel untuk platform Anda dan versi Python. process_time()tidak tidak termasuk waktu saat tidur dan oleh karena itu tidak yang sesuai untuk mengukur waktu berlalu.
jfs

2
Saya menggunakan implementasi yang disarankan oleh Pierre, apakah nilai diberikan dalam hitungan detik?
ugotchi

Jawaban ini tampaknya di luar topik (yah, pertanyaannya tidak terlalu spesifik). Ada dua pengukuran "waktu": waktu jam dinding antara dua titik, dari konsumsi CPU dari proses.
Franklin Piat

87

Diberi fungsi yang Anda inginkan waktunya,

test.py:

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

cara termudah untuk digunakan timeitadalah dengan memanggilnya dari baris perintah:

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

Jangan mencoba menggunakan time.timeatau time.clock(secara naif) untuk membandingkan kecepatan fungsi. Mereka dapat memberikan hasil yang menyesatkan .

PS. Jangan meletakkan pernyataan cetak dalam fungsi yang Anda inginkan; jika tidak, waktu yang diukur akan tergantung pada kecepatan terminal .


65

Sangat menyenangkan untuk melakukan ini dengan manajer konteks yang secara otomatis mengingat waktu mulai pada saat masuk ke withblok, lalu membekukan waktu akhir pada blok keluar. Dengan sedikit tipuan, Anda bahkan bisa mendapatkan penghitungan waktu yang berjalan di dalam blok dari fungsi konteks-manajer yang sama.

Pustaka inti tidak memiliki ini (tapi mungkin seharusnya). Setelah berada di tempat, Anda dapat melakukan hal-hal seperti:

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() )

Berikut kode manajer konteks yang cukup untuk melakukan trik:

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

Dan beberapa kode demo yang dapat dijalankan:

import time

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

Perhatikan bahwa dengan desain fungsi ini, nilai kembali elapsed()beku pada blok keluar, dan panggilan lebih lanjut mengembalikan durasi yang sama (sekitar 6 detik dalam contoh mainan ini).


2
Contoh manajer konteks lain: dabeaz.blogspot.fr/2010/02/…
Jérôme

1
@ Jérôme contoh yang bagus - Saya mengadaptasinya sebagai jawaban lain - stackoverflow.com/a/41408510/243392
Brian Burns

62

Mengukur waktu dalam detik:

from timeit import default_timer as timer
from datetime import timedelta

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

Keluaran :

0:00:01.946339

1
Ini adalah jawaban paling ringkas dengan output terbersih.
Dave Liu

56

Saya lebih memilih ini. timeitdoc terlalu membingungkan.

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))

Perhatikan, bahwa tidak ada pemformatan yang terjadi di sini, saya hanya menulis hh:mm:sske dalam cetakan sehingga orang dapat menafsirkantime_elapsed


Saya diberitahu bahwa timeit menghitung waktu CPU, apakah datetime juga memperhitungkan waktu CPU yang digunakan? Apakah ini hal yang sama?
Sreehari R

3
Berisiko untuk mengukur waktu yang berlalu dengan cara ini karena datetime.now () dapat mengubah antara dua panggilan dengan alasan seperti sinkronisasi waktu jaringan, peralihan penghematan siang hari atau pengguna memutar-mutar jam.
user1318499

45

Berikut cara lain untuk melakukan ini:

>> 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.

Membandingkan dengan cara tradisional:

>> 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.

Instalasi:

pip install pytictoc

Lihat halaman PyPi untuk lebih jelasnya.


13
Akan lebih baik untuk menjelaskan keuntungan menggunakan perpustakaan ini daripada pendekatan lain.
hlg

Fungsi bersarang sebenarnya rusak. Saya membuka masalah yang menjelaskan di mana masalah dalam kode tetapi repo belum dikelola dalam setahun jadi saya tidak akan mengharapkan perubahan.
PetarMI

Saya menemukan sarang sedikit membingungkan. Jika saya menemukan t.tic()terkubur dalam kode, terserah saya pengembang untuk menyimpan daftar mental di mana dalam seri saya harus mengharapkan ini. Apakah Anda menemukan diri Anda membuat sarang atau hanya beberapa tictocs?
ScottieB

1
@PetarMI: FYI, saya baru saja memperbaiki masalah ini ttictoc. Cukup berantakan yang saya alami, tetapi itu harusnya baik sekarang.
H. Sánchez

33

Berikut ini adalah temuan saya setelah melalui banyak jawaban yang baik di sini dan juga beberapa artikel lainnya.

Pertama, jika Anda berdebat antara timeitdan time.time, timeitada dua keuntungan:

  1. timeit pilih timer terbaik yang tersedia di OS dan versi Python Anda.
  2. timeit menonaktifkan pengumpulan sampah, namun, ini bukan sesuatu yang Anda mungkin atau mungkin tidak inginkan.

Sekarang masalahnya adalah timeittidak sesederhana itu untuk digunakan karena membutuhkan pengaturan dan hal-hal menjadi jelek ketika Anda memiliki banyak impor. Idealnya, Anda hanya ingin dekorator atau menggunakan withblok dan mengukur waktu. Sayangnya, tidak ada built-in yang tersedia untuk ini sehingga Anda memiliki dua opsi:

Opsi 1: Gunakan perpustakaan timebudget

The timebudget adalah perpustakaan serbaguna dan sangat sederhana yang dapat Anda gunakan hanya dalam satu baris kode setelah pip install.

@timebudget  # Record how long this function takes
def my_method():
    # my code

Opsi 2: Gunakan modul kode secara langsung

Saya buat di bawah ini sedikit modul utilitas.

# 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

Sekarang Anda dapat mengatur waktu fungsi apa pun hanya dengan meletakkan dekorator di depannya:

import utils

@utils.MeasureTime
def MyBigFunc():
    #do something time consuming
    for i in range(10000):
        print(i)

Jika Anda ingin waktu bagian kode maka cukup taruh di dalam withblok:

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

Keuntungan:

Ada beberapa versi setengah didukung yang beredar jadi saya ingin menunjukkan beberapa highlight:

  1. Gunakan timer dari timeit bukan time.time karena alasan yang dijelaskan sebelumnya.
  2. Anda dapat menonaktifkan GC selama penghitungan waktu jika diinginkan.
  3. Dekorator menerima fungsi dengan param bernama atau tidak disebutkan namanya.
  4. Kemampuan untuk menonaktifkan pencetakan dalam waktu blok (gunakan with utils.MeasureBlockTime() as tdan kemudian t.elapsed).
  5. Kemampuan untuk menjaga gc diaktifkan untuk timing blok.

28

Menggunakan time.timeuntuk mengukur eksekusi memberi Anda waktu eksekusi keseluruhan dari perintah Anda termasuk waktu yang dihabiskan untuk proses lain di komputer Anda. Ini adalah waktu pemberitahuan pengguna, tetapi tidak baik jika Anda ingin membandingkan cuplikan kode / algoritme / fungsi / ...

Informasi lebih lanjut tentang timeit:

Jika Anda ingin wawasan yang lebih dalam tentang pembuatan profil:

Pembaruan : Saya banyak menggunakan http://pythonhosted.org/line_profiler/ selama setahun terakhir dan merasa sangat membantu dan merekomendasikan untuk menggunakannya sebagai ganti modul profil Python.


19

Ini adalah kelas pengatur waktu kecil yang mengembalikan string "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

Pemakaian:

# 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

Modul python cProfile dan pstats menawarkan dukungan besar untuk mengukur waktu yang berlalu dalam fungsi tertentu tanpa harus menambahkan kode apa pun di sekitar fungsi yang ada.

Misalnya jika Anda memiliki skrip 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()

Untuk menjalankan profiler dan menghasilkan statistik untuk file, Anda dapat menjalankan:

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

Apa yang dilakukan adalah menggunakan modul cProfile untuk membuat profil semua fungsi di timeFunctions.py dan mengumpulkan statistik dalam file timeStats.profile. Perhatikan bahwa kami tidak perlu menambahkan kode apa pun ke modul yang ada (timeFunctions.py) dan ini dapat dilakukan dengan modul apa pun.

Setelah Anda memiliki file statistik, Anda dapat menjalankan modul pstats sebagai berikut:

python -m pstats timeStats.profile

Ini menjalankan browser statistik interaktif yang memberi Anda banyak fungsi yang bagus. Untuk kasus penggunaan khusus Anda, Anda dapat memeriksa statistik fungsi Anda. Dalam contoh kami memeriksa statistik untuk kedua fungsi menunjukkan kepada kami hal berikut:

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)

Contoh boneka tidak banyak membantu tetapi memberi Anda gambaran tentang apa yang bisa dilakukan. Bagian terbaik tentang pendekatan ini adalah saya tidak perlu mengedit kode saya yang ada untuk mendapatkan angka-angka ini dan jelas membantu membuat profil.


Semua ini baik-baik saja, tetapi AFAICT ini masih mengukur waktu CPU, bukan waktu jam dinding.
ShreevatsaR

1
Sebenarnya ada beberapa kebingungan; tampaknya cProfile memang melihat waktu jam dinding secara default. Saya telah mengangkat jawaban Anda.
ShreevatsaR

FYI: Jika Anda python -m pstats timeStats.profile ValueError: bad marshal data (unknown type code)memeriksa versi python Anda sedang berjalan. Saya mendapatkan ini ketika saya berlari python3 -m cProfile...dan python -m pstats. Kesalahan saya tetapi membuat saya sejenak, jadi, saya ingin berbagi don't forget consistency. =)
JayRizzo

17

Berikut manajer konteks lain untuk kode waktu -

Pemakaian:

from benchmark import benchmark

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

atau, jika Anda membutuhkan nilai waktu

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

Diadaptasi dari http://dabeaz.blogspot.fr/2010/02/context-manager-for-timing-benchmarks.html


17

Gunakan modul profiler. Ini memberikan profil yang sangat rinci.

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

ini menghasilkan sesuatu seperti:

          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)

Saya merasa sangat informatif.


1
Apa main()? Akan lebih bermanfaat jika Anda bisa memberikan contoh kode sederhana.
not2qubit

15

Saya suka itu sederhana (python 3):

from timeit import timeit

timeit(lambda: print("hello"))

Output adalah mikrodetik untuk satu eksekusi:

2.430883963010274

Penjelasan : timeit menjalankan fungsi anonim 1 juta kali secara default dan hasilnya diberikan dalam hitungan detik . Oleh karena itu hasil untuk 1 eksekusi tunggal adalah jumlah yang sama tetapi dalam mikrodetik rata-rata.


Untuk operasi yang lambat, tambahkan jumlah iterasi yang lebih rendah atau Anda bisa menunggu selamanya:

import time

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

Output selalu dalam detik untuk jumlah total iterasi:

1.5015795179999714

14

(Hanya dengan Ipython) Anda dapat menggunakan % timeit untuk mengukur waktu pemrosesan rata-rata:

def foo():
    print "hello"

lalu:

%timeit foo()

hasilnya adalah sesuatu seperti:

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

4
Perlu disebutkan bahwa dimungkinkan untuk meneruskan flag ke% timeit, misalnya -n menentukan berapa kali kode harus diulang.
raacer

11

Satu lagi cara untuk menggunakan timeit :

from timeit import timeit

def func():
    return 1 + 1

time = timeit(func, number=1)
print(time)

10

di python3:

from time import sleep, perf_counter as pc
t0 = pc()
sleep(1)
print(pc()-t0)

elegan dan pendek.


apa ini? MS?
KIC

9

Agak respons yang sangat baik, tetapi mungkin itu bermanfaat bagi seseorang. Ini adalah cara untuk melakukannya yang menurut saya super bersih.

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")

Perlu diingat bahwa "cetak" adalah fungsi dalam Python 3 dan bukan Python 2.7. Namun, ini berfungsi dengan fungsi lain. Bersulang!


Bagaimana saya bisa mencetak waktu yang sangat kecil? Saya agak selalu mendapatkan 0,0dtk
Rowland Mtetezi

Anda dapat mengubahnya menjadi dekorator; ini terlihat lebih baik bagi saya.
Daniel Moskovich

8

Anda dapat menggunakan timeit.

Berikut adalah contoh tentang cara menguji naive_func yang mengambil parameter menggunakan 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  

Anda tidak perlu fungsi pembungkus jika fungsi tidak memiliki parameter apa pun.


1
A lambdaakan lebih ringkas:print(timeit.timeit(lambda: naive_func(1_000), number=1_000_000))
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

7

Kita juga dapat mengubah waktu menjadi waktu yang dapat dibaca manusia.

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

Saya membuat perpustakaan untuk ini, jika Anda ingin mengukur suatu fungsi Anda bisa melakukannya seperti ini


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

Untuk mendapatkan wawasan tentang setiap panggilan fungsi secara rekursif, lakukan:

%load_ext snakeviz
%%snakeviz

Hanya membutuhkan 2 baris kode di notebook Jupyter , dan menghasilkan diagram interaktif yang bagus. Sebagai contoh:

masukkan deskripsi gambar di sini

Ini kodenya. Sekali lagi, 2 baris yang dimulai dengan %adalah satu-satunya baris kode tambahan yang diperlukan untuk menggunakan 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)

Tampaknya juga memungkinkan untuk menjalankan snakeviz di luar notebook. Info lebih lanjut di situs web 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

Pendekatan berbasis kelas yang unik ini menawarkan representasi string yang dapat dicetak, pembulatan yang dapat disesuaikan, dan akses mudah ke waktu yang telah berlalu sebagai string atau float. Ini dikembangkan dengan 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)))

Pemakaian:

# 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

Mengukur waktu eksekusi snipet kode kecil.

Unit waktu : diukur dalam detik sebagai pelampung

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]

Metode repeat () adalah kenyamanan untuk memanggil timeit () beberapa kali dan mengembalikan daftar hasil.

repeat(repeat=3

Dengan daftar ini kita dapat mengambil rata-rata setiap saat.

Secara default, timeit () sementara mematikan pengumpulan sampah selama penghitungan waktu. time.Timer () memecahkan masalah ini.

Pro:

timeit.Timer () menjadikan timing independen lebih dapat dibandingkan. Gc dapat menjadi komponen penting dari kinerja fungsi yang diukur. Jika demikian, gc (pengumpul sampah) dapat diaktifkan kembali sebagai pernyataan pertama dalam string pengaturan. Sebagai contoh:

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

Sumber Python Documents !


1

Jika Anda ingin mengatur waktu dengan nyaman, Anda dapat menggunakan dekorator sederhana:

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

Anda dapat menggunakannya pada fungsi yang Anda ingin waktu seperti ini:

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

Kemudian setiap kali Anda menelepon function_to_time, itu akan mencetak berapa lama dan nama fungsi yang diatur waktunya.


1

berdasarkan pada solusi contextmanager yang diberikan oleh https://stackoverflow.com/a/30024601/5095636 , di bawah ini adalah versi gratis lambda, sebagaimana flake8 memperingatkan tentang penggunaan lambda sesuai 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

uji:

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

Cara termudah untuk menghitung durasi operasi:

import time

start_time = time.time()
print(time.ctime())

<operations, programs>

print('minutes: ',(time.time() - start_time)/60)

1

Berikut adalah dekorator petunjuk yang didokumentasikan dengan cukup baik dan sepenuhnya saya gunakan sebagai utilitas umum:

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

Contoh penggunaan:

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))

Keluaran:

takes_long: 4.942629056s
True

Dokumen dapat diperiksa dengan:

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

Dan tipnya mengisyaratkan:

$ mypy timer.py

1
Ini sangat keren, terima kasih sudah berbagi. Saya belum menemukan perpustakaan pengetikan atau kata kunci nonlokal - asyik mencari hal baru untuk dipelajari. Saya mengalami kesulitan membungkus kepala saya sekitar ini: Callable[[AnyF], AnyF]. Apa artinya?
Danny

1
@Danny Di atas saya telah mendefinisikan jenis alias AnyFberarti Callable[..., Any], jadi AnyFadalah fungsi yang dapat mengambil jumlah argumen jenis apa pun dan mengembalikan apa pun. Jadi Callable[[AnyF], AnyF]akan berkembang menjadi Callable[[Callable[..., Any]], Callable[..., Any]]. Ini adalah jenis nilai pengembalian timeralias tipe penuh decorator. Ini adalah fungsi yang mengambil segala jenis fungsi sebagai satu-satunya argumen dan mengembalikan segala jenis fungsi.
ruohola

1
Terima kasih untuk penjelasannya! Saya masih mencoba untuk membungkus kepala saya sepenuhnya dengan bagian dalam dekorator. Ini sangat membantu!
Danny
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.