[cpif] r11 - trunk/varios
svn at argo.es
svn at argo.es
Wed Apr 18 22:25:28 CEST 2007
Author: jcea
Date: Wed Apr 18 22:25:26 2007
New Revision: 11
Log:
Added:
trunk/varios/
trunk/varios/prueba_de_concepto.py
Added: trunk/varios/prueba_de_concepto.py
==============================================================================
--- (empty file)
+++ trunk/varios/prueba_de_concepto.py Wed Apr 18 22:25:26 2007
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+
+# Original en http://www.curiosoperoinutil.com/forum/viewtopic.php?t=3721
+# Mas concretamente http://www.curiosoperoinutil.com/forum/viewtopic.php?p=71941#71941
+# y http://www.curiosoperoinutil.com/forum/viewtopic.php?p=72387#72387
+
+
+from logging import disable
+ disable(9999)
+
+ import sys
+ sys.path.append("/export/home/correo/durus-berkeleydbstorage")
+
+ from durus.btree import BTree
+ from durus.persistent_dict import PersistentDict
+ from durus.connection import Connection
+ from berkeleydb_storage import BerkeleyDBStorage
+
+ datos=Connection(BerkeleyDBStorage("db",durable=False,async_log_write=True))
+
+ root=datos.get_root()
+
+ # La numeracion de los mensajes es global.
+ # Lo primero es crear el arbol de actualizacion de hilos
+ # dicho arbol, indexado por numero de mensaje global, nos indica en que
+ # momento se actualizo, por ultima vez, un hilo concreto
+ #
+ # Por otra parte tenemos otro arbol, indexado por hilo, que
+ # nos indica el ultimo mensaje del mismo
+ #
+ # En principio suponemos que cada hilo solo tiene un mensaje,
+ # para inicializar todos los hilos con "algo".
+
+ hilo2last_msg=BTree()
+ last_msg2hilo=BTree()
+
+ for i in xrange(1000) : # Hay mil hilos, cada uno con un mensaje. LA NUMERACION ES GLOBAL!!!
+ hilo2last_msg[i]=i
+ last_msg2hilo[i]=i
+
+ # Al principio suponemos que los usuarios estan "al dia". Es decir, para cada
+ # hilos, han leido todos los mensajes.
+
+ # Cada usuario tiene tres datos:
+ # - El ultimo numero de mensaje que "sabe" que ha entrado en los hilos
+ # - La posicion de lectura en cada hilo
+ # - El ultimo mensaje leido en cada hilo con mensajes nuevos
+ #
+ # OPTIMIZACION: Un hilo leido por TODOS los usuarios
+ # no se mantiene (su posicion) en cada usuario, sino en
+ # una estructura global. Es decir, cuando se quiere ver cual
+ # es el numero del ultimo mensaje leido por un usuario en
+ # un hilo concreto, buscamos la posicion de de dicho hilo
+ # en la estructura privada del usuario. Si ahi no aparece nada,
+ # la buscamos en la estructura global, compartida por todos los
+ # usuarios. Esta es una optimizacion de espacio en disco, ya
+ # que en cada usuario solo se guardaran las posiciones de lectura
+ # en los hilos "vivos", mientras que los hilos muertos
+ # se guardan en la estructura global, compartida por todos los
+ # usuarios.
+
+ # En lo que sigue suponemos que todos los usuarios parten de todos
+ # los mensajes leidos, asi que su posicion estara en una estructura
+ # global que no se muestra. Basicamente, lo que se guarda localmente
+ # en cada usuario es su diferencia personal respecto a esa tabla global.
+
+ import copy
+ punto_de_lectura_global=copy.deepcopy(hilo2last_msg)
+
+ usuarios=BTree()
+ for i in xrange(10000) : # 10.000 usuarios
+ usuarios[i]=PersistentDict({"ultimo mensaje conocido":999, \
+ "punto de lectura no leidos":BTree(),
+ "punto de lectura":BTree()})
+
+ # Una vez inicializado todo, comprometemos la transaccion
+ root["usuarios"]=usuarios
+ root["hilo2last_msg"]=hilo2last_msg
+ root["last_msg2hilo"]=last_msg2hilo
+ root["proximo mensaje"]=1000
+ root["punto de lectura global"]=punto_de_lectura_global
+ print "Commit inicial..."
+ datos.commit()
+
+
+ # Aqui empieza la chicha. Lo primero que queremos saber es el coste
+ # de insercion de un mensaje nuevo.
+
+ import time
+ from random import randint
+
+ # Elegimos 100 hilos al azar
+ hilos=[randint(0,999) for i in xrange(100)] # Insertamos 100 mensajes nuevos en hilos al azar
+ t=time.time()
+ for hilo in hilos : # Lo que sigue se puede optimizar bastante, pero ya vuela...
+ num_msg=root["proximo mensaje"]
+ root["proximo mensaje"]+=1
+ last=root["hilo2last_msg"][hilo]
+ root["hilo2last_msg"][hilo]=num_msg
+ del root["last_msg2hilo"][last]
+ root["last_msg2hilo"][num_msg]=hilo
+ datos.commit() # Comprometemos esa transaccion...
+ print "Realizamos %f inserciones por segundo" %(100/(time.time()-t))
+
+
+ # Bien, ahora un usuario quiere ver que hilos no ha leido, y movese al ultimo
+ # mensaje no leido de cada uno de ellos.
+ # Observese que este caso es MUY pesimista, ya que puede haber hasta 100
+ # hilos con mensajes nuevos, lo que es poco realista. El tiempo REAL
+ # es propocional al numero de hilos actualizados, no al numero de mensajes
+ # posteados. Es decir, si se han actualizado 100 hilos con un unico mensaje
+ # mas que en el caso normal de que se hayan actualizado unos pocos hilos,
+ # cada uno de ellos con varios mensajes.
+ # Pero vamos a ser muy pesimistas y suponer que el numero de hilos actualizados
+ # es enorme.
+
+ t=time.time()
+ for usernum in xrange(1000) : # Probamos a hacer login de los primeros 1000 usuarios
+ usuario=root["usuarios"][usernum]
+
+ # Lo que sigue es un poco "raro" por una limitacion de la version actual de
+ # durus. En Durus 3.7, actualmente en beta, podremos iterar sobre intervalos abiertos...
+ l=usuario["ultimo mensaje conocido"]
+ posicion_hilos_no_leidos=usuario["punto de lectura no leidos"]
+ posicion_hilos=usuario["punto de lectura"]
+ punto_de_lectura_global=root["punto de lectura global"]
+
+ for last,hilo in root["last_msg2hilo"].items_backward() :
+ if last<l : # Hemos terminado. Esto sera mas simple en Durus 3.7
+ usuario["ultimo mensaje conocido"]=root["last_msg2hilo"].get_max_item()[0]
+ datos.commit()
+ break
+ # Vemos cual es el ultimo leido para ese hilo
+ ultimo=posicion_hilos.get(hilo,None) # Esta es la optimizacion de hilos que todo el mundo ha leido ya...
+ if ultimo==None : ultimo=punto_de_lectura_global[hilo]
+ if ultimo < last : # Este hilo tiene mensajes nuevos...
+ posicion_hilos_no_leidos[hilo]=ultimo # Lo marcamos como pendiente de leer y nos vamos al ultimo que hemos leido
+
+ print "En un caso muy pesimista, tenemos %f actualizaciones de hilos no leidos por segundo" %(1000/(time.time()-t))
+
+
More information about the cpif
mailing list