<div dir="ltr">I vote for the C implementation.<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Feb 13, 2015 at 2:07 AM, Victor Stinner <span dir="ltr"><<a href="mailto:victor.stinner@gmail.com" target="_blank">victor.stinner@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
TL,DR: are you ok to add 800 lines of C code for os.scandir(), 4x<br>
faster than os.listdir() when the file type is checked?<br>
<br>
I accepted the PEP 471 (os.scandir) a few months ago, but it is not<br>
implement yet in Python 3.5, because I didn't make a choice on the<br>
implementation.<br>
<br>
Ben Hoyt wrote different implementations:<br>
- full C: os.scandir() and DirEntry are written in C (no change on os.py)<br>
- C+Python: os._scandir() (wrapper for opendir/readdir and<br>
FindFirstFileW/FindNextFileW) in C, DirEntry in Python<br>
- ctypes: os.scandir() and DirEntry fully implemented in Python<br>
<br>
I'm not interested by the ctypes implementation. It's useful for a<br>
third party project hosted at PyPI, but for CPython I prefer to wrap C<br>
functions using C code.<br>
<br>
<br>
In short, the C implementation is faster than the C+Python implementation.<br>
<br>
The issue #22524 (*) is full of benchmark numbers. IMO the most<br>
interesting benchmark is to compare os.listdir() + os.stat() versus<br>
os.scandir() + Direntry.is_dir(). Let me try to summarize results of<br>
this benchmark:<br>
<br>
* C implementation: scandir is at least 3.5x faster than listdir, up<br>
to 44.6x faster on Windows<br>
* C+Python implementation: scandir is not really faster than listdir,<br>
between 1.3x and 1.4x faster<br>
<br>
(*) <a href="http://bugs.python.org/issue22524" target="_blank">http://bugs.python.org/issue22524</a><br>
<br>
<br>
Ben Hoyt reminded me that os.scandir() (PEP 471) doesn't add any new<br>
feature: pathlib already provides a nice API on top of os and os.path<br>
modules. (You may even notice that DirEntry a much fewer methods ;-))<br>
The main (only?) purpose of the PEP is performance.<br>
<br>
If os.scandir() is "only" 1.4x faster, I don't think that it is<br>
interesting to use os.scandir() in an application. I guess that all<br>
applications/libraries will want to keep compatibility with Python 3.4<br>
and older and so will anyway have to duplicate the code to use<br>
os.listdir() + os.stat(). So is it worth to duplicate code for such<br>
small speedup?<br>
<br>
Now I see 3 choices:<br>
<br>
- take the full C implementation, because it's much faster (at least<br>
3.4x faster!)<br>
- reject the whole PEP 471 (not nice), because it adds too much code<br>
for a minor speedup (not true on Windows: up to 44x faster!)<br>
- take the C+Python implementation, because maintenance matters more<br>
than performances (only 1.3x faster, sorry)<br>
<br>
=> IMO the best option is to take the C implementation. What do you think?<br>
<br>
<br>
I'm concerned by the length of the C code: the full C implementations<br>
adds ~800 lines of C code to posixmodule.c. This file is already the<br>
longest C file in CPython. I don't want to make it longer, but I'm not<br>
motived to start to split it. Last time I proposed to split a file<br>
(unicodeobject.c), some developers complained that it makes search<br>
harder. I don't understand this, there are so many tools to navigate<br>
in C code. But it was enough for me to give up on this idea.<br>
<br>
A alternative is to add a new _scandir.c module to host the new C<br>
code, and share some code with posixmodule.c: remove "static" keyword<br>
from required C functions (functions to convert Windows attributes to<br>
a os.stat_result object). That's a reasonable choice. What do you<br>
think?<br>
<br>
<br>
FYI I ran the benchmark on different hardware (SSD, HDD, tmpfs), file<br>
systems (ext4, tmpfs, NFS/ext4), operating systems (Linux, Windows).<br>
<br>
Victor<br>
_______________________________________________<br>
Python-Dev mailing list<br>
<a href="mailto:Python-Dev@python.org">Python-Dev@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-dev" target="_blank">https://mail.python.org/mailman/listinfo/python-dev</a><br>
Unsubscribe: <a href="https://mail.python.org/mailman/options/python-dev/guido%40python.org" target="_blank">https://mail.python.org/mailman/options/python-dev/guido%40python.org</a><br>
</blockquote></div><br><br clear="all"><br>-- <br><div class="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido">python.org/~guido</a>)</div>
</div>