mirror of
https://github.com/python/cpython.git
synced 2025-08-31 05:58:33 +00:00
gh-107674: Improve performance of sys.settrace
(GH-117133)
* Check tracing in RESUME_CHECK * Only change to RESUME_CHECK if not tracing
This commit is contained in:
parent
998c3856c1
commit
9c14ed0618
7 changed files with 63 additions and 52 deletions
|
@ -0,0 +1 @@
|
||||||
|
Improved the performance of :func:`sys.settrace` significantly
|
|
@ -148,20 +148,18 @@ dummy_func(
|
||||||
|
|
||||||
tier1 inst(RESUME, (--)) {
|
tier1 inst(RESUME, (--)) {
|
||||||
assert(frame == tstate->current_frame);
|
assert(frame == tstate->current_frame);
|
||||||
uintptr_t global_version =
|
if (tstate->tracing == 0) {
|
||||||
_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) &
|
uintptr_t global_version =
|
||||||
~_PY_EVAL_EVENTS_MASK;
|
_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) &
|
||||||
PyCodeObject *code = _PyFrame_GetCode(frame);
|
~_PY_EVAL_EVENTS_MASK;
|
||||||
uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(code->_co_instrumentation_version);
|
PyCodeObject* code = _PyFrame_GetCode(frame);
|
||||||
assert((code_version & 255) == 0);
|
uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(code->_co_instrumentation_version);
|
||||||
if (code_version != global_version) {
|
assert((code_version & 255) == 0);
|
||||||
int err = _Py_Instrument(code, tstate->interp);
|
if (code_version != global_version) {
|
||||||
ERROR_IF(err, error);
|
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
|
||||||
next_instr = this_instr;
|
ERROR_IF(err, error);
|
||||||
}
|
next_instr = this_instr;
|
||||||
else {
|
DISPATCH();
|
||||||
if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) {
|
|
||||||
CHECK_EVAL_BREAKER();
|
|
||||||
}
|
}
|
||||||
assert(this_instr->op.code == RESUME ||
|
assert(this_instr->op.code == RESUME ||
|
||||||
this_instr->op.code == RESUME_CHECK ||
|
this_instr->op.code == RESUME_CHECK ||
|
||||||
|
@ -173,6 +171,9 @@ dummy_func(
|
||||||
#endif /* ENABLE_SPECIALIZATION */
|
#endif /* ENABLE_SPECIALIZATION */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) {
|
||||||
|
CHECK_EVAL_BREAKER();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(RESUME_CHECK, (--)) {
|
inst(RESUME_CHECK, (--)) {
|
||||||
|
@ -189,7 +190,7 @@ dummy_func(
|
||||||
inst(INSTRUMENTED_RESUME, (--)) {
|
inst(INSTRUMENTED_RESUME, (--)) {
|
||||||
uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK;
|
uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK;
|
||||||
uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version);
|
uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version);
|
||||||
if (code_version != global_version) {
|
if (code_version != global_version && tstate->tracing == 0) {
|
||||||
if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) {
|
if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) {
|
||||||
ERROR_NO_POP();
|
ERROR_NO_POP();
|
||||||
}
|
}
|
||||||
|
@ -4284,7 +4285,7 @@ dummy_func(
|
||||||
#endif
|
#endif
|
||||||
uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker);
|
uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker);
|
||||||
DEOPT_IF(eval_breaker & _PY_EVAL_EVENTS_MASK);
|
DEOPT_IF(eval_breaker & _PY_EVAL_EVENTS_MASK);
|
||||||
assert(eval_breaker == FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version));
|
assert(tstate->tracing || eval_breaker == FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version));
|
||||||
}
|
}
|
||||||
|
|
||||||
// END BYTECODES //
|
// END BYTECODES //
|
||||||
|
|
|
@ -808,17 +808,23 @@ resume_frame:
|
||||||
{
|
{
|
||||||
_Py_CODEUNIT *prev = frame->instr_ptr;
|
_Py_CODEUNIT *prev = frame->instr_ptr;
|
||||||
_Py_CODEUNIT *here = frame->instr_ptr = next_instr;
|
_Py_CODEUNIT *here = frame->instr_ptr = next_instr;
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
int original_opcode = 0;
|
||||||
int original_opcode = _Py_call_instrumentation_line(
|
if (tstate->tracing) {
|
||||||
tstate, frame, here, prev);
|
PyCodeObject *code = _PyFrame_GetCode(frame);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
original_opcode = code->_co_monitoring->lines[(int)(here - _PyCode_CODE(code))].original_opcode;
|
||||||
if (original_opcode < 0) {
|
} else {
|
||||||
next_instr = here+1;
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
goto error;
|
original_opcode = _Py_call_instrumentation_line(
|
||||||
}
|
tstate, frame, here, prev);
|
||||||
next_instr = frame->instr_ptr;
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
if (next_instr != here) {
|
if (original_opcode < 0) {
|
||||||
DISPATCH();
|
next_instr = here+1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
next_instr = frame->instr_ptr;
|
||||||
|
if (next_instr != here) {
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (_PyOpcode_Caches[original_opcode]) {
|
if (_PyOpcode_Caches[original_opcode]) {
|
||||||
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)(next_instr+1);
|
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)(next_instr+1);
|
||||||
|
|
|
@ -358,12 +358,16 @@ do { \
|
||||||
// for an exception handler, displaying the traceback, and so on
|
// for an exception handler, displaying the traceback, and so on
|
||||||
#define INSTRUMENTED_JUMP(src, dest, event) \
|
#define INSTRUMENTED_JUMP(src, dest, event) \
|
||||||
do { \
|
do { \
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer); \
|
if (tstate->tracing) {\
|
||||||
next_instr = _Py_call_instrumentation_jump(tstate, event, frame, src, dest); \
|
next_instr = dest; \
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame); \
|
} else { \
|
||||||
if (next_instr == NULL) { \
|
_PyFrame_SetStackPointer(frame, stack_pointer); \
|
||||||
next_instr = (dest)+1; \
|
next_instr = _Py_call_instrumentation_jump(tstate, event, frame, src, dest); \
|
||||||
goto error; \
|
stack_pointer = _PyFrame_GetStackPointer(frame); \
|
||||||
|
if (next_instr == NULL) { \
|
||||||
|
next_instr = (dest)+1; \
|
||||||
|
goto error; \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
|
|
2
Python/executor_cases.c.h
generated
2
Python/executor_cases.c.h
generated
|
@ -4346,7 +4346,7 @@
|
||||||
UOP_STAT_INC(uopcode, miss);
|
UOP_STAT_INC(uopcode, miss);
|
||||||
JUMP_TO_JUMP_TARGET();
|
JUMP_TO_JUMP_TARGET();
|
||||||
}
|
}
|
||||||
assert(eval_breaker == FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version));
|
assert(tstate->tracing || eval_breaker == FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
31
Python/generated_cases.c.h
generated
31
Python/generated_cases.c.h
generated
|
@ -3292,7 +3292,7 @@
|
||||||
INSTRUCTION_STATS(INSTRUMENTED_RESUME);
|
INSTRUCTION_STATS(INSTRUMENTED_RESUME);
|
||||||
uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK;
|
uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK;
|
||||||
uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version);
|
uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version);
|
||||||
if (code_version != global_version) {
|
if (code_version != global_version && tstate->tracing == 0) {
|
||||||
if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) {
|
if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -4948,20 +4948,18 @@
|
||||||
_Py_CODEUNIT *this_instr = next_instr - 1;
|
_Py_CODEUNIT *this_instr = next_instr - 1;
|
||||||
(void)this_instr;
|
(void)this_instr;
|
||||||
assert(frame == tstate->current_frame);
|
assert(frame == tstate->current_frame);
|
||||||
uintptr_t global_version =
|
if (tstate->tracing == 0) {
|
||||||
_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) &
|
uintptr_t global_version =
|
||||||
~_PY_EVAL_EVENTS_MASK;
|
_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) &
|
||||||
PyCodeObject *code = _PyFrame_GetCode(frame);
|
~_PY_EVAL_EVENTS_MASK;
|
||||||
uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(code->_co_instrumentation_version);
|
PyCodeObject* code = _PyFrame_GetCode(frame);
|
||||||
assert((code_version & 255) == 0);
|
uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(code->_co_instrumentation_version);
|
||||||
if (code_version != global_version) {
|
assert((code_version & 255) == 0);
|
||||||
int err = _Py_Instrument(code, tstate->interp);
|
if (code_version != global_version) {
|
||||||
if (err) goto error;
|
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
|
||||||
next_instr = this_instr;
|
if (err) goto error;
|
||||||
}
|
next_instr = this_instr;
|
||||||
else {
|
DISPATCH();
|
||||||
if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) {
|
|
||||||
CHECK_EVAL_BREAKER();
|
|
||||||
}
|
}
|
||||||
assert(this_instr->op.code == RESUME ||
|
assert(this_instr->op.code == RESUME ||
|
||||||
this_instr->op.code == RESUME_CHECK ||
|
this_instr->op.code == RESUME_CHECK ||
|
||||||
|
@ -4973,6 +4971,9 @@
|
||||||
#endif /* ENABLE_SPECIALIZATION */
|
#endif /* ENABLE_SPECIALIZATION */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) {
|
||||||
|
CHECK_EVAL_BREAKER();
|
||||||
|
}
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1217,15 +1217,13 @@ int
|
||||||
_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev)
|
_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev)
|
||||||
{
|
{
|
||||||
PyCodeObject *code = _PyFrame_GetCode(frame);
|
PyCodeObject *code = _PyFrame_GetCode(frame);
|
||||||
|
assert(tstate->tracing == 0);
|
||||||
assert(is_version_up_to_date(code, tstate->interp));
|
assert(is_version_up_to_date(code, tstate->interp));
|
||||||
assert(instrumentation_cross_checks(tstate->interp, code));
|
assert(instrumentation_cross_checks(tstate->interp, code));
|
||||||
int i = (int)(instr - _PyCode_CODE(code));
|
int i = (int)(instr - _PyCode_CODE(code));
|
||||||
|
|
||||||
_PyCoMonitoringData *monitoring = code->_co_monitoring;
|
_PyCoMonitoringData *monitoring = code->_co_monitoring;
|
||||||
_PyCoLineInstrumentationData *line_data = &monitoring->lines[i];
|
_PyCoLineInstrumentationData *line_data = &monitoring->lines[i];
|
||||||
if (tstate->tracing) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
PyInterpreterState *interp = tstate->interp;
|
PyInterpreterState *interp = tstate->interp;
|
||||||
int8_t line_delta = line_data->line_delta;
|
int8_t line_delta = line_data->line_delta;
|
||||||
int line = 0;
|
int line = 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue