Skip to content

Commit db3b8a6

Browse files
committed
Defer formatting task name
The default task name is "Task-<counter>" (if no name is passed in during Task creation). This is initialized in `Task.__init__` (C impl) using string formatting, which can be quite slow. Actually using the task name in real world code is not very common, so this is wasted init. Let's defer this string formatting to the first time the name is read (in `get_name` impl), so we don't need to pay the string formatting cost if the task name is never read.
1 parent dca27a6 commit db3b8a6

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

Modules/_asynciomodule.c

+14-2
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ typedef struct {
129129
int task_must_cancel;
130130
int task_log_destroy_pending;
131131
int task_num_cancels_requested;
132+
uint64_t task_name_counter;
132133
} TaskObj;
133134

134135
typedef struct {
@@ -2065,12 +2066,16 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
20652066
self->task_must_cancel = 0;
20662067
self->task_log_destroy_pending = 1;
20672068
self->task_num_cancels_requested = 0;
2069+
self->task_name_counter = 0;
20682070
Py_INCREF(coro);
20692071
Py_XSETREF(self->task_coro, coro);
20702072

20712073
if (name == Py_None) {
2072-
name = PyUnicode_FromFormat("Task-%" PRIu64,
2073-
++state->task_name_counter);
2074+
// optimization: defer task name formatting
2075+
// set task_name to None to indicate deferred formatting, and
2076+
// store the task name counter for formatting in get_name impl
2077+
Py_INCREF(name);
2078+
self->task_name_counter = ++state->task_name_counter;
20742079
} else if (!PyUnicode_CheckExact(name)) {
20752080
name = PyObject_Str(name);
20762081
} else {
@@ -2448,6 +2453,13 @@ static PyObject *
24482453
_asyncio_Task_get_name_impl(TaskObj *self)
24492454
/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
24502455
{
2456+
if (Py_IsNone(self->task_name)) {
2457+
assert(self->task_name_counter > 0);
2458+
PyObject *name = PyUnicode_FromFormat(
2459+
"Task-%" PRIu64, self->task_name_counter);
2460+
Py_XSETREF(self->task_name, name);
2461+
return Py_NewRef(self->task_name);
2462+
}
24512463
if (self->task_name) {
24522464
return Py_NewRef(self->task_name);
24532465
}

0 commit comments

Comments
 (0)