मैं पायथन समयसीमा के साथ प्रदर्शन के परीक्षण के लिए एक कोड खंड कैसे बना सकता हूं?


162

मेरे पास एक पाइथन स्क्रिप्ट है, जो ठीक उसी तरह काम करती है, जैसी मुझे होनी चाहिए, लेकिन मुझे निष्पादन का समय लिखना होगा। मैंने गुगली की है कि मुझे इसका उपयोग करना चाहिए timeitलेकिन मैं इसे काम करने के लिए नहीं देख सकता।

मेरी पायथन लिपि इस तरह दिखती है:

import sys
import getopt
import timeit
import random
import os
import re
import ibm_db
import time
from string import maketrans
myfile = open("results_update.txt", "a")

for r in range(100):
    rannumber = random.randint(0, 100)

    update = "update TABLE set val = %i where MyCount >= '2010' and MyCount < '2012' and number = '250'" % rannumber
    #print rannumber

    conn = ibm_db.pconnect("dsn=myDB","usrname","secretPWD")

for r in range(5):
    print "Run %s\n" % r        
    ibm_db.execute(query_stmt)
 query_stmt = ibm_db.prepare(conn, update)

myfile.close()
ibm_db.close(conn)

क्वेरी को निष्पादित करने और फ़ाइल में लिखने के लिए मुझे जो समय चाहिए वह है results_update.txt। इसका उद्देश्य विभिन्न डेटाबेस और ट्यूनिंग तंत्रों के साथ मेरे डेटाबेस के लिए एक अपडेट स्टेटमेंट का परीक्षण करना है।


क्या आपका प्रश्न विशिष्ट था timeit? मुझे नहीं लगता। उस मामले में, आपको शायद शीर्षक से "पायथन समयसीमा के साथ" हटा देना चाहिए।
मार्टिन थोमा

जवाबों:


275

आप जिस समय को ब्लॉक करना चाहते हैं, उसके पहले time.time()या time.clock()बाद में उपयोग कर सकते हैं ।

import time

t0 = time.time()
code_block
t1 = time.time()

total = t1-t0

यह तरीका उतना सटीक नहीं है timeit(यह कई रन औसत नहीं है) लेकिन यह सीधा है।

time.time()(विंडोज और लिनक्स में) और time.clock()(लिनक्स में) तेज कार्यों के लिए पर्याप्त सटीक नहीं है (आपको कुल = 0 मिलता है)। इस मामले में या यदि आप कई रनों से गुजरे समय को औसत करना चाहते हैं, तो आपको फ़ंक्शन को कई बार मैन्युअल रूप से कॉल करना होगा (जैसा कि मुझे लगता है कि आप पहले से ही उदाहरण कोड में करते हैं और जब आप इसका नंबर तर्क सेट करते हैं तो समय स्वचालित रूप से होता है)

import time

def myfast():
   code

n = 10000
t0 = time.time()
for i in range(n): myfast()
t1 = time.time()

total_n = t1-t0

विंडोज में, जैसा कि कोरी ने टिप्पणी में कहा है, time.clock()इसमें बहुत अधिक सटीकता है (सेकंड के बजाय माइक्रोसेकंड) और इसे पसंद किया जाता है time.time()


8
खिड़कियों पर फी, समय के बजाय time.clock () का उपयोग करें। समय ()
कोरी गोल्डबर्ग

4
धन्यवाद कोरी, क्यों? क्योंकि घड़ी अधिक सटीक है (माइक्रोसेकंड) या कुछ और है?
प्रातः

11
आप अपने कोड प्लेटफ़ॉर्म को स्वतंत्र बनाने के लिए timeit.default_timer () का उपयोग कर सकते हैं; यह OS के लिए उपयुक्त समय .lock () या time.time () के रूप में लौटता है।
मार्क स्ट्रैब

