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-138535: Optimize fill_time for typical timestamps by jbosboom · Pull Request #138537 · python/cpython

Conversation

@jbosboom

@jbosboom jbosboom commented Sep 5, 2025 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Contributor

While file timestamps can be anything the file system can store, most lie between the recent past and the near future. Optimize fill_time for typical timestamps in three ways:

  • When possible, convert to nanoseconds with C arithmetic.
  • When using C arithmetic and the seconds member is not required (for st_birthtime), avoid creating a long object.
  • When using C arithmetic, reorder the code to avoid the null checks implied in Py_XDECREF.

This improves python -m pyperf timeit -s 'import os' 'os.stat(".")' from 1.26 us +- 0.02 us to 1.15 us +- 0.01 us on Linux 6.16.2.arch1-1 btrfs and --enable-optimizations --with-lto.

I found this while implementing os.stat_result.st_birthtime on Linux and trying not to regress performance. This is a small change that should be an improvement on all platforms, so I've submitted it separately.

This needs tests, presumably in test_os.py UtimeTests.test_large_time, though it's actually testing os.stat. But that test currently only runs on NTFS on Windows. I'll look at Linux filesystem support tomorrow.

  • Issue: Optimize posixmodule.c:fill_time for typical timestamps #138535

Sorry, something went wrong.

Uh oh!

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

All reactions
@jbosboom
Optimize fill_time for typical timestamps
a92719d
While file timestamps can be anything the file system can store, most
lie between the recent past and the near future.  Optimize fill_time for
typical timestamps in three ways:

- When possible, convert to nanoseconds with C arithmetic.
- When using C arithmetic and the seconds member is not required (for
  st_birthtime), avoid creating a long object.
- When using C arithmetic, reorder the code to avoid the null checks
  implied in Py_XDECREF.
@bedevere-app bedevere-app Bot added the awaiting review label Sep 5, 2025
@bedevere-app

bedevere-app Bot commented Sep 5, 2025

Copy link
Copy Markdown

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

All reactions

Sorry, something went wrong.

Uh oh!

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

@bedevere-app bedevere-app Bot mentioned this pull request Sep 5, 2025
Optimize posixmodule.c:fill_time for typical timestamps #138535
Closed
eendebakpt
eendebakpt reviewed Sep 5, 2025
View reviewed changes
Comment thread Modules/posixmodule.c Resolved

Uh oh!

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

@eendebakpt eendebakpt added the performance Performance or resource usage label Sep 5, 2025
eendebakpt
eendebakpt reviewed Sep 5, 2025
View reviewed changes
Comment thread Modules/posixmodule.c Resolved

Uh oh!

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

eendebakpt
eendebakpt reviewed Sep 5, 2025
View reviewed changes
Comment thread Modules/posixmodule.c Resolved

Uh oh!

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

@jbosboom
Address review comments
6f05f25
@bedevere-app

bedevere-app Bot commented Sep 5, 2025

Copy link
Copy Markdown

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

All reactions

Sorry, something went wrong.

Uh oh!

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

@jbosboom
assert(!PyErr_Occurred()) only on success
bbab367
@jbosboom

jbosboom commented Sep 6, 2025 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Contributor Author

I want to add tests for timestamps just inside and outside the fast path to UtimeTests.test_large_time. Most but not all Linux filesystems support large timestamps. The direct way to check the filesystem type is calling statfs and comparing the f_type member to the magic numbers in man statfs. Unfortunately both sizeof(struct statfs) and sizeof(f_type) vary across different architectures, which makes it hard to call with ctypes. Is there precedent for adding a non-public Python interface to a Linux-specific C function just for test purposes? I didn't see anything about that in the devguide docs.

After some reflection, we can deal with varying struct statfs by simply overallocating by a lot. f_type is always the first 4 or 8 bytes of the structure (u32 or s64 [sic]). The magic numbers are all 2 or 4 bytes, and none of them are 0 or -1. Look at the first pair of u32s. If one of them is 0 or -1, the other is the magic (depending on architecture endianness). Otherwise the first (lowest address) u32 is the magic.

Another way is to parse /proc/self/mountinfo looking for the major:minor of the test file, but parsing that file is nontrivial because it is space-separated with fields that may contain spaces, has optional fields in the middle of lines, and has no documented escaping rules (see man proc_pid_mountinfo).

All reactions

Sorry, something went wrong.

Uh oh!

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

@jbosboom

jbosboom commented Sep 6, 2025

Copy link
Copy Markdown
Contributor Author

