Skip to content

Commit a92719d

Browse files
committed
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.
1 parent d1d8409 commit a92719d

File tree

1 file changed

+34
-12
lines changed

1 file changed

+34
-12
lines changed

Modules/posixmodule.c

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2588,12 +2588,43 @@ static int
25882588
fill_time(PyObject *module, PyObject *v, int s_index, int f_index, int ns_index, time_t sec, unsigned long nsec)
25892589
{
25902590
assert(!PyErr_Occurred());
2591+
#define S_TO_NS (1000000000LL)
2592+
assert(nsec < S_TO_NS);
2593+
2594+
if (f_index >= 0) {
2595+
PyObject *float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2596+
if (!float_s) {
2597+
return -1;
2598+
}
2599+
PyStructSequence_SET_ITEM(v, f_index, float_s);
2600+
}
2601+
2602+
/* 1677-09-21 00:12:44 to 2262-04-11 23:47:15 UTC inclusive */
2603+
if ((LLONG_MIN / S_TO_NS) <= sec && sec <= (LONG_MAX / S_TO_NS - 1)) {
2604+
if (s_index >= 0) {
2605+
PyObject *s = _PyLong_FromTime_t(sec);
2606+
if (!s) {
2607+
return -1;
2608+
}
2609+
PyStructSequence_SET_ITEM(v, s_index, s);
2610+
}
2611+
2612+
if (ns_index >= 0) {
2613+
PyObject *ns_total = PyLong_FromLongLong(sec * S_TO_NS + nsec);
2614+
if (!ns_total) {
2615+
return -1;
2616+
}
2617+
PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2618+
}
2619+
2620+
assert(!PyErr_Occurred());
2621+
return 0;
2622+
}
2623+
#undef S_TO_NS
25912624

25922625
int res = -1;
25932626
PyObject *s_in_ns = NULL;
25942627
PyObject *ns_total = NULL;
2595-
PyObject *float_s = NULL;
2596-
25972628
PyObject *s = _PyLong_FromTime_t(sec);
25982629
PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
25992630
if (!(s && ns_fractional)) {
@@ -2606,22 +2637,14 @@ fill_time(PyObject *module, PyObject *v, int s_index, int f_index, int ns_index,
26062637
}
26072638

26082639
ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2609-
if (!ns_total)
2610-
goto exit;
2611-
2612-
float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2613-
if (!float_s) {
2640+
if (!ns_total) {
26142641
goto exit;
26152642
}
26162643

26172644
if (s_index >= 0) {
26182645
PyStructSequence_SET_ITEM(v, s_index, s);
26192646
s = NULL;
26202647
}
2621-
if (f_index >= 0) {
2622-
PyStructSequence_SET_ITEM(v, f_index, float_s);
2623-
float_s = NULL;
2624-
}
26252648
if (ns_index >= 0) {
26262649
PyStructSequence_SET_ITEM(v, ns_index, ns_total);
26272650
ns_total = NULL;
@@ -2635,7 +2658,6 @@ fill_time(PyObject *module, PyObject *v, int s_index, int f_index, int ns_index,
26352658
Py_XDECREF(ns_fractional);
26362659
Py_XDECREF(s_in_ns);
26372660
Py_XDECREF(ns_total);
2638-
Py_XDECREF(float_s);
26392661
return res;
26402662
}
26412663

0 commit comments

Comments
 (0)