Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Optimize fill_time for typical timestamps
While file timestamps can be anything the file system can store, most
lie between the recent past and the near future.  Optimize fill_time for
typical timestamps in three ways:

- When possible, convert to nanoseconds with C arithmetic.
- When using C arithmetic and the seconds member is not required (for
  st_birthtime), avoid creating a long object.
- When using C arithmetic, reorder the code to avoid the null checks
  implied in Py_XDECREF.
  • Loading branch information
jbosboom committed Sep 5, 2025
commit a92719dfee57f0b7cc22c4da7362cf20af8dc992
46 changes: 34 additions & 12 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2588,12 +2588,43 @@ static int
fill_time(PyObject *module, PyObject *v, int s_index, int f_index, int ns_index, time_t sec, unsigned long nsec)
{
assert(!PyErr_Occurred());
#define S_TO_NS (1000000000LL)
Comment thread
jbosboom marked this conversation as resolved.
Outdated
assert(nsec < S_TO_NS);

if (f_index >= 0) {
PyObject *float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
Comment thread
jbosboom marked this conversation as resolved.
Outdated
if (!float_s) {
return -1;
}
PyStructSequence_SET_ITEM(v, f_index, float_s);
}

/* 1677-09-21 00:12:44 to 2262-04-11 23:47:15 UTC inclusive */
if ((LLONG_MIN / S_TO_NS) <= sec && sec <= (LONG_MAX / S_TO_NS - 1)) {
if (s_index >= 0) {
PyObject *s = _PyLong_FromTime_t(sec);
if (!s) {
return -1;
}
PyStructSequence_SET_ITEM(v, s_index, s);
}
Comment thread
jbosboom marked this conversation as resolved.
Outdated

if (ns_index >= 0) {
PyObject *ns_total = PyLong_FromLongLong(sec * S_TO_NS + nsec);
if (!ns_total) {
return -1;
}
PyStructSequence_SET_ITEM(v, ns_index, ns_total);
}

assert(!PyErr_Occurred());
return 0;
}
#undef S_TO_NS

int res = -1;
PyObject *s_in_ns = NULL;
PyObject *ns_total = NULL;
PyObject *float_s = NULL;

PyObject *s = _PyLong_FromTime_t(sec);
PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
if (!(s && ns_fractional)) {
Expand All @@ -2606,22 +2637,14 @@ fill_time(PyObject *module, PyObject *v, int s_index, int f_index, int ns_index,
}

ns_total = PyNumber_Add(s_in_ns, ns_fractional);
Comment thread
jbosboom marked this conversation as resolved.
Outdated
if (!ns_total)
goto exit;

float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
if (!float_s) {
if (!ns_total) {
goto exit;
}

if (s_index >= 0) {
PyStructSequence_SET_ITEM(v, s_index, s);
s = NULL;
}
if (f_index >= 0) {
PyStructSequence_SET_ITEM(v, f_index, float_s);
float_s = NULL;
}
if (ns_index >= 0) {
PyStructSequence_SET_ITEM(v, ns_index, ns_total);
ns_total = NULL;
Expand All @@ -2635,7 +2658,6 @@ fill_time(PyObject *module, PyObject *v, int s_index, int f_index, int ns_index,
Py_XDECREF(ns_fractional);
Py_XDECREF(s_in_ns);
Py_XDECREF(ns_total);
Py_XDECREF(float_s);
return res;
}

Expand Down
Loading