Je crois qu'un fichier mappé en mémoire sera la solution la plus rapide. J'ai essayé de quatre fonctions: la fonction affichée par les OP (opcount
); une simple itération sur les lignes dans le fichier (simplecount
); readline avec un mappés en mémoire déposé (mmap) (mapcount
); et le tampon de lire la solution proposée par Mykola Kharechko (bufcount
).
J'ai couru à chaque fonction de cinq fois, et calculé la moyenne de la durée d'exécution de 1,2 million de ligne d'un fichier texte.
Windows XP, Python 2.5, 2 go de RAM, 2 GHz processeur AMD
Voici mes résultats:
mapcount : 0.465599966049
simplecount : 0.756399965286
bufcount : 0.546800041199
opcount : 0.718600034714
Edit: les chiffres pour la version 2.6 de Python:
mapcount : 0.471799945831
simplecount : 0.634400033951
bufcount : 0.468800067902
opcount : 0.602999973297
De sorte que le tampon de lecture de la stratégie semble être la manière la plus rapide pour Windows/version 2.6 de Python
Voici le code:
from __future__ import with_statement
import time
import mmap
import random
from collections import defaultdict
def mapcount(filename):
f = open(filename, "r+")
buf = mmap.mmap(f.fileno(), 0)
lines = 0
readline = buf.readline
while readline():
lines += 1
return lines
def simplecount(filename):
lines = 0
for line in open(filename):
lines += 1
return lines
def bufcount(filename):
f = open(filename)
lines = 0
buf_size = 1024 * 1024
read_f = f.read # loop optimization
buf = read_f(buf_size)
while buf:
lines += buf.count('\n')
buf = read_f(buf_size)
return lines
def opcount(fname):
with open(fname) as f:
for i, l in enumerate(f):
pass
return i + 1
counts = defaultdict(list)
for i in range(5):
for func in [mapcount, simplecount, bufcount, opcount]:
start_time = time.time()
assert func("big_file.txt") == 1209138
counts[func].append(time.time() - start_time)
for key, vals in counts.items():
print key.__name__, ":", sum(vals) / float(len(vals))