codigo - python es lento
¿Cómo puedo programar un segmento de código para probar el rendimiento con Pythons timeit? (5)
Tengo un script de python que funciona como debería, pero necesito escribir el tiempo de ejecución. He buscado en Google que debería usar timeit
pero parece que no puedo hacer que funcione.
Mi script Python se ve así:
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)
Lo que necesito es el tiempo que lleva ejecutar la consulta y escribirla en el archivo results_update.txt
. El objetivo es probar una declaración de actualización para mi base de datos con diferentes índices y mecanismos de ajuste.
Aparte del tiempo, este código que muestra es simplemente incorrecto: ejecuta 100 conexiones (ignorando por completo todas menos la última) y luego, cuando realiza la primera llamada de ejecución, le pasa una variable local query_stmt
que solo inicializa después del ejecutar llamada.
Primero, haga que su código sea correcto, sin preocuparse por el tiempo: es decir, una función que realiza o recibe una conexión y realiza 100 o 500 o el número de actualizaciones de esa conexión, luego cierra la conexión. Una vez que tenga su código funcionando correctamente, ¡es el momento correcto para pensar en usar timeit
en él!
Específicamente, si la función que desea timeit.timeit es un parámetro sin parámetros llamado foobar
, puede usar timeit.timeit (2.6 o posterior, es más complicado en 2.5 y antes):
timeit.timeit(''foobar()'', number=1000)
Será mejor que especifique el número de ejecuciones porque el valor predeterminado, un millón, puede ser alto para su caso de uso (lo que lleva a pasar mucho tiempo en este código ;-).
Enfócate en una cosa específica . La E / S de disco es lenta, así que la sacaría de la prueba si lo único que va a modificar es la consulta de la base de datos.
Y si necesita cronometrar la ejecución de su base de datos, busque herramientas de base de datos, como solicitar el plan de consulta, y tenga en cuenta que el rendimiento varía no solo con la consulta exacta y qué índices tiene, sino también con la carga de datos (cuántos datos usted ha almacenado).
Dicho esto, puede simplemente poner su código en una función y ejecutar esa función con timeit.timeit()
:
def function_to_repeat():
# ...
duration = timeit.timeit(function_to_repeat, number=1000)
Esto inhabilitaría la recolección de basura, llamaría repetidamente a la function_to_repeat()
y timeit.default_timer la duración total de esas llamadas usando timeit.default_timer , que es el reloj disponible más preciso para su plataforma específica.
Debería mover el código de configuración fuera de la función repetida; por ejemplo, primero debe conectarse a la base de datos, luego cronometrar solo las consultas. Utilice el argumento de setup
para importar o crear esas dependencias y pasarlas a su función:
def function_to_repeat(var1, var2):
# ...
duration = timeit.timeit(
''function_to_repeat(var1, var2)'',
''from __main__ import function_to_repeat, var1, var2'',
number=1000)
tomaría las function_to_repeat
var1
, var1
y var2
de su script y las pasaría a la función cada repetición.
Puede usar time.time()
o time.clock()
antes y después del bloque que desea time.clock()
.
import time
t0 = time.time()
code_block
t1 = time.time()
total = t1-t0
Este método no es tan exacto como el timeit
(no promedia varias ejecuciones) pero es sencillo.
time.time()
(en Windows y Linux) y time.clock()
(en Linux) no son lo suficientemente precisos para las funciones rápidas (obtienes total = 0). En este caso o si desea promediar el tiempo transcurrido por varias ejecuciones, debe llamar manualmente la función varias veces (como creo que ya hace en su código de ejemplo y timeit lo hace automáticamente cuando establece su argumento numérico )
import time
def myfast():
code
n = 10000
t0 = time.time()
for i in range(n): myfast()
t1 = time.time()
total_n = t1-t0
En Windows, como declaró Corey en el comentario, time.clock()
tiene una precisión mucho mayor (microsegundos en lugar de segundos) y es preferible a time.time()
.
Si está perfilando su código y puede usar IPython, tiene la función mágica %timeit
.
%%timeit
opera en las celdas.
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
Veo que la pregunta ya ha sido respondida, pero aún quiero agregar mis 2 centavos por la misma.
También me he enfrentado a un escenario similar en el que tengo que probar los tiempos de ejecución para varios enfoques y, por lo tanto, escribí un pequeño script, que llama tiempo en todas las funciones escritas en él.
El guión también está disponible como github gist here .
Espero que te ayude a ti y a los demás.
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")