GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-99726: Improves correctness of stat results for Windows, and uses faster API when available by zooba · Pull Request #102149 · python/cpython

Conversation

@zooba

@zooba zooba commented Feb 22, 2023 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member
  • Issue: Add fast path to os.[l]stat() that returns incomplete information #99726

Also fixes #49970

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
zooba added 2 commits February 22, 2023 17:36
@zooba
pythongh-99726: Improves correctness of stat results for Windows, and…
5187810
… uses faster API when available
@zooba
Few typos
4f9695e
@zooba zooba added the OS-windows label Feb 22, 2023
@bedevere-bot bedevere-bot added the awaiting core review label Feb 22, 2023
@bedevere-bot bedevere-bot mentioned this pull request Feb 22, 2023
Add fast path to os.[l]stat() that returns incomplete information #99726
Closed
@zooba
Whitespace
00460d8
@zooba

zooba commented Feb 24, 2023

Copy link
Copy Markdown
Member Author

Open questions on this are:

  • does it work with the new Windows API (I'll test when I get access to a build with it)
  • can we change st_ctime immediately or is it better to just not expose ChangeTime and use both st_ctime and st_birthtime for the same value?
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@zooba zooba self-assigned this Feb 24, 2023
zooba added 2 commits February 28, 2023 00:09
@zooba
Add st_birthtime_ns and deprecate st_ctime instead of changing it
a01fb67
@zooba
Merge remote-tracking branch 'cpython/main' into pythongh-99726-2
0314273
@zooba

zooba commented Feb 28, 2023

Copy link
Copy Markdown
Member Author

I decided that we can't just change st_ctime, so it's deprecated instead (in docs) but still returns the same as st_birthtime for now.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

zooba added 4 commits March 3, 2023 11:24
@zooba
Merge remote-tracking branch 'cpython/main' into pythongh-99726-2
652dd19
@zooba
Update API
e2fa2a5
@zooba
Remove unnecessary FileId check and fix extension check
23a4dcc
@zooba
Merge remote-tracking branch 'cpython/main' into pythongh-99726-2
64cc626
@zooba
zooba marked this pull request as ready for review March 6, 2023 22:53
@zooba
zooba requested a review from a team as a code owner March 6, 2023 22:53
@zooba

zooba commented Mar 6, 2023

Copy link
Copy Markdown
Member Author

This supersedes #99755, or at least will conflict so much that it will need to be reimplemented.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@zooba

zooba commented Mar 7, 2023

Copy link
Copy Markdown
Member Author

@eryksun Could you take a look at this for me? Also, the API is slightly different from the last time you looked - we got some changes made in the OS to suit our needs better.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

zooba added 4 commits March 9, 2023 21:34
@zooba
Merge remote-tracking branch 'cpython/main' into pythongh-99726-2
ce037f3
@zooba
Merge branch 'main' into pythongh-99726-2
a7c6394
@zooba
Store correct birthtime value
de11468
@zooba
Improve whatsnew
d168950
@DefaultRyan

DefaultRyan commented Mar 15, 2023

Copy link
Copy Markdown

@zooba , I was analyzing some data from these changes, and I noticed that we have some "slow" calls from isdir/isfile/exists that are no longer calling stat due to #101324 (gh-101196: Make isdir/isfile/exists faster on Windows) by @mdboom . I suspect that those functions could be made faster by using the new and improved stat, when it exists. Not exists() might be a wash, but it's probably worth checking and running those benchmarks from #101324 again.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@zooba

zooba commented Mar 15, 2023

Copy link
Copy Markdown
Member Author

They shouldn't really be able to be any faster. GetFileAttributesW was already using the fast path that we now have for more info with the new API, so in theory they should be slightly faster due to a little less memcpy.

But since you've confirmed you're running these changes and haven't complained, I'll take that as the best signal I'm going to get that they're good and merge it in (tomorrow, just in case)!

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@zooba
zooba merged commit 0f17576 into python:main Mar 16, 2023
@bedevere-bot bedevere-bot removed the awaiting core review label Mar 16, 2023
@zooba
zooba deleted the gh-99726-2 branch March 16, 2023 17:27
@DefaultRyan

DefaultRyan commented Mar 16, 2023

Copy link
Copy Markdown

They shouldn't really be able to be any faster. GetFileAttributesW was already using the fast path that we now have for more info with the new API, so in theory they should be slightly faster due to a little less memcpy.

But since you've confirmed you're running these changes and haven't complained, I'll take that as the best signal I'm going to get that they're good and merge it in (tomorrow, just in case)!

Thanks for replying, but I'm not sure I understand. The new isdir/isfile/islink are no longer calling os_stat, but are calling CreateFile + GetFileInformationByHandleEx + CloseHandle, which is the "slow" pattern that this PR was replacing with GetFileInformationByName for better perf. So with this change, stat is faster, but isdir/isfile/islink are still running the slower code.

What am I missing here?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@zooba

zooba commented Mar 16, 2023

Copy link
Copy Markdown
Member Author

Huh, you're right. You're missing that I misremembered how we implemented those.

They should probably change to GetFileAttributes and check for a reparse point that way, then use the slow path for symlinks (except for the case where we only want the symlink).

In any case, now this is merged, it can be a new issue.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@zooba zooba mentioned this pull request Mar 16, 2023
Improve performance of ntpath.isdir/isfile/exists/islink #102765
Closed
@eryksun

eryksun commented Mar 16, 2023

Copy link
Copy Markdown
Contributor

@zooba, I was waiting to review this PR until GetFileInformationByName() is pushed to the general availability channel. I'm surprised that you merged code that depends on a new Windows API function that isn't generally available and has no documentation -- not even a blog post. CPython has never been that aggressive in adopting new Windows features.

They shouldn't really be able to be any faster. GetFileAttributesW was already using the fast path that we now have for more info with the new API, so in theory they should be slightly faster due to a little less memcpy.

The new ntpath.is*() functions (e.g. os__path_isdir_impl) use CreateFileW() and GetFileInformationByHandleEx(). Using GetFileAttributesW() would still require a fallback implementation that calls CreateFileW() for reparse points. It was simpler to implement just the CreateFileW() path. Also, testing showed that using CreateFileW() on balance was about as fast or faster than GetFileAttributesW(). For reparse points, using just CreateFileW() was obviously faster, since we have to call CreateFileW() anyway. Here's what I said at the time:

For me, this implementation takes about about a third less time than using os.stat(). It takes about 10% more time than using GetFileAttributesW(), but using GetFileAttributesW() is significantly more expensive for a reparse point (e.g. symlink, junction) because CreateFileW() has to be called to traverse it, which means the file is opened and queried twice.

On the other hand, at the time, my tests showed that NtQueryInformationByName() was significantly faster than NtQueryAttributesFile(). NtQueryInformationByName() uses a completely different implementation in the kernel. In principle, NtQueryAttributesFile() could take the same path, so maybe they've updated its implementation in the development channel. Either way, the ntpath.is*() functions would benefit from using this faster path to the filesystem information.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@zooba

zooba commented Mar 17, 2023

Copy link
Copy Markdown
Member Author

I'm surprised that you merged code that depends on a new Windows API function that isn't generally available and has no documentation -- not even a blog post. CPython has never been that aggressive in adopting new Windows features.

It's not a dependency - the behaviour is identical regardless of whether the API is present or not - it's just a perf optimisation when the API is available.

And we've always been this quick to adopt Windows features when I've been the one advocating to get them added into Windows for the sake of Python ;) There just haven't been a whole lot of them.

