পাইথনস টাইমিটের সাথে পারফরম্যান্স পরীক্ষার জন্য আমি কোনও কোড সেগমেন্টকে কীভাবে সময় দিতে পারি?


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
উইন্ডোতে ফাই, টাইম.লাইকের পরিবর্তে টাইমলক () ব্যবহার করুন (সময়) ()
কোরি গোল্ডবার্গ

4
ধন্যবাদ কোরি, কেন? কারণ ঘড়িটি আরও সুনির্দিষ্ট (মাইক্রোসেকেন্ডস) বা আরও কিছু আছে?
joaquin

11
আপনার কোড প্ল্যাটফর্মটি স্বাধীন করার জন্য আপনি টাইমিট.ডিফল্ট_টাইমার () ব্যবহার করতে পারেন; এটি টাইমক্লক () বা টাইম.টাইম () OS এর জন্য উপযুক্ত হিসাবে প্রদান করে।
মার্ক স্টোবার

6
হাত দ্বারা একটি ঘড়ি নির্বাচন করার পরিবর্তে, ব্যবহার timeit.default_timer; পাইথন ইতিমধ্যে আপনার জন্য কাজটি সম্পন্ন করেছে। তবে সত্যই, আপনার timeit.timeit(myfast, number=n)পুনরাবৃত্তি কল চাকাটি পুনরায় উদ্ভাবনের পরিবর্তে ব্যবহার করা উচিত (এবং timeitবারবার কোড চালানোর সময় আবর্জনা সংগ্রহকারীকে অক্ষম করে এমন বিষয়টি মিস করুন )।
মার্টিজন পিটারস

15
আপডেট: টাইম.ক্লক () এখন অবচয় করা হয়েছে। আপনার এখন সময়.টাইম () ব্যবহার করা উচিত। প্রকৃতপক্ষে, সংস্করণ 3.3 থেকে, সেরা বিকল্পটি হবে সময়.পার্ফ_কাউন্টার ()
ম্যাডলোজোজ

42

আপনি যদি নিজের কোডটি প্রোফাইলিং করে থাকেন এবং আইপিথন ব্যবহার করতে পারেন তবে এতে যাদু ফাংশন রয়েছে %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আপনি টাইমটি.টাইমাইট ব্যবহার করতে পারেন (২.6 বা তার পরে - এটি 2.5 এবং এর আগে আরও জটিল):

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

আপনার রানের সংখ্যাটি আরও ভালভাবে নির্দিষ্ট করতে চাই কারণ আপনার ব্যবহারের ক্ষেত্রে ডিফল্ট, মিলিয়ন মিলিয়ন বেশি হতে পারে (এই কোডটিতে অনেক সময় ব্যয় করতে পারে ;-)।


26
সর্বশেষ কয়েকটি টুকরোটির জন্য এটির সাথে লড়াই করার পরে আমি ভবিষ্যতের দর্শকদের জানতে চাই যে আপনার ফাংশন foobarমূল ফাইলে থাকলে সম্ভবত আপনি একটি সেটআপ ভেরিয়েবলও পাস করতে চান । এটি পছন্দ করুন: timeit.timeit('foobar()','from __main__ import foobar',number=1000)
ধনী

3
পাইথন ২.7.৮ এ আপনি সহজেই ব্যবহার করতে পারবেন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সমস্ত বিকল্প দেখতে চালাতে । পাইথন এমটডব্লুতে একটি দুর্দান্ত বিভাগ রয়েছে 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
------------------------------
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.