Repository navigation
date.today() is half as fast as datetime.now().date() #88473
Description
Activity
$ python3.10 -m timeit -s 'from datetime import datetime' 'datetime.now().date()' 500000 loops, best of 5: 708 nsec per loop $ python3.10 -m timeit -s 'from datetime import date' 'date.today()' 200000 loops, best of 5: 1.4 usec per loop
this surprised me so I dug into it -- it appears a fast path can be added to
date.today()to make it faster thandatetime.date.now()-- though I'm rather unfamiliar with the functions involved herehere is my ~sloppy patch attempting to add a fast path, I would need some guidance to improve it and get it accepted:
$ git diff -w diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 8ef2dad37a..7eaa5d1740 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -2875,6 +2875,17 @@ date_fromtimestamp(PyObject *cls, PyObject *obj) static PyObject * date_today(PyObject *cls, PyObject *dummy) { + /* fast path, don't call fromtimestamp */ + if ((PyTypeObject *)cls == &PyDateTime_DateType) { + struct tm tm; + time_t t; + time(&t); + localtime_r(&t, &tm); + return new_date_ex(tm.tm_year + 1900, + tm.tm_mon + 1, + tm.tm_mday, + (PyTypeObject*)cls); + } else { PyObject *time; PyObject *result; _Py_IDENTIFIER(fromtimestamp); @@ -2893,6 +2904,7 @@ date_today(PyObject *cls, PyObject *dummy) Py_DECREF(time); return result; } +} /*[clinic input] @classmethod
after this,
date.today()is faster!$ ./python -m timeit -s 'from datetime import datetime' 'datetime.now().date()' 500000 loops, best of 5: 764 nsec per loop $ ./python -m timeit -s 'from datetime import date' 'date.today()' 500000 loops, best of 5: 407 nsec per loop
\o/
- added3.11only security fixesonly security fixesextension-modulesC modules in the Modules dirC modules in the Modules dirperformancePerformance or resource usagePerformance or resource usage
on Jun 4, 2021 Yeah, I knew this was slower and it's been on my long list to look at it (tied to this is the fact that
datetime.today()is basically just a slow version ofdatetime.now(), in defiance of user expectations).My inclination is that we shouldn't re-implement
fromtimestampindate.today, but rather calldate_fromtimestampin the fast path. I believe that incurs the overhead of creating one additional Python object (an integer), but if it's a sufficiently significant speedup, we could possibly refactordate_fromtimestampto a version that accepts a C integer and a version that accepts a Python integer, then call the version accepting a C integer.I think this won't give any speedup to
datetime.today, sincedatetime.todaywill still take the slow path. If we care about this, we may be able to implementdatetime.todayas an alias fordatetime.now(None), assuming there are no behavioral differences between the two.- changed the title
[-]date.today() is 2x slower than datetime.now().date()[/-][+]date.today() is half as fast as datetime.now().date()[/+]on Jun 4, 2021 - changed the title
[-]date.today() is 2x slower than datetime.now().date()[/-][+]date.today() is half as fast as datetime.now().date()[/+]on Jun 4, 2021 @terry.reddy -- I believe your title change makes this more difficult to understand
*terry.reedy oops typo!
2 remaining items
- addedtype-featureA feature request or enhancementA feature request or enhancementand removed3.12only security fixesonly security fixes
on Mar 8, 2025 @pganssle do we want to backport?
- addedinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)pendingThe issue will be closed if no feedback is providedThe issue will be closed if no feedback is providedand removedinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)
on Sep 16, 2025 - removedpendingThe issue will be closed if no feedback is providedThe issue will be closed if no feedback is provided
on Sep 16, 2025 Performance improvements are usually not backported if they are considered new features. I would see this as a feature rather than a bugfix.
Reacted by Paul GanssleThat was my thinking.
Interesting, the issue still exist with CPython 3.14.4:
python -m timeit -s 'from datetime import datetime' 'datetime.now().date()'
Provides the following outpt:
500000 loops, best of 5: 416 nsec per loopWhile this code:
python -m timeit -s 'from datetime import date' 'date.today()'
Gives the following output:
500000 loops, best of 5: 834 nsec per loopSo the ratio still holds.
That's because it didn't make it into 3.14, in 3.15/6:
$ ./python -m timeit -s 'from datetime import datetime' 'datetime.now().date()' 500000 loops, best of 5: 502 nsec per loop $ ./python -m timeit -s 'from datetime import date' 'date.today()' 1000000 loops, best of 5: 269 nsec per loop $ ./python --version Python 3.16.0a0Reacted by AskicVThanks Stan, I missed that.
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsDone
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
Linked PRs