The new ntpath.is*() functions ...

Yes, I acknowledged that I made a mistake with my earlier statement, and there's a new bug to update them and I already have someone looking at it (when they get time - if not, I'll probably get to it myself). Having gone through the functionality with one of the filesystem devs, GetFileAttributesW should be optimal for the non-reparse case, and as it will tell us if it was a reparse point, it's a more efficient first check than GetFileInformationByName (which also has the same fallback). So it doesn't actually depend on this change at all.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

carljm added a commit to carljm/cpython that referenced this pull request Mar 17, 2023
@carljm
Merge branch 'main' into inlinecomp2
1a8f4a0
* main: (34 commits)
  pythongh-102701: Fix overflow in dictobject.c (pythonGH-102750)
  pythonGH-78530: add support for generators in `asyncio.wait` (python#102761)
  Increase stack reserve size for Windows debug builds to avoid test crashes (pythonGH-102764)
  pythongh-102755: Add PyErr_DisplayException(exc) (python#102756)
  Fix outdated note about 'int' rounding or truncating (python#102736)
  pythongh-102192: Replace PyErr_Fetch/Restore etc by more efficient alternatives (python#102760)
  pythongh-99726: Improves correctness of stat results for Windows, and uses faster API when available (pythonGH-102149)
  pythongh-102192: remove redundant exception fields from ssl module socket (python#102466)
  pythongh-102192: Replace PyErr_Fetch/Restore etc by more efficient alternatives (python#102743)
  pythongh-102737: Un-ignore ceval.c in the CI globals check (pythongh-102745)
  pythonGH-102748: remove legacy support for generator based coroutines from `asyncio.iscoroutine` (python#102749)
  pythongh-102721: Improve coverage of `_collections_abc._CallableGenericAlias` (python#102722)
  pythonGH-102653: Make recipe docstring show the correct distribution (python#102742)
  Add comments to `{typing,_collections_abc}._type_repr` about each other (python#102752)
  pythongh-102594: PyErr_SetObject adds note to exception raised on normalization error (python#102675)
  pythongh-94440: Fix issue of ProcessPoolExecutor shutdown hanging (python#94468)
  pythonGH-100112:  avoid using iterable coroutines in asyncio internally (python#100128)
  pythongh-102690: Use Edge as fallback in webbrowser instead of IE (python#102691)
  pythongh-102660: Fix Refleaks in import.c (python#102744)
  pythongh-102738: remove from cases generator the code related to register instructions (python#102739)
  ...
Fidget-Spinner pushed a commit to Fidget-Spinner/cpython that referenced this pull request Mar 27, 2023
@zooba @Fidget-Spinner
pythongh-99726: Improves correctness of stat results for Windows, and…
a10c1f2
… uses faster API when available (pythonGH-102149)

This deprecates `st_ctime` fields on Windows, with the intent to change them to contain the correct value in 3.14. For now, they should keep returning the creation time as they always have.
warsaw pushed a commit to warsaw/cpython that referenced this pull request Apr 11, 2023
@zooba @warsaw
pythongh-99726: Improves correctness of stat results for Windows, and…
ea7d6fe
… uses faster API when available (pythonGH-102149)

This deprecates `st_ctime` fields on Windows, with the intent to change them to contain the correct value in 3.14. For now, they should keep returning the creation time as they always have.
@RayyanAnsari RayyanAnsari mentioned this pull request Jul 10, 2023
borg2: --files-cache=ctime,inode,size (windows) borgbackup/borg#7193
Closed
@adang1345 adang1345 mentioned this pull request Oct 30, 2023
python 3.12: os.fstat() raises WinError 87 adang1345/PythonVista#19
Closed
@adang1345 adang1345 mentioned this pull request Nov 8, 2023
os.fstat() fails on FAT32 file system on Windows #111856
Closed
@AdamBraden AdamBraden mentioned this pull request Aug 21, 2024
MSYS/Cygwin performance is extremely low microsoft/Windows-Dev-Performance#15
Open
@danielhanchen danielhanchen mentioned this pull request Sep 9, 2026
Studio: cover the unsigned 64-bit edge of a linked-folder identity unslothai/unsloth#10606
Merged
@garyo garyo mentioned this pull request Sep 9, 2026
fix(install): track recursive InstallDir changes DarkStarSystems/pcons#132
Merged
@jezdez jezdez mentioned this pull request Sep 17, 2026
Windows os.stat and os.fstat report different st_ctime_ns values #157671
Open
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@zooba zooba

Labels

OS-windows

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

ctime: I don't think that word means what you think it means.

Uh oh!

There was an error while loading. Please reload this page.

4 participants

@zooba @DefaultRyan @eryksun @bedevere-bot
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.