Skip to content

Commit db3d5b3

Browse files
committed
[3.12] gh-109181: Speed up Traceback object creation by lazily compute the line number (GH-111548)
Signed-off-by: Pablo Galindo <[email protected]>. (cherry picked from commit abb1542) Co-authored-by: Pablo Galindo Salgado <[email protected]> Signed-off-by: Pablo Galindo <[email protected]>
1 parent dde5a99 commit db3d5b3

File tree

2 files changed

+31
-14
lines changed

2 files changed

+31
-14
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Speed up :obj:`Traceback` object creation by lazily compute the line number.
2+
Patch by Pablo Galindo

Python/traceback.c

+29-14
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,26 @@ tb_next_get(PyTracebackObject *self, void *Py_UNUSED(_))
107107
return Py_NewRef(ret);
108108
}
109109

110+
static int
111+
tb_get_lineno(PyTracebackObject* tb) {
112+
PyFrameObject* frame = tb->tb_frame;
113+
assert(frame != NULL);
114+
return PyCode_Addr2Line(PyFrame_GetCode(frame), tb->tb_lasti);
115+
}
116+
117+
static PyObject *
118+
tb_lineno_get(PyTracebackObject *self, void *Py_UNUSED(_))
119+
{
120+
int lineno = self->tb_lineno;
121+
if (lineno == -1) {
122+
lineno = tb_get_lineno(self);
123+
if (lineno < 0) {
124+
Py_RETURN_NONE;
125+
}
126+
}
127+
return PyLong_FromLong(lineno);
128+
}
129+
110130
static int
111131
tb_next_set(PyTracebackObject *self, PyObject *new_next, void *Py_UNUSED(_))
112132
{
@@ -150,12 +170,12 @@ static PyMethodDef tb_methods[] = {
150170
static PyMemberDef tb_memberlist[] = {
151171
{"tb_frame", T_OBJECT, OFF(tb_frame), READONLY|PY_AUDIT_READ},
152172
{"tb_lasti", T_INT, OFF(tb_lasti), READONLY},
153-
{"tb_lineno", T_INT, OFF(tb_lineno), READONLY},
154173
{NULL} /* Sentinel */
155174
};
156175

157176
static PyGetSetDef tb_getsetters[] = {
158177
{"tb_next", (getter)tb_next_get, (setter)tb_next_set, NULL, NULL},
178+
{"tb_lineno", (getter)tb_lineno_get, NULL, NULL, NULL},
159179
{NULL} /* Sentinel */
160180
};
161181

@@ -234,8 +254,7 @@ _PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame)
234254
assert(tb_next == NULL || PyTraceBack_Check(tb_next));
235255
assert(frame != NULL);
236256
int addr = _PyInterpreterFrame_LASTI(frame->f_frame) * sizeof(_Py_CODEUNIT);
237-
return tb_create_raw((PyTracebackObject *)tb_next, frame, addr,
238-
PyFrame_GetLineNumber(frame));
257+
return tb_create_raw((PyTracebackObject *)tb_next, frame, addr, -1);
239258
}
240259

241260

@@ -983,34 +1002,30 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit,
9831002
}
9841003
while (tb != NULL) {
9851004
code = PyFrame_GetCode(tb->tb_frame);
1005+
int tb_lineno = tb->tb_lineno;
1006+
if (tb_lineno == -1) {
1007+
tb_lineno = tb_get_lineno(tb);
1008+
}
9861009
if (last_file == NULL ||
9871010
code->co_filename != last_file ||
988-
last_line == -1 || tb->tb_lineno != last_line ||
1011+
last_line == -1 || tb_lineno != last_line ||
9891012
last_name == NULL || code->co_name != last_name) {
9901013
if (cnt > TB_RECURSIVE_CUTOFF) {
9911014
if (tb_print_line_repeated(f, cnt) < 0) {
9921015
goto error;
9931016
}
9941017
}
9951018
last_file = code->co_filename;
996-
last_line = tb->tb_lineno;
1019+
last_line = tb_lineno;
9971020
last_name = code->co_name;
9981021
cnt = 0;
9991022
}
10001023
cnt++;
10011024
if (cnt <= TB_RECURSIVE_CUTOFF) {
1002-
if (tb_displayline(tb, f, code->co_filename, tb->tb_lineno,
1025+
if (tb_displayline(tb, f, code->co_filename, tb_lineno,
10031026
tb->tb_frame, code->co_name, indent, margin) < 0) {
1004-
goto error;
10051027
}
10061028

1007-
if (PyErr_CheckSignals() < 0) {
1008-
goto error;
1009-
}
1010-
}
1011-
Py_CLEAR(code);
1012-
tb = tb->tb_next;
1013-
}
10141029
if (cnt > TB_RECURSIVE_CUTOFF) {
10151030
if (tb_print_line_repeated(f, cnt) < 0) {
10161031
goto error;

0 commit comments

Comments
 (0)