Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Add optimized versions of isdir / isfile on Windows #101196

Copy link
Copy link
Closed
@mdboom

Description

@mdboom
Issue body actions

I went down this rabbit hole when someone mentioned that isfile/isdir/exists all make a rather expensive os.stat call on Windows (which is actually a long wrapper around a number of system calls on Windows), rather than the simpler and more direct call to GetFileAttributeW.

I noticed that at one point there was a version of isdir that does exactly this. At the time, this claimed a 2x speedup.

However, this C implementation of isdir was removed as part of a large set of changes in df2d4a6, and as a result, isdir got faster.

With the following benchmark:

isdir benchmark
import os.path
import timeit


for i in range(100):
    os.makedirs(f"exists{i}", exist_ok=True)


def test_exists():
    for i in range(100):
        os.path.isdir(f"exists{i}")


def test_extinct():
    for i in range(100):
        os.path.isdir(f"extinct{i}")


print(timeit.timeit(test_exists, number=100))
print(timeit.timeit(test_extinct, number=100))


for i in range(100):
    os.rmdir(f"exists{i}")

I get the following with df2d4a6:

exists: 0.18694799999957468
doesn't exist: 0.08418370000072173

and with the prior commit:

exists: 0.25393609999991895
doesn't exist: 0.08511730000009265

So, from this, I'd conclude that the idea of replacing calls to os.stat with calls to GetFileAttributeW would not bear fruit, but @zooba should probably confirm I'm benchmarking the right thing and making sense.

In any event, we should probably remove the little vestige that imports this fast path that was removed:

try:
    # The genericpath.isdir implementation uses os.stat and checks the mode
    # attribute to tell whether or not the path is a directory.
    # This is overkill on Windows - just pass the path to GetFileAttributes
    # and check the attribute from there.
    from nt import _isdir as isdir
except ImportError:
    # Use genericpath.isdir as imported above.
    pass

Linked PRs

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    Morty Proxy This is a proxified and sanitized view of the page, visit original site.