J'ai besoin de maintenir une grande liste d'objets python pickleable. La liste est trop grande pour être stockée dans la mémoire RAM, donc un mécanisme de base de données \ paging est requis. J'ai besoin que le mécanisme permette un accès rapide pour les zones proches (proches) de la liste.maintenir une grande liste en python
La liste devrait implémenter toutes les fonctionnalités de python-list, mais la plupart du temps je vais travailler séquentiellement: balayer une partie de la liste et pendant l'analyse décider si je veux insérer \ pop quelques noeuds dans le point de scan.
La liste peut être très volumineuse (2-3 Go) et ne devrait pas être contenue dans la RAM à la fois. Les nœuds sont petits (100-200 octets) mais peuvent contenir différents types de données.
Une bonne solution pour cela pourrait être d'utiliser un BTree, où seuls les derniers buckets accédés sont chargés dans la RAM.
L'utilisation de tables SQL n'est pas bonne, car j'aurai besoin d'implémenter un mécanisme de clé d'index complexe. Mes données ne sont pas une table, c'est une simple liste python, avec la fonction d'ajouter des éléments dans des index spécifiques, et de faire sauter des éléments à partir de positions spécifiques.
J'ai essayé ZODB et zc.blist, qui implémentent une liste basée sur BTree qui peut être stockée dans un fichier de base de données ZODB, mais je ne sais pas comment le configurer pour que les fonctionnalités ci-dessus s'exécutent dans un délai raisonnable. Je n'ai pas besoin de toutes les fonctionnalités multi-threading \ transactioning. Personne d'autre ne touchera le fichier de base de données sauf pour mon programme monothread. Est-ce que quelqu'un peut m'expliquer comment configurer le ZODB \ zc.blist afin que les fonctionnalités ci-dessus puissent s'exécuter rapidement, ou me montrer une autre implémentation de grandes listes?
Une partie du code & rapide sale que j'ai essayé:
import time
import random
NODE_JUMP = 50000
NODE_ACCESS = 10000
print 'STARTING'
random_bytes = open('/dev/urandom', 'rb')
my_list = list()
nodes_no = 0
while True:
nodes_no += NODE_JUMP
start = time.time()
my_list.extend(random_bytes.read(100) for i in xrange(NODE_JUMP))
print 'extending to %s nodes took %.2f seconds' % (nodes_no, time.time() - start)
section_start = random.randint(0, nodes_no -NODE_ACCESS -1)
start = time.time()
for index in xrange(section_start, section_start + NODE_ACCESS):
# rotate the string
my_list[index] = my_list[index][1:] + my_list[index][0]
print 'access to %s nodes took %.2f seconds' % (NODE_ACCESS, time.time() - start,)
Imprimer terminée par:
extending to 5000000 nodes took 3.49 seconds access to 10000 nodes took 0.02 seconds extending to 5050000 nodes took 3.98 seconds access to 10000 nodes took 0.01 seconds extending to 5100000 nodes took 2.54 seconds access to 10000 nodes took 0.01 seconds extending to 5150000 nodes took 2.19 seconds access to 10000 nodes took 0.11 seconds extending to 5200000 nodes took 2.49 seconds access to 10000 nodes took 0.01 seconds extending to 5250000 nodes took 3.13 seconds access to 10000 nodes took 0.05 seconds Killed (not by me)
Quelle est la taille de 400 Mo? Quelle est la quantité de RAM de votre ordinateur? –
Disons qu'il peut atteindre 2Go. Je ne veux pas qu'il gaspille toutes les ressources de la mémoire. – Oren
Ma première tentative de mettre 4 000 000 objets de 100 octets dans un dictionnaire a donné lieu à un processus python consommant 900 Mo. Le temps pris était de quelques dizaines de secondes, et le temps d'accès au dictionnaire est fondamentalement instantané. –