Issue 32403: date, time and datetime alternate constructors should take fast construction path (original) (raw)

In the addition of the fromisoformat() alternate constructor (bpo-15873: https://github.com/python/cpython/pull/4699), I noted that I was able to get some significant speedup by special-casing the datetime baseclass in the C code so that it bypasses the Python constructor, by replacing code that looks like this:

return PyObject_CallFunction(cls, "iii", year, month, day);

With code that looks like this:

PyObject *result;
if ( (PyTypeObject *)cls == & PyDateTime_DateType ) {
    result = new_date_ex(year, month, day, (PyTypeObject *)cls);
} else {
    result = PyObject_CallFunction(cls, "iii", year, month, day);
}

return result;

(This is for date, but the results are even more striking for datetime).

In my initial proof of concept implementation of a new_date_subclass_ex method, I've seen (this is not compiled with optimizations on, mind you) speedups for the other constructors as well:

Old constructor:
================
Class: date
constructor:        940.5ns
date.fromordinal:   1544.8ns
date.fromtimestamp: 1941.9ns

Class: DateSubclass
constructor:        1016.6ns
date.fromordinal:   1760.3ns
date.fromtimestamp: 2295.3ns


With fastpath:
==============
Class: date
constructor:        964.3ns
date.fromordinal:   997.6ns
date.fromtimestamp: 1130.2ns

Class: DateSubclass
constructor:        1086.9ns
date.fromordinal:   1818.5ns
date.fromtimestamp: 2129.9ns

As you can see, this is a fairly significant speedup in the common case with no cost in the unusual case and no change in behavior. I propose that we switch over all the C constructors where it makes sense to do so in date, time and datetime.

I'll have a PR forthcoming soon.