6
हाथ से घड़ी का चयन करने के बजाय, उपयोग करें timeit.default_timer; अजगर आपके लिए काम कर चुका है। लेकिन वास्तव में, आपको timeit.timeit(myfast, number=n)दोहराए जाने वाले कॉल व्हील का फिर से आविष्कार करने के बजाय उपयोग करना चाहिए (और इस तथ्य को याद करना चाहिए कि timeitबार-बार कोड चलाते समय कचरा कलेक्टर को निष्क्रिय कर देता है)।
मार्टिन पीटर्स

15
अद्यतन: time.clock () अब पदावनत हो गया है। अब आपको time.time () का उपयोग करना चाहिए। वास्तव में, संस्करण ३.३ के बाद से, सबसे अच्छा विकल्प time.perf_counter ()
मैडलोज़ोज़

42

यदि आप अपना कोड प्रोफाइल कर रहे हैं और IPython का उपयोग कर सकते हैं, तो इसका जादू कार्य है %timeit

%%timeit कोशिकाओं पर कार्य करता है।

In [2]: %timeit cos(3.14)
10000000 loops, best of 3: 160 ns per loop

In [3]: %%timeit
   ...: cos(3.14)
   ...: x = 2 + 3
   ...: 
10000000 loops, best of 3: 196 ns per loop

36

समय के अलावा, आपके द्वारा दिखाया गया यह कोड बस गलत है: आप 100 कनेक्शन निष्पादित करते हैं (पूरी तरह से सभी को अनदेखा करते हुए अंतिम एक), और फिर जब आप पहली बार निष्पादित करते हैं तो आप इसे एक स्थानीय चर पास करते हैं query_stmtजिसे आप केवल निष्पादित करने के बाद आरंभ करते हैं। कहते हैं।

सबसे पहले, समय के बारे में चिंता किए बिना, अपने कोड को सही बनाएं: यानी एक ऐसा फ़ंक्शन जो कनेक्शन बनाता है या प्राप्त करता है और उस कनेक्शन पर 100 या 500 या जो भी अपडेट करता है, वह कनेक्शन बंद कर देता है। एक बार जब आपके पास अपना कोड सही ढंग से काम करने लगता है, तो वह सही बिंदु होता है जिस timeitपर उस पर प्रयोग करने के बारे में सोचना चाहिए!

विशेष रूप से, यदि आप जिस फ़ंक्शन को समय देना चाहते हैं, वह एक पैरामीटर-कम है जिसे foobarआप कॉल कर सकते हैं तो timeit.timeit (2.6 या बाद में - यह 2.5 और उससे पहले में अधिक जटिल है):

timeit.timeit('foobar()', number=1000)

आप बेहतर रन की संख्या निर्दिष्ट करेंगे क्योंकि डिफ़ॉल्ट, एक लाख, आपके उपयोग के मामले के लिए उच्च हो सकता है (इस कोड में बहुत समय बिताने के लिए अग्रणी; ;-))।


26
पिछले कुछ टकसालों के लिए इसके साथ संघर्ष करने के बाद मैं भविष्य के दर्शकों को यह बताना चाहता हूं कि आप शायद एक सेटअप चर भी पास करना चाहते हैं यदि आपका फ़ंक्शन foobarएक मुख्य फ़ाइल में है। जैसे: timeit.timeit('foobar()','from __main__ import foobar',number=1000)
रिच

3
पायथन 2.7.8 में, आप बस इस्तेमाल कर सकते हैंtimeit.timeit( foobar, number=1000 )

9

एक खास बात पर ध्यान दें । डिस्क I / O धीमा है, इसलिए मैं परीक्षा से बाहर निकालूंगा यदि आप सभी को ट्विक करने जा रहे हैं तो डेटाबेस क्वेरी है।

और अगर आपको अपने डेटाबेस के निष्पादन के समय की आवश्यकता है, तो इसके बजाय डेटाबेस टूल देखें, जैसे क्वेरी प्लान के लिए पूछें, और ध्यान दें कि प्रदर्शन न केवल सटीक क्वेरी और आपके पास जो इंडेक्स है, बल्कि डेटा लोड (कितना डेटा) के साथ भी भिन्न होता है आपने जमा किया है)।

