Skip to content

C implementation for strptime #158252

Description

@pganssle

Feature or enhancement

Proposal:

I have long known that dt.strptime is very slow, despite being an extremely commonly used function. This is basically because it is written in Python. If you for example compare datetime.fromisoformat (C) to datetime.strptime (Python) for parsing "2024-02-29T12:34:56.123456+05:30", strptime takes about 39× as long to produce the same result:

Method Time per call
datetime.strptime 3.43 µs
datetime.fromisoformat 88.5 ns
Reproducer
python -m timeit -s 'import datetime; import _strptime' \
  'datetime.datetime.strptime("2024-02-29T12:34:56.123456+05:30", "%Y-%m-%dT%H:%M:%S.%f%z")'
python -m timeit -s 'import datetime' \
  'datetime.datetime.fromisoformat("2024-02-29T12:34:56.123456+05:30")'

Ages ago, I suggested this to @StanFromIreland as something to do with a Claude subscription that he had gotten and he produced this experiment, which had some real improvements, (~2x faster), but was clearly bottlenecking on some sort of round trip through Python. (Expand below for benchmarks)

Benchmarks
FAST PATH
Format                                C direct     Python   Combined  Speedup
%Y-%m-%d (date only)                     491ns     8419ns     4352ns     1.9x
%Y-%m-%d %H:%M:%S (datetime)             549ns    11903ns     4430ns     2.7x
%F (compound date)                       477ns     8993ns     4129ns     2.2x
%T (compound time)                       523ns     9679ns     4158ns     2.3x
%H:%M:%S (time)                          517ns     9737ns     4329ns     2.2x
datetime+microseconds                    529ns    13351ns     4216ns     3.2x
datetime+tz offset                       569ns    15485ns     4502ns     3.4x
datetime+tz colon                        551ns    17058ns     4360ns     3.9x
year+julian day                          512ns     9173ns     4309ns     2.1x
year+week+weekday                        535ns    11619ns     4191ns     2.8x
year+week(Mon)+weekday                   548ns    11475ns     4257ns     2.7x
compact date                             464ns     8803ns     4278ns     2.1x
EU date format                           522ns    10643ns     4207ns     2.5x
ISO week date                            533ns    11057ns     4178ns     2.6x
2-digit year only                        487ns     7396ns     4118ns     1.8x
2-digit year (1900s)                     485ns     7330ns     4106ns     1.8x

FALLBACK PATH
Format                                  Python   w/ C try   Overhead
%b (abbrev month)                       9299ns     9466ns      1.8%
%B (full month)                         9465ns     9425ns     -0.4%
default ctime format                   13074ns    13131ns      0.4%
%A (full weekday name)                  7917ns     8080ns      2.1%
%I+%p (12-hour+AM/PM)                  11701ns    11709ns      0.1%
%Z (timezone name)                      9539ns     9461ns     -0.8%

I recently had ChatGPT 6.0 take another crack at it (I'm sure Claude also would be able to do the same I just happened to be using ChatGPT 6.0), specifically telling it to make sure to avoid doubling back into Python and it produced something more consistent with fromisoformat. fromisoformat() gives 88.5ns but and the fully-C fast path gives 121ns for the same format as above. I will send a PR with more extensive benchmarks, but I figured I would create this bug to track an effort to speed up strptime in case that one withers.

Overall it's adding complexity, but this is a pretty significant speed-up for a very common function, I think it's going to be worth doing.

Has this already been discussed elsewhere?

This is a minor feature, which does not need previous discussion elsewhere

Links to previous discussion of this feature:

No response

Linked PRs

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirtype-featureA feature request or enhancement

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions