Skip to content

gh-148085: datetime cache time module lookups#148088

Open
maurycy wants to merge 6 commits intopython:mainfrom
maurycy:datetime-cache-time-module-lookups
Open

gh-148085: datetime cache time module lookups#148088
maurycy wants to merge 6 commits intopython:mainfrom
maurycy:datetime-cache-time-module-lookups

Conversation

@maurycy
Copy link
Copy Markdown
Contributor

@maurycy maurycy commented Apr 4, 2026

See gh-148085 for more details.

This takes a lazy approach, in the spirit of lazy, instead of preloading in init_state(). The trade-off is decreased readability.

Please see Links to previous discussion of this feature section in the gh-148085. My understanding is that only @ericsnowcurrently's work in gh-119810 made this possible and clean.

Benchmark

Benchmark main-c50d6cd datetime-cache-time-module-lookups-ae32bfd
datetime.timetuple 260 ns 124 ns: 2.10x faster
datetime.strftime 784 ns 517 ns: 1.52x faster
date.timetuple 258 ns 124 ns: 2.08x faster
Geometric mean (ref) 1.88x faster

For:

import pyperf, datetime

r = pyperf.Runner()
dt = datetime.datetime(2026, 4, 4, 12, 30, 45)
d = datetime.date(2026, 4, 4)

r.bench_func("datetime.timetuple", dt.timetuple)
r.bench_func("datetime.strftime", dt.strftime, "%Y-%m-%d")
r.bench_func("date.timetuple", d.timetuple)

For:

2026-04-04T14:17:02.794335000+0200 maurycy@gimel /Users/maurycy/work/cpython-main (main c50d6cd) % ./python.exe -c "import sysconfig; print(sysconfig.get_config_var('CONFIG_ARGS'))"
'--enable-optimizations' '--with-lto'
[127] 2026-04-04T14:17:24.011667000+0200 maurycy@gimel /Users/maurycy/src/github.com/maurycy/cpython (datetime-cache-time-module-lookups a49f862) % ./python.exe -c "import sysconfig; print(sysconfig.get_config_var('CONFIG_ARGS'))"
'--enable-optimizations' '--with-lto'

Copy link
Copy Markdown
Member

@StanFromIreland StanFromIreland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have a precedent for lazy caching, I think it's always eager? I'm worried this might cause issues, historically datetime and caching hasn't worked out.

@maurycy
Copy link
Copy Markdown
Contributor Author

maurycy commented Apr 4, 2026

@StanFromIreland We do:

https://github.com/python/cpython/blob/dea4083aa95/Modules/arraymodule.c#L2561

https://github.com/python/cpython/blob/dea4083aa95/Modules/_decimal/_decimal.c#L3699

I copied my approach from there. I'm OK with moving to init_state(), somehow PEP 810 set the tone.

I believe the reason why it didn't work is that it relied on a global variable, instead of per-interpreter module. I left a note in #148085 in the previous discussions feature section.

return NULL;
}
if (st->time_time == NULL) {
st->time_time = PyImport_ImportModuleAttrString("time", "time");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking more about this, I think we could just replace this with a call to PyTime_Time directly, I assume this predates the existence of the C-API.

@picnixz
Copy link
Copy Markdown
Member

picnixz commented Apr 4, 2026

I remember there were issues with datetime and the capsule API so be careful there. Likewise, if you do per-state caching, it may break existing hooks (removing the module from sys.modules will not make it reload I think)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants