John O'Connor <tehj...@gmail.com> added the comment: I experimented with a bunch of different options.
All benchmarks performed with: $ for i in 1 4 128 256 1024 2048 4069 8192; do echo -n "buffer_size=${i} "; ./python -m timeit -s "f=open('LICENSE','rb');b=bytearray(${i})" \ "f.seek(0)" "while f.readinto(b): pass"; done with io.DEFAULT_BUFFER_SIZE = 8192 -------------------------------------------------------------------------------- Before patch buffer_size=1 100 loops, best of 3: 10.4 msec per loop buffer_size=4 100 loops, best of 3: 2.67 msec per loop buffer_size=128 10000 loops, best of 3: 102 usec per loop buffer_size=256 10000 loops, best of 3: 54.9 usec per loop buffer_size=1024 10000 loops, best of 3: 26.9 usec per loop buffer_size=2048 10000 loops, best of 3: 20.3 usec per loop buffer_size=4069 100000 loops, best of 3: 16.3 usec per loop buffer_size=8192 100000 loops, best of 3: 11.1 usec per loop -------------------------------------------------------------------------------- Always read into caller's buffer buffer_size=1 100 loops, best of 3: 14 msec per loop buffer_size=4 100 loops, best of 3: 4.02 msec per loop buffer_size=128 10000 loops, best of 3: 114 usec per loop buffer_size=256 10000 loops, best of 3: 63.7 usec per loop buffer_size=1024 100000 loops, best of 3: 19.4 usec per loop buffer_size=2048 100000 loops, best of 3: 11.2 usec per loop * buffer_size=4069 100000 loops, best of 3: 8.12 usec per loop * buffer_size=8192 100000 loops, best of 3: 5.79 usec per loop -------------------------------------------------------------------------------- Read into caller's buffer if java-like bound of internal buffer size is smaller buffer_size=1 100 loops, best of 3: 5.01 msec per loop buffer_size=4 1000 loops, best of 3: 1.27 msec per loop buffer_size=128 10000 loops, best of 3: 46.9 usec per loop buffer_size=256 10000 loops, best of 3: 29.5 usec per loop buffer_size=1024 100000 loops, best of 3: 12.9 usec per loop buffer_size=2048 100000 loops, best of 3: 10.8 usec per loop buffer_size=4069 100000 loops, best of 3: 9.06 usec per loop * buffer_size=8192 100000 loops, best of 3: 5.78 usec per loop -------------------------------------------------------------------------------- Using bound = buffer_size / 2 buffer_size=1 100 loops, best of 3: 6.04 msec per loop buffer_size=4 1000 loops, best of 3: 1.34 msec per loop buffer_size=128 10000 loops, best of 3: 49.4 usec per loop buffer_size=256 10000 loops, best of 3: 29.5 usec per loop buffer_size=1024 100000 loops, best of 3: 13.2 usec per loop buffer_size=2048 100000 loops, best of 3: 10.7 usec per loop * buffer_size=4069 100000 loops, best of 3: 8.66 usec per loop buffer_size=8192 100000 loops, best of 3: 6.1 usec per loop -------------------------------------------------------------------------------- Using bound = buffer_size / 4 buffer_size=1 100 loops, best of 3: 5.45 msec per loop buffer_size=4 1000 loops, best of 3: 1.34 msec per loop buffer_size=128 10000 loops, best of 3: 49.6 usec per loop buffer_size=256 10000 loops, best of 3: 28.8 usec per loop buffer_size=1024 100000 loops, best of 3: 13.1 usec per loop buffer_size=2048 100000 loops, best of 3: 12.8 usec per loop buffer_size=4069 100000 loops, best of 3: 8.42 usec per loop buffer_size=8192 100000 loops, best of 3: 5.93 usec per loop -------------------------------------------------------------------------------- Always use internal buffer * buffer_size=1 100 loops, best of 3: 4.53 msec per loop * buffer_size=4 1000 loops, best of 3: 1.14 msec per loop * buffer_size=128 10000 loops, best of 3: 45 usec per loop * buffer_size=256 10000 loops, best of 3: 26.9 usec per loop * buffer_size=1024 100000 loops, best of 3: 12.9 usec per loop * buffer_size=2048 100000 loops, best of 3: 10.2 usec per loop buffer_size=4069 100000 loops, best of 3: 9.15 usec per loop buffer_size=8192 100000 loops, best of 3: 8.42 usec per loop -------------------------------------------------------------------------------- Use read() instead $ for i in 1 4 128 256 1024 2048 4069 8192; do echo -n "size=${i} "; ./python -m timeit -s "f=open('LICENSE','rb');" "f.seek(0)" \ "while f.read(${i}): pass"; done * size=1 100 loops, best of 3: 2.56 msec per loop * size=4 1000 loops, best of 3: 709 usec per loop * size=128 10000 loops, best of 3: 29.7 usec per loop * size=256 100000 loops, best of 3: 18.6 usec per loop size=1024 100000 loops, best of 3: 13.3 usec per loop size=2048 100000 loops, best of 3: 10.8 usec per loop size=4069 100000 loops, best of 3: 10.1 usec per loop size=8192 100000 loops, best of 3: 6.41 usec per loop -------------------------------------------------------------------------------- Based on the above I think you are right about using the internal buffer regardless (revision attached). You pay a price with larger buffer sizes but on balance it seems to be a much better general purpose solution. The java-like solution is decent as well, it is only slightly slower for small reads and optimal for larger buffer sizes. Personally, I would opt for the performance with larger buffer sizes but I can only speculate as to what the general user would do. We could always note the trade-off in the docs. Interestingly enough it seems like using read() is a better idea if you use a smaller size (how is that right?). I attached the afformentioned revisions. ---------- Added file: http://bugs.python.org/file21940/issue9971.patch _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue9971> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com