[cpif] r19 - in trunk: . tests
svn at argo.es
svn at argo.es
Mon Apr 23 20:01:43 CEST 2007
Author: jcea
Date: Mon Apr 23 20:01:41 2007
New Revision: 19
Log:
Mas infraestructura.
Un nuevo ejemplo equivalente al anterior, pero usando
la nueva infraestructura.
Corregido un bug en el ejemplo inicial.
Added:
trunk/tests/ejemplo2.py
- copied, changed from r18, /trunk/tests/ejemplo1.py
Modified:
trunk/database.py
trunk/tests/ejemplo1.py
Modified: trunk/database.py
==============================================================================
--- trunk/database.py (original)
+++ trunk/database.py Mon Apr 23 20:01:41 2007
@@ -1,6 +1,11 @@
# $Id$
-VERSION_DB="2007041901"
+
+VERSION_DB="2007042301"
+
+
+def normaliza_nick(nick) :
+ return nick.lower()
def init_database(monitor) :
@monitor
@@ -36,5 +41,104 @@
seguimiento_no_leidos["last_msg2hilo"]=BTree()
root["seguimiento_no_leidos"]=seguimiento_no_leidos
+ root["punto_de_lectura_global"]=BTree()
+
init()
+
+def usuario_add(conn,nick,datos) :
+ from durus.btree import BTree
+ from durus.persistent_dict import PersistentDict
+ import time
+
+ root=conn.get_root()
+ usuarios=root["usuarios"]
+
+ nick_normalizado=normaliza_nick(nick)
+ assert nick_normalizado not in usuarios["usuarios"]
+
+ usuarios["num_usuarios"]+=1
+
+ usuarios["usuarios"][nick_normalizado]=PersistentDict(
+ {"ultimo mensaje conocido":root["mensajes"]["num_mensajes"],
+ "punto de lectura no leidos":BTree(),
+ "punto de lectura":BTree(),
+ "TS creacion":time.time(),
+ "TS ultima entrada":0,
+ "num mensajes":0,
+ "mensajes":BTree(),
+ "datos":datos})
+
+def mensaje_add(conn,texto,usuario,hilo=None,titulo=None) :
+ from durus.btree import BTree
+ from durus.persistent_dict import PersistentDict
+ import time
+
+ usuario=normaliza_nick(usuario)
+
+ root=conn.get_root()
+ hilos=root["hilos"]
+ mensajes=root["mensajes"]
+ seguimiento_no_leidos=root["seguimiento_no_leidos"]
+
+ mensaje=PersistentDict(
+ {"texto":texto,
+ "TS":time.time(),
+ "autor":usuario})
+
+ mensajes["num_mensajes"]+=1
+ num_msg=mensajes["num_mensajes"]
+ mensajes["mensajes"][num_msg]=mensaje
+
+ if hilo!=None :
+ h=hilo
+ mensaje["hilo"]=hilo
+ hilo=hilos["hilos"][hilo]
+ last=hilo["mensajes"].get_max_item()[0]
+ del seguimiento_no_leidos["last_msg2hilo"][last]
+ else : # Empezamos un hilo nuevo
+ hilos["num_hilos"]+=1
+ h=hilos["num_hilos"]
+ root["punto_de_lectura_global"][h]=0
+ hilo=PersistentDict()
+ assert titulo
+ hilo=PersistentDict(
+ {"creador":usuario,
+ "TS creacion":time.time(),
+ "titulo":titulo,
+ "num_mensajes":0,
+ "mensajes":BTree()})
+ hilos["hilos"][h]=hilo
+ mensaje["hilo"]=h
+
+ seguimiento_no_leidos["hilo2last_msg"][h]=num_msg
+ seguimiento_no_leidos["last_msg2hilo"][num_msg]=h
+
+ hilo["num_mensajes"]+=1
+ hilo["mensajes"][num_msg]=mensaje
+
+ usuario=root["usuarios"]["usuarios"][usuario]
+ usuario["num mensajes"]+=1
+ usuario["mensajes"][num_msg]=mensaje
+
+def actualiza_no_leidos(conn,usuario) :
+ root=conn.get_root()
+ punto_de_lectura_global=root["punto_de_lectura_global"]
+ usuario=root["usuarios"]["usuarios"][normaliza_nick(usuario)]
+ l=usuario["ultimo mensaje conocido"]
+ posicion_hilos_no_leidos=usuario["punto de lectura no leidos"]
+ posicion_hilos=usuario["punto de lectura"]
+
+ last_msg2hilo=root["seguimiento_no_leidos"]["last_msg2hilo"]
+
+ for last,hilo in last_msg2hilo.items_backward() :
+ if last<=l : # Hemos terminado. Esto sera mas simple en Durus 3.7
+ usuario["ultimo mensaje conocido"]=root["mensajes"]["num_mensajes"]
+ break
+ # Vemos cual es el ultimo leido para ese hilo
+ ultimo=posicion_hilos.get(hilo) # Esta es la optimizacion de hilos que todo el mundo ha leido ya...
+ if not ultimo : 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
+
+
Modified: trunk/tests/ejemplo1.py
==============================================================================
--- trunk/tests/ejemplo1.py (original)
+++ trunk/tests/ejemplo1.py Mon Apr 23 20:01:41 2007
@@ -8,6 +8,10 @@
# Modificado para que funcione en nuestro entorno
+from logging import disable
+disable(9999)
+
+
import os
os.chdir("..")
import sys
@@ -96,28 +100,27 @@
from random import randint
@monitor
-def mete_mensajes(conn) :
+def mete_mensaje(conn,hilo) :
root=conn.get_root()
- # 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
+ 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
+# Elegimos 100 hilos al azar
+hilos=[randint(0,999) for i in xrange(100)]*10 # Insertamos 1000 mensajes nuevos en hilos al azar
t=time.time()
-mete_mensajes()
-print "Realizamos %f inserciones por segundo" %(100/(time.time()-t))
+for hilo in hilos :
+ mete_mensaje(hilo)
+print "Realizamos %f inserciones por segundo" %(1000/(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
+# 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
@@ -127,30 +130,30 @@
# es enorme.
@monitor
-def actualiza_usuarios(conn) :
+def actualiza_usuario(conn,usernum) :
root=conn.get_root()
- for usernum in xrange(1000) : # Probamos a hacer login de los primeros 1000 usuarios
- usuario=root["usuarios"][usernum]
+ 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]
- 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
+ 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]
+ break
+ # Vemos cual es el ultimo leido para ese hilo
+ ultimo=posicion_hilos.get(hilo) # Esta es la optimizacion de hilos que todo el mundo ha leido ya...
+ if not ultimo : 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
t=time.time()
-actualiza_usuarios()
+for usernum in xrange(1000) : # Probamos a hacer login de los primeros 1000 usuarios
+ actualiza_usuario(usernum)
print "En un caso muy pesimista, tenemos %f actualizaciones de hilos no leidos por segundo" %(1000/(time.time()-t))
Copied: trunk/tests/ejemplo2.py (from r18, /trunk/tests/ejemplo1.py)
==============================================================================
--- /trunk/tests/ejemplo1.py (original)
+++ trunk/tests/ejemplo2.py Mon Apr 23 20:01:41 2007
@@ -8,87 +8,46 @@
# Modificado para que funcione en nuestro entorno
+from logging import disable
+disable(9999)
+
import os
os.chdir("..")
import sys
sys.path.append(".")
-from durus.btree import BTree
-from durus.persistent_dict import PersistentDict
-
import storage
dummy,dummy,monitor=storage.storage_and_monitor("db-test",storage=storage.storage_test)
-# 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".
+import database
-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()})
-
+database.init_database(monitor)
-# Una vez inicializado todo, comprometemos la transaccion
@monitor
-def inicializa(conn) :
+def inicializacion(conn) :
root=conn.get_root()
- 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..."
-
-inicializa()
+ usuarios=root["usuarios"]["usuarios"]
+ for i in xrange(10000) : # 10.000 usuarios
+ i=str(i)
+ database.usuario_add(conn,i,{})
+# Marcamos como "leido hasta aqui"
+ usuarios[i]["ultimo mensaje conocido"]=1000
+
+ for i in xrange(1000) : # 1.000 hilos
+ database.mensaje_add(conn,"prueba",str(i),None,"hilo %d" %i)
+
+# Marcamos todo como leido, para todos
+ punto_de_lectura_global=root["punto_de_lectura_global"]
+ for i in xrange(1,1001) :
+ punto_de_lectura_global[i]=i
+
+ print "Commit inicial..."
+
+inicializacion()
+
-
# Aqui empieza la chicha. Lo primero que queremos saber es el coste
# de insercion de un mensaje nuevo.
@@ -96,61 +55,24 @@
from random import randint
@monitor
-def mete_mensajes(conn) :
- root=conn.get_root()
- # 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
+def mete_mensaje(conn,usuario,hilo,mensaje) :
+ database.mensaje_add(conn,mensaje,usuario,hilo)
+hilos=[randint(1,1000) for i in xrange(100)]*10 # Insertamos 1000 mensajes nuevos en 100 hilos al azar
t=time.time()
-mete_mensajes()
-print "Realizamos %f inserciones por segundo" %(100/(time.time()-t))
+for hilo in hilos :
+ mete_mensaje(str(hilo),hilo,"PRUEBA!!!")
+print "Realizamos %f inserciones por segundo" %(1000/(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.
-
@monitor
-def actualiza_usuarios(conn) :
- root=conn.get_root()
- 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]
- 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
+def actualiza_usuario(conn,usuario) :
+ database.actualiza_no_leidos(conn,usuario)
+usuarios=[str(i) for i in xrange(10)] # Probamos a hacer login de los primeros 1000 usuarios
t=time.time()
-actualiza_usuarios()
-print "En un caso muy pesimista, tenemos %f actualizaciones de hilos no leidos por segundo" %(1000/(time.time()-t))
+for usernum in usuarios :
+ actualiza_usuario(usernum)
+print "En un caso muy pesimista, tenemos %f actualizaciones de hilos no leidos por segundo" %(10/(time.time()-t))
More information about the cpif
mailing list