Skip to content

Commit abb1542

Browse files
authored
gh-109181: Speed up Traceback object creation by lazily compute the line number (#111548)
Signed-off-by: Pablo Galindo <[email protected]>
1 parent ad6380b commit abb1542

File tree

2 files changed

+31
-6
lines changed

2 files changed

+31
-6
lines changed
Lines changed: 2 additions & 0 deletions
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

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,26 @@ tb_next_get(PyTracebackObject *self, void *Py_UNUSED(_))
109109
return Py_NewRef(ret);
110110
}
111111

112+
static int
113+
tb_get_lineno(PyTracebackObject* tb) {
114+
_PyInterpreterFrame* frame = tb->tb_frame->f_frame;
115+
assert(frame != NULL);
116+
return PyCode_Addr2Line(_PyFrame_GetCode(frame), tb->tb_lasti);
117+
}
118+
119+
static PyObject *
120+
tb_lineno_get(PyTracebackObject *self, void *Py_UNUSED(_))
121+
{
122+
int lineno = self->tb_lineno;
123+
if (lineno == -1) {
124+
lineno = tb_get_lineno(self);
125+
if (lineno < 0) {
126+
Py_RETURN_NONE;
127+
}
128+
}
129+
return PyLong_FromLong(lineno);
130+
}
131+
112132
static int
113133
tb_next_set(PyTracebackObject *self, PyObject *new_next, void *Py_UNUSED(_))
114134
{
@@ -152,12 +172,12 @@ static PyMethodDef tb_methods[] = {
152172
static PyMemberDef tb_memberlist[] = {
153173
{"tb_frame", _Py_T_OBJECT, OFF(tb_frame), Py_READONLY|Py_AUDIT_READ},
154174
{"tb_lasti", Py_T_INT, OFF(tb_lasti), Py_READONLY},
155-
{"tb_lineno", Py_T_INT, OFF(tb_lineno), Py_READONLY},
156175
{NULL} /* Sentinel */
157176
};
158177

159178
static PyGetSetDef tb_getsetters[] = {
160179
{"tb_next", (getter)tb_next_get, (setter)tb_next_set, NULL, NULL},
180+
{"tb_lineno", (getter)tb_lineno_get, NULL, NULL, NULL},
161181
{NULL} /* Sentinel */
162182
};
163183

@@ -236,8 +256,7 @@ _PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame)
236256
assert(tb_next == NULL || PyTraceBack_Check(tb_next));
237257
assert(frame != NULL);
238258
int addr = _PyInterpreterFrame_LASTI(frame->f_frame) * sizeof(_Py_CODEUNIT);
239-
return tb_create_raw((PyTracebackObject *)tb_next, frame, addr,
240-
PyFrame_GetLineNumber(frame));
259+
return tb_create_raw((PyTracebackObject *)tb_next, frame, addr, -1);
241260
}
242261

243262

@@ -681,23 +700,27 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
681700
}
682701
while (tb != NULL) {
683702
code = PyFrame_GetCode(tb->tb_frame);
703+
int tb_lineno = tb->tb_lineno;
704+
if (tb_lineno == -1) {
705+
tb_lineno = tb_get_lineno(tb);
706+
}
684707
if (last_file == NULL ||
685708
code->co_filename != last_file ||
686-
last_line == -1 || tb->tb_lineno != last_line ||
709+
last_line == -1 || tb_lineno != last_line ||
687710
last_name == NULL || code->co_name != last_name) {
688711
if (cnt > TB_RECURSIVE_CUTOFF) {
689712
if (tb_print_line_repeated(f, cnt) < 0) {
690713
goto error;
691714
}
692715
}
693716
last_file = code->co_filename;
694-
last_line = tb->tb_lineno;
717+
last_line = tb_lineno;
695718
last_name = code->co_name;
696719
cnt = 0;
697720
}
698721
cnt++;
699722
if (cnt <= TB_RECURSIVE_CUTOFF) {
700-
if (tb_displayline(tb, f, code->co_filename, tb->tb_lineno,
723+
if (tb_displayline(tb, f, code->co_filename, tb_lineno,
701724
tb->tb_frame, code->co_name) < 0) {
702725
goto error;
703726
}

0 commit comments

Comments
 (0)