web-dev-qa-db-ja.com

Pythonのtimeitでパフォーマンスをテストするためにコードセグメントの時間を計るにはどうすればよいですか?

私はpythonスクリプトを持っていますが、これは正常に機能しますが、実行時間を記述する必要があります。 timeit を使用する必要があることをグーグルで確認しましたが、機能させることができないようです。

私のPythonスクリプトは次のようになります。

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に書き込むのにかかる時間です。目的は、さまざまなインデックスとチューニングメカニズムを使用して、データベースの更新ステートメントをテストすることです。

132
Mestika

time.time() または time.clock() は、時間を計るブロックの前後に使用できます。

import time

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

total = t1-t0

このメソッドは timeit (複数の実行の平均はありません)ほど正確ではありませんが、簡単です。

time.time()(WindowsおよびLinuxの場合)およびtime.clock()(Linuxの場合)は、高速関数には十分な精度ではありません(合計= 0になります)。この場合、または複数回の実行で経過した時間を平均したい場合は、関数を手動で複数回呼び出す必要があります(サンプルコードで既に実行しているように、timeitはnumber引数)

import time

def myfast():
   code

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

total_n = t1-t0

Windowsでは、Coreyがコメントで述べたように、time.clock()の精度ははるかに高く(秒ではなくマイクロ秒)、time.time()よりも優先されます。

228
joaquin

コードをプロファイリングしていて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
39
munk

タイミングとはまったく異なり、表示するこのコードは単に間違っています。100の接続を実行し(最後の接続以外は完全に無視します)、最初の実行呼び出しを行うと、ローカル変数query_stmtを渡します。実行呼び出しを初期化するafterのみ。

まず、タイミングを心配せずにコードを修正します。つまり、接続を確立または受信し、その接続で100または500または何回でも更新を実行し、接続を閉じます。コードを正しく動作させたら、timeitを使用することを考える正しいポイントになります。

具体的には、時間を計測したい関数がfoobarと呼ばれるパラメーターなしの関数である場合、 timeit.timeit (2.6以降-2.5以前ではより複雑です)を使用できます。

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

ユースケースではデフォルトの100万が多いため、実行回数を指定する方が適切です(このコードで多くの時間を費やすことになります;-)。

33
Alex Martelli

1つの特定のものに注目してください。ディスクI/Oは遅いので、データベースクエリだけを微調整する場合はテストから除外します。

また、データベースの実行時間を計る必要がある場合は、代わりに、クエリプランを要求するなどのデータベースツールを探してください。パフォーマンスは、クエリとインデックスの正確さだけでなく、データロード(データ量保存しました)。

とはいえ、単にコードを関数に入れて、その関数を timeit.timeit() で実行できます:

def function_to_repeat():
    # ...

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

これにより、ガベージコレクションが無効になり、function_to_repeat()関数が繰り返し呼び出され、特定のプラットフォームで利用可能な最も正確なクロックである timeit.default_timer() を使用して、これらの呼び出しの合計時間が計られます。

繰り返し機能のセットアップコードoutを移動する必要があります。たとえば、最初にデータベースに接続し、次にクエリのみの時間を設定する必要があります。 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_repeatvar1およびvar2を取得し、それらを繰り返しごとに関数に渡します。

8
Martijn Pieters

これがスティーブンの答えの簡単なラッパーです。この関数は繰り返しの実行/平均化を行わず、どこでもタイミングコードを繰り返す必要がなくなるだけです:)

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

質問はすでに回答されていますが、それでも2セントを追加したいと思っています。

また、いくつかのアプローチの実行時間をテストする必要がある同様のシナリオに直面しているため、小さなスクリプトを作成し、それに記述されているすべての関数でtimeitを呼び出します。

このスクリプトは、github Gist here としても利用できます。

それがあなたと他の人たちを助けることを願っています。

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 __== "__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
Abhijit Mamarde