I don't think that checking large timestamp support using the filesystem magic number or name is actually that useful. I think tmpfs has supported 64-bit timestamps as long as the kernel VFS layer has. btrfs has always had 64-bit timestamps on-disk but I'm not sure they were plumbed in right away. The in-kernel NTFS driver should also have 64-bit timestamps, but I think most Linux NTFS users use the FUSE implementation ntfs-3g, and that will have the same magic number as other FUSE filesystems.

For the other common Linux filesystems we can't assume large timestamps. It's still possible to format ext4 with 32-bit timestamps, and anyway ext2 and ext3 use the same f_type magic number as ext4. xfs has only supported 64-bit timestamps since Linux 5.10.

I imagine most programs that care test for large timestamps by seeing if utimes and friends fails or stat returns a clamped timestamp ("Updated file timestamps are set to the greatest value supported by the filesystem that is not greater than the specified time." -- man utimensat). But obviously that can't be part of a test that os.stat properly handles large timestamps!

So, reviewers, would you be satisfied just testing this on Windows NTFS by adding a few timestamps to UtimeTests.test_large_time? fill_time only depends on time_t, and that should be a signed 64-bit type everywhere now.

All reactions

Sorry, something went wrong.

Uh oh!

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

@eendebakpt

eendebakpt commented Sep 6, 2025 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Contributor

For the tests I would prefer to keep it simple: just add some more cases above and below the fast path threshold. If needed add tests for both 32- and 64-bit.

There is a slight behavior change with this PR (I do not think it matters, but that is for someone else to judge): with current main if an error occurs anywhere, no changes are made to the struct sequence. In this PR it can happen that some changes are already made (e.g. s_index is set), and then an error occurs.

@jbosboom Could you add a news entry?

jbosboom reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

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

@AA-Turner
AA-Turner requested a review from vstinner September 6, 2025 23:00
jbosboom added 3 commits September 6, 2025 20:03
@jbosboom
Fix typo in fast path upper bound
1a9183c
@jbosboom
Add tests for boundaries of fast path
2c74007
@jbosboom
Add blurb
30d790f
vstinner
vstinner reviewed Sep 8, 2025
View reviewed changes
Comment thread Lib/test/test_os.py Resolved

Uh oh!

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

Comment thread Modules/posixmodule.c Resolved

Uh oh!

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

Comment thread Modules/posixmodule.c Resolved

Uh oh!

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

Comment thread Modules/posixmodule.c Resolved

Uh oh!

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

@jbosboom @vstinner
Apply suggestions from code review
be7d76f
Co-authored-by: Victor Stinner <[email protected]>
@vstinner

vstinner commented Sep 9, 2025

Copy link
Copy Markdown
Member

This improves python -m pyperf timeit -s 'import os' 'os.stat(".")' from 1.26 us +- 0.02 us to 1.15 us +- 0.01 us on Linux 6.16.2.arch1-1 btrfs and --enable-optimizations --with-lto.

I re-run the benchmark on Python built with ./configure (gcc -O3):

Mean +- std dev: [ref] 1.07 us +- 0.01 us -> [change] 867 ns +- 13 ns: 1.23x faster

Nice performance improvement!

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner
vstinner merged commit d4825ac into python:main Sep 9, 2025
@bedevere-app bedevere-app Bot removed the awaiting review label Sep 9, 2025
@vstinner

vstinner commented Sep 9, 2025

Copy link
Copy Markdown
Member

Merged, thanks for this nice optimization.

All reactions

Sorry, something went wrong.

Uh oh!

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

lkollar pushed a commit to lkollar/cpython that referenced this pull request Sep 9, 2025
@jbosboom @vstinner @lkollar
pythongh-138535: Optimize fill_time for typical timestamps (python#13…
9204500
…8537)

While file timestamps can be anything the file system can store, most
lie between the recent past and the near future.  Optimize fill_time()
for typical timestamps in three ways:

- When possible, convert to nanoseconds with C arithmetic.
- When using C arithmetic and the seconds member is not required (for
  st_birthtime), avoid creating a long object.
- When using C arithmetic, reorder the code to avoid the null checks
  implied in Py_XDECREF().

Co-authored-by: Victor Stinner <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@vstinner vstinner vstinner left review comments
@eendebakpt eendebakpt eendebakpt left review comments

Uh oh!

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

Assignees

No one assigned

Labels

performance Performance or resource usage

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

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

3 participants

@jbosboom @eendebakpt @vstinner
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.