उस ने कहा, आप अपना कोड किसी फ़ंक्शन में रख सकते हैं और उस फ़ंक्शन को इसके साथ चला सकते हैं timeit.timeit():

def function_to_repeat():
    # ...

duration = timeit.timeit(function_to_repeat, number=1000)

यह कचरा संग्रह को निष्क्रिय कर देगा, बार-बार function_to_repeat()फ़ंक्शन को कॉल करेगा , और उन कॉल की कुल अवधि का उपयोग करेगा timeit.default_timer(), जो आपके विशिष्ट प्लेटफॉर्म के लिए सबसे सटीक उपलब्ध घड़ी है।

आपको दोहराए गए फ़ंक्शन से सेटअप कोड को स्थानांतरित करना चाहिए ; उदाहरण के लिए, आपको पहले डेटाबेस से कनेक्ट करना चाहिए, फिर केवल क्वेरीज़। setupउन आयातों को आयात करने या बनाने के लिए तर्क का उपयोग करें , और उन्हें अपने फ़ंक्शन में पास करें:

def function_to_repeat(var1, var2):
    # ...

duration = timeit.timeit(
    'function_to_repeat(var1, var2)',
    'from __main__ import function_to_repeat, var1, var2', 
    number=1000)

ग्लोबल्स को function_to_repeat, var1और var2आपकी स्क्रिप्ट से और प्रत्येक पुनरावृत्ति फ़ंक्शन को पास करेगा।


कोड को एक फंक्शन में लाना एक ऐसा कदम है जिसे मैं देख रहा था-बस कोड को एक स्ट्रिंग बनाने के लिए और evalआईएनजी पूरी तरह से तुच्छ नहीं होने वाली किसी भी चीज के लिए उड़ान भरने वाला नहीं है। thx
javadba

2

मैं देख रहा हूं कि प्रश्न का उत्तर पहले ही दिया जा चुका है, लेकिन फिर भी मैं अपने 2 सेंट उसी के लिए जोड़ना चाहता हूं।

मुझे भी इसी तरह के परिदृश्य का सामना करना पड़ा है जिसमें मुझे कई दृष्टिकोणों के लिए निष्पादन समय का परीक्षण करना है और इसलिए एक छोटी स्क्रिप्ट लिखी है, जो इसमें लिखे गए सभी कार्यों पर समयबद्धता कहती है।

लिपि भी यहाँ गीथब जिस्ट के रूप में उपलब्ध है

आशा है कि यह आपकी और दूसरों की मदद करेगा।

from random import random
import types

def list_without_comprehension():
    l = []
    for i in xrange(1000):
        l.append(int(random()*100 % 100))
    return l

def list_with_comprehension():
    # 1K random numbers between 0 to 100
    l = [int(random()*100 % 100) for _ in xrange(1000)]
    return l


# operations on list_without_comprehension
def sort_list_without_comprehension():
    list_without_comprehension().sort()

def reverse_sort_list_without_comprehension():
    list_without_comprehension().sort(reverse=True)

def sorted_list_without_comprehension():
    sorted(list_without_comprehension())


# operations on list_with_comprehension
def sort_list_with_comprehension():
    list_with_comprehension().sort()

def reverse_sort_list_with_comprehension():
    list_with_comprehension().sort(reverse=True)

def sorted_list_with_comprehension():
    sorted(list_with_comprehension())


def main():
    objs = globals()
    funcs = []
    f = open("timeit_demo.sh", "w+")

    for objname in objs:
        if objname != 'main' and type(objs[objname]) == types.FunctionType:
            funcs.append(objname)
    funcs.sort()
    for func in funcs:
        f.write('''echo "Timing: %(funcname)s"
python -m timeit "import timeit_demo; timeit_demo.%(funcname)s();"\n\n
echo "------------------------------------------------------------"
''' % dict(
                funcname = func,
                )
            )

    f.close()

