gh-150716: Speed up timedelta construction for integer arguments#150718
Open
gaborbernat wants to merge 1 commit into
Open
gh-150716: Speed up timedelta construction for integer arguments#150718gaborbernat wants to merge 1 commit into
gaborbernat wants to merge 1 commit into
Conversation
7745883 to
5bbd195
Compare
timedelta() built its result through PyNumber arithmetic on Python ints plus two checked_divmod() calls, allocating a dozen temporary objects and doing a per-call module-state lookup even for the common all-integer case. Add delta_new_int_fastpath(): accumulate the total microseconds in a 64-bit integer with overflow guards, then normalize with floor division and hand the result to the existing new_delta_ex(). Non-exact-int arguments, 64-bit overflow, and out-of-range day counts fall through to the unchanged object path, so bool, float, int subclasses (including a custom __mul__) and bignums keep byte-identical results and errors.
5bbd195 to
92d33cd
Compare
Member
|
Can you please write a benchmark (ideally using pyperf)? |
Contributor
Author
|
Benchmark below, using Script: import pyperf
SETUP = "from datetime import timedelta"
CASES = {
"timedelta()": "timedelta()",
"timedelta(seconds=45)": "timedelta(seconds=45)",
"timedelta(days=7)": "timedelta(days=7)",
"timedelta(microseconds=123456)": "timedelta(microseconds=123456)",
"timedelta(days=2,h=3,m=4,s=5)": "timedelta(days=2, hours=3, minutes=4, seconds=5)",
"timedelta(days=-1,seconds=-1)": "timedelta(days=-1, seconds=-1)",
"timedelta(weeks=3)": "timedelta(weeks=3)",
"timedelta(seconds=1.5) # float/slow path": "timedelta(seconds=1.5)",
}
runner = pyperf.Runner()
for name, stmt in CASES.items():
runner.timeit(name=name, stmt=stmt, setup=SETUP)Results ( The integer cases run 2.0-3.5x faster, geometric mean 2.15x. The float argument keeps the original path and stays flat (1.01x is within noise). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Callers usually build
datetime.timedeltafrom whole numbers of seconds, minutes, or days, yet that common case runs through the same construction path as float and other arguments.This adds a direct path for whole-number arguments. Other inputs (float, bool, int subclasses, values too large to fit) keep the current behavior, so results and error messages stay the same.
Code that creates timedeltas in bulk gains the most: a pipeline turning a per-row second count into
timedelta(seconds=value)over millions of rows, a scheduler handing outtimedelta(minutes=n)to thousands of jobs, or retry logic computingtimedelta(seconds=2 ** attempt)in a loop.A
pyperfcomparison of base versus patched builds (script and full table in a comment below) shows the integer cases run 2.0 to 3.5x faster, geometric mean 2.15x, with the float path flat. A reference check over hundreds of thousands of argument combinations, including overflowing ones, found no differences. This follows thedate.today()fast path from gh-88473.Resolves #150716.