#!/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()