[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