optimizar lento codigo python testing timeit database-tuning

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