if __name__ == "__main__":
    main()

    from os import system

    #Works only for *nix platforms
    system("/bin/bash timeit_demo.sh")

    #un-comment below for windows
    #system("cmd timeit_demo.sh")

2

यहाँ स्टीवन के जवाब के लिए एक साधारण आवरण है। यह फ़ंक्शन बार-बार रन / एवरेज नहीं करता है, बस आपको समय कोड को हर जगह दोहराने से बचाता है :)

'''function which prints the wall time it takes to execute the given command'''
def time_func(func, *args): #*args can take 0 or more 
  import time
  start_time = time.time()
  func(*args)
  end_time = time.time()
  print("it took this long to run: {}".format(end_time-start_time))

0

परीक्षण सूट आयातित का उपयोग करने का प्रयास नहीं करता है, timeitइसलिए यह बताना मुश्किल है कि इरादा क्या था। फिर भी, यह एक विहित जवाब है, इसलिए timeitऑर्डर में लगता है का एक पूरा उदाहरण , मार्टिज़न के उत्तर पर विस्तृत है ।

के लिये दस्तावेजtimeit प्रस्ताव कई उदाहरण और झंडे के लायक बाहर की जाँच। कमांड लाइन पर मूल उपयोग है:

$ python -mtimeit "all(True for _ in range(1000))"
2000 loops, best of 5: 161 usec per loop
$ python -mtimeit "all([True for _ in range(1000)])"
2000 loops, best of 5: 116 usec per loop

साथ चलाने के लिए -hसभी विकल्पों को देखने के लिए। पायथन MOTW का एक बड़ा भाग है timeitजो दिखाता है कि आयात और मॉड्यूल लाइन कोड कमांड के माध्यम से मॉड्यूल कैसे चलाएं।

स्क्रिप्ट के रूप में, मैं आमतौर पर इसे इस तरह उपयोग करता हूं:

import argparse
import copy
import dis
import inspect
import random
import sys
import timeit

def test_slice(L):
    L[:]

def test_copy(L):
    L.copy()

def test_deepcopy(L):
    copy.deepcopy(L)

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--n", type=int, default=10 ** 5)
    parser.add_argument("--trials", type=int, default=100)
    parser.add_argument("--dis", action="store_true")
    args = parser.parse_args()
    n = args.n
    trials = args.trials
    namespace = dict(L = random.sample(range(n), k=n))
    funcs_to_test = [x for x in locals().values() 
                     if callable(x) and x.__module__ == __name__]
    print(f"{'-' * 30}\nn = {n}, {trials} trials\n{'-' * 30}\n")

    for func in funcs_to_test:
        fname = func.__name__
        fargs = ", ".join(inspect.signature(func).parameters)
        stmt = f"{fname}({fargs})"
        setup = f"from __main__ import {fname}"
        time = timeit.timeit(stmt, setup, number=trials, globals=namespace)
        print(inspect.getsource(globals().get(fname)))

        if args.dis:
            dis.dis(globals().get(fname))

        print(f"time (s) => {time}\n{'-' * 30}\n")

आप बहुत आसानी से उन कार्यों और तर्कों को छोड़ सकते हैं जिनकी आपको आवश्यकता है। अशुद्ध कार्यों का उपयोग करते समय सावधानी बरतें और राज्य का ख्याल रखें।

नमूना उत्पादन:

$ python benchmark.py --n 10000
------------------------------
n = 10000, 100 trials
------------------------------

def test_slice(L):
    L[:]

time (s) => 0.015502399999999972
------------------------------

def test_copy(L):
    L.copy()

time (s) => 0.01651419999999998
------------------------------

def test_deepcopy(L):
    copy.deepcopy(L)

time (s) => 2.136012
------------------------------
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.