[Python-ideas] Prefetching on buffered IO files
solipsis at pitrou.net
Tue Sep 28 17:06:44 CEST 2010
> I don't think the extra interface would benefit code written in Python
> as much. Even if Python code gets the data into a buffer more
> easily, it's going to pay those costs to manipulate the buffered data.
> It would mostly help modules written in C, such as pickle, which right
> now are heavily bottlenecked getting the data into a buffer.
Right. It would, however, benefit /file objects/ written in Python
(since the cost of calling a peek() written in pure Python is certainly
significant compared to the cost of the actual peeking operation).
> - But first, fix bufferediobase_readinto() so it doesn't work by
> calling the read() method and/or follow up on the TODO in
Patches welcome :)
> Comparing the C code for Python 2's cPickle and Python 3's pickle, I
> see that Python 2 has paths for unpickling from a FILE *, cStringIO,
> and "other". Python effectively only has a code path for "other", so
> it's not surprising that it's slower. In the worst case, I am sure
> that if we re-added specialized code paths that we could make it just
> as fast as Python 2, although that would make the code messy.
It would be very ugly, IMO. And it would still be slower than the clean
solution, which is to have a buffer size big enough that the overhead of
making a read() method call is dwarfed by the processing cost of the
data (that's how TextIOWrapper works).
(for the record, with the read()+peek() patch, unpickle is already
faster than Python 2, but that's comparing apples to oranges because
Python 3 got other unpickle optimizations in the meantime)
> If you want a new API, I think a new C API for I/O objects with
> C-friendly arguments would be better than a new Python-level API.
I really think we should keep an unified API. A low-level C API would be
difficult to get right, make implementations more complicated, and
consumers would have to keep fallback code for objects not implementing
the C API, which would complicate things on their side too.
Conversely, one purpose of my prefetch() proposal, besides optimizing
some workloads, is to *simplify* writing of buffered IO code.
> In a nutshell, if you feel the need to make a buffer around
> BufferedReader, then I agree there's a problem, but I don't think
> helping you make a buffer around BufferedReader is the right
> solution. ;-)
In a layered approach, it's hard not to end up with multiple levels of
buffering (think TextIOWrapper + BufferedReader + OS page-level
caching) :) I agree that shared buffers sound more efficient but, again,
I fear they would be a lot of work to get right. If you look at the
BufferedReader code, it's already non-trivial, and bugs in this area can
be really painful.
More information about the Python-ideas