#!/usr/bin/python2
"""Tests different versions to implement tail (except seek or mmap)
Results for python-2.7, linux x86_64:
20940 lines, average line length 163:
dequetail 3.69968
listtail 5.02768
Performance seems largely independent of requested number of lines
"""
import collections
import sys
import timeit
def tail(filename, count, method):
with open(filename, 'r') as filein:
return method(filein, count)
def dequetail(filein, count):
return collections.deque(filein, count)
def listtail(filein, count):
lines = list()
readlines = filein.readlines
while True:
block = readlines(8196)
if block:
replaced = max(0, len(block) + len(lines) - count)
del lines[:replaced]
lines += block
else:
break
del lines[:-count]
return lines
def test(methods, filename, count):
results = ((method, list(tail(filename, count, method))) for method
in methods)
_, trusted = next(results)
wrongs = (method.__name__ for method, result in results
if result != trusted)
messages = ("%s failed\n" % method for method in wrongs)
sys.stderr.writelines(messages)
filename = None
def main():
global filename
filename = sys.argv[1]
count = 100
methods = (dequetail, listtail)
test(methods, filename, count)
methodnames = [method.__name__ for method in methods]
setups = ('from __main__ import %s, tail, filename' % method for method
in methodnames)
stmts = ("tail(filename, %d, %s)" % (count, method) for method
in methodnames)
times = (timeit.timeit(setup=setup, stmt=stmt, number=1000)
for setup, stmt in zip(setups, stmts))
output = ("%s\t%g\n" % (method, time) for method, time
in zip(methodnames, times))
sys.stderr.writelines(output)
if __name__ == '__main__':
main()
Comments