Noticias
Entradas
Comentarios
hacker emblem

En uno de los proyectos Python en los que he estado trabajando en Emergya, detectamos la necesidad de cambiar el sistema de persistencia bsddb por algún otro que fuera más rápido. Alejandro “CuasiInfinito” Leiva me pidió diseñar un comparador de sistemas de persistencia con el estado del arte actual. Este comparador es el que ocupa esta nueva entrada en el blog.

¿Qué sistemas de persistencia se evalúan?

Los sistemas de persistencia a evaluar en rendimiento son los siguientes:

  • bsddb
  • durus
  • ZODB
  • Redis
  • PyTables

¿Qué pruebas se utilizan para medir el rendimiento?

La primera prueba para cada sistema de persistencia consiste en tomar un fichero CSV línea a línea y utilizar la operación de escritura persistente proporcionada por el sistema que se está evaluando. Es importante el hecho de que esta escritura sea persistente, uno de los errores que cometí de inicio fue pensar que unos sistemas eran más rápidos que otros sin apreciar que estaban realizando la escritura en memoria directa. Para asegurar este punto, cerraremos el manejador de datos de cada sistema una vez hayamos realizado la escritura persistente del fichero CSV completo.

A continuación, creamos un nuevo manejador y leemos los datos almacenados por el sistema de persistencia. Estos datos deben coincidir con los del CSV línea a línea.

Ambas pruebas serán medidas con una marca de tiempo al inicio y al final del proceso. Se realiza una impresión por pantalla del tiempo consumido en cada prueba por parte de cada sistema de persistencia.

¿Dónde descargo el código?

El código puede descargarse de mi cuenta en BitBucket: https://bitbucket.org/jialvarez/persystems/

¿Cómo está estructurado el código?

El código consta de un programa principal que carga el backend escogido y realiza las dos pruebas descritas en un punto anterior. Las operaciones descritas en cada backend son las siguientes:

  • __init__
  • Inicialización del backend dependiendo de la prueba a ejecutar (lectura o escritura).

  • __setitem__
  • Asignación de un elemento de manera persistente.

  • __getitem__
  • Recuperación de un elemento.

  • __len__
  • Número de elementos almacenados por el sistema persistente.

  • first
  • Devuelve el primer elemento de los almacenados de forma persistente.

  • iteritems
  • Itera a través de los elementos almacenados de forma persistente devolviendo un elemento en cada iteración. No implementado aún en todos los backends.

  • close
  • Cierra y/o destruye el manejador del sistema persistente.

  • getTestDBItems
  • Devuelve una lista con todos los elementos almacenados de forma persistente.

¿Cómo pruebo el comparador?

El código se estructura de la siguiente manera:

neonigma@hyperion:~/things/persystems$ tree
.
??? backends
?   ??? __init__.py
?   ??? pybsddb.py
?   ??? pydurus.py
?   ??? pyredis.py
?   ??? pytables.py
?   ??? pyzodb.py
??? __init__.py
??? test.py

En el directorio backends se encuentran los módulos que implementan los diferentes sistemas de persistencia. En el directorio principal, encontramos el programa test.py. Hay que modificar la variable FILENAME para que apunte a un fichero CSV válido:

FILENAME = '/tmp/fichero1.csv'

Al final del proograma, encontramos las llamadas a la ejecución de pruebas sobre cada backend:

tester = Test(getCSVReader(), "pytables")
tester = Test(getCSVReader(), "pybsddb")
tester = Test(getCSVReader(), "pyzodb")
tester = Test(getCSVReader(), "pydurus")
tester = Test(getCSVReader(), "pyredis")

Basta con comentar las que no queramos incluir en la ejecución de las pruebas. Para ejecutar el programa, escribimos:

neonigma@hyperion:~/things/persystems$ python test.py
pytables writing time: 0.0846199989319
pytables reading time: 0.0147368907928

pybsddb writing time: 0.278237104416
pybsddb reading time: 0.0832049846649

pyzodb writing time: 0.164448976517
pyzodb reading time: 0.0207080841064

pydurus writing time: 0.253404855728
pydurus reading time: 0.0357837677002

pyredis writing time: 1.39871191978
pyredis reading time: 0.624420881271

Closing remaining open files: /tmp/testpytables.db... done

En este caso los tiempos son pequeños porque estoy utilizando un fichero CSV pequeño, de 10K líneas, pero ya puede apreciarse que el ganador de la comparativa es PyTables.

A 1 persona le gusta esta entrada

2 Comentarios a “Comparativa de sistemas de persistencia en Python”

  1. javisantana dice:

    sin conocer mucho de bases de datos, no te parece que redis, una base de datos en memoria, sea la peor de todas por un order de magnitud?

  2. neonigma dice:

    Sí, es algo que me trajo de cabeza. Para el proyecto en el que trabajé era necesario que los datos no me dejaran el sistema sin memoria, y vi que en la FAQ de Redis anunciaban “Redis is an in-memory but persistent on disk database”. La duda me llevó a encontrar este enlace http://stackoverflow.com/a/11216700 con esta respuesta:

    “Redis is a server: all commands involve network or IPC roundtrips. It is meaningless to compare it to embedded data stores such as SQLite, Berkeley DB, Tokyo/Kyoto Cabinet, etc … because the cost of most operations is precisely dominated by network/protocol management.”

    En definitiva, que no tiene mucho sentido comparar a Redis en términos de persistencia en disco, puesto que su campo es la escritura concurrente / over the network. Aún así, me dejé este backend a modo académico, si bien es cierto que no está muy pulido, pues vista la causa me centré en los demás.

    Un saludo.

Dejar un comentario