Skip to content

Commit 0ebb67a

Browse files
committed
gh-141504: Configurable JIT optimization thresholds
1 parent b538c28 commit 0ebb67a

6 files changed

Lines changed: 69 additions & 13 deletions

File tree

Include/internal/pycore_backoff.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,9 @@ trigger_backoff_counter(void)
127127
#define JUMP_BACKWARD_INITIAL_VALUE 4000
128128
#define JUMP_BACKWARD_INITIAL_BACKOFF 6
129129
static inline _Py_BackoffCounter
130-
initial_jump_backoff_counter(void)
130+
initial_jump_backoff_counter(uint16_t initial_value, uint16_t initial_backoff)
131131
{
132-
return make_backoff_counter(JUMP_BACKWARD_INITIAL_VALUE,
133-
JUMP_BACKWARD_INITIAL_BACKOFF);
132+
return make_backoff_counter(initial_value, initial_backoff);
134133
}
135134

136135
/* Initial exit temperature.
@@ -141,10 +140,9 @@ initial_jump_backoff_counter(void)
141140
#define SIDE_EXIT_INITIAL_BACKOFF 6
142141

143142
static inline _Py_BackoffCounter
144-
initial_temperature_backoff_counter(void)
143+
initial_temperature_backoff_counter(uint16_t initial_value, uint16_t initial_backoff)
145144
{
146-
return make_backoff_counter(SIDE_EXIT_INITIAL_VALUE,
147-
SIDE_EXIT_INITIAL_BACKOFF);
145+
return make_backoff_counter(initial_value, initial_backoff);
148146
}
149147

150148
/* Unreachable backoff counter. */

Include/internal/pycore_tstate.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ typedef struct _PyJitTracerState {
5252
_PyJitTracerInitialState initial_state;
5353
_PyJitTracerPreviousState prev_state;
5454
} _PyJitTracerState;
55+
56+
typedef struct _PyJitMetrics {
57+
uint16_t jump_backward_initial_value;
58+
uint16_t jump_backward_initial_backoff;
59+
uint16_t side_exit_initial_value;
60+
uint16_t side_exit_initial_backoff;
61+
} _PyJitMetrics;
5562
#endif
5663

5764
// Every PyThreadState is actually allocated as a _PyThreadStateImpl. The
@@ -131,6 +138,7 @@ typedef struct _PyThreadStateImpl {
131138
#endif
132139
#if _Py_TIER2
133140
_PyJitTracerState jit_tracer_state;
141+
_PyJitMetrics jit_metrics;
134142
#endif
135143
} _PyThreadStateImpl;
136144

Python/ceval.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,7 +1473,9 @@ stop_tracing_and_jit(PyThreadState *tstate, _PyInterpreterFrame *frame)
14731473
_tstate->jit_tracer_state.initial_state.jump_backward_instr[1].counter = restart_backoff_counter(counter);
14741474
}
14751475
else {
1476-
_tstate->jit_tracer_state.initial_state.jump_backward_instr[1].counter = initial_jump_backoff_counter();
1476+
_tstate->jit_tracer_state.initial_state.jump_backward_instr[1].counter = initial_jump_backoff_counter(
1477+
_tstate->jit_metrics.jump_backward_initial_value,
1478+
_tstate->jit_metrics.jump_backward_initial_backoff);
14771479
}
14781480
}
14791481
else {
@@ -1483,7 +1485,9 @@ stop_tracing_and_jit(PyThreadState *tstate, _PyInterpreterFrame *frame)
14831485
exit->temperature = restart_backoff_counter(exit->temperature);
14841486
}
14851487
else {
1486-
exit->temperature = initial_temperature_backoff_counter();
1488+
exit->temperature = initial_temperature_backoff_counter(
1489+
_tstate->jit_metrics.side_exit_initial_value,
1490+
_tstate->jit_metrics.side_exit_initial_backoff);
14871491
}
14881492
}
14891493
_PyJit_FinalizeTracing(tstate);

Python/optimizer.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ insert_executor(PyCodeObject *code, _Py_CODEUNIT *instr, int index, _PyExecutorO
113113
}
114114

115115
static _PyExecutorObject *
116-
make_executor_from_uops(_PyUOpInstruction *buffer, int length, const _PyBloomFilter *dependencies, int chain_depth);
116+
make_executor_from_uops(_PyThreadStateImpl *tstate, _PyUOpInstruction *buffer, int length, const _PyBloomFilter *dependencies);
117117

118118
static int
119119
uop_optimize(_PyInterpreterFrame *frame, PyThreadState *tstate,
@@ -1328,7 +1328,7 @@ sanity_check(_PyExecutorObject *executor)
13281328
* and not a NOP.
13291329
*/
13301330
static _PyExecutorObject *
1331-
make_executor_from_uops(_PyUOpInstruction *buffer, int length, const _PyBloomFilter *dependencies, int chain_depth)
1331+
make_executor_from_uops(_PyThreadStateImpl *tstate, _PyUOpInstruction *buffer, int length, const _PyBloomFilter *dependencies)
13321332
{
13331333
int exit_count = count_exits(buffer, length);
13341334
_PyExecutorObject *executor = allocate_executor(exit_count, length);
@@ -1337,12 +1337,15 @@ make_executor_from_uops(_PyUOpInstruction *buffer, int length, const _PyBloomFil
13371337
}
13381338

13391339
/* Initialize exits */
1340+
int chain_depth = tstate->jit_tracer_state.initial_state.chain_depth;
13401341
_PyExecutorObject *cold = _PyExecutor_GetColdExecutor();
13411342
_PyExecutorObject *cold_dynamic = _PyExecutor_GetColdDynamicExecutor();
13421343
cold->vm_data.chain_depth = chain_depth;
13431344
for (int i = 0; i < exit_count; i++) {
13441345
executor->exits[i].index = i;
1345-
executor->exits[i].temperature = initial_temperature_backoff_counter();
1346+
executor->exits[i].temperature = initial_temperature_backoff_counter(
1347+
tstate->jit_metrics.side_exit_initial_value,
1348+
tstate->jit_metrics.side_exit_initial_backoff);
13461349
}
13471350
int next_exit = exit_count-1;
13481351
_PyUOpInstruction *dest = (_PyUOpInstruction *)&executor->trace[length];
@@ -1510,7 +1513,7 @@ uop_optimize(
15101513
length = prepare_for_execution(buffer, length);
15111514
assert(length <= UOP_MAX_TRACE_LENGTH);
15121515
_PyExecutorObject *executor = make_executor_from_uops(
1513-
buffer, length, dependencies, _tstate->jit_tracer_state.initial_state.chain_depth);
1516+
_tstate, buffer, length, dependencies);
15141517
if (executor == NULL) {
15151518
return -1;
15161519
}

Python/pystate.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "Python.h"
55
#include "pycore_abstract.h" // _PyIndex_Check()
66
#include "pycore_audit.h" // _Py_AuditHookEntry
7+
#include "pycore_backoff.h" // JUMP_BACKWARD_INITIAL_VALUE, SIDE_EXIT_INITIAL_VALUE
78
#include "pycore_ceval.h" // _PyEval_AcquireLock()
89
#include "pycore_codecs.h" // _PyCodec_Fini()
910
#include "pycore_critical_section.h" // _PyCriticalSection_Resume()
@@ -1526,6 +1527,44 @@ init_threadstate(_PyThreadStateImpl *_tstate,
15261527

15271528
#ifdef _Py_TIER2
15281529
_tstate->jit_tracer_state.code_buffer = NULL;
1530+
1531+
// Initialize JIT metrics from environment variables
1532+
_tstate->jit_metrics.jump_backward_initial_value = JUMP_BACKWARD_INITIAL_VALUE;
1533+
_tstate->jit_metrics.jump_backward_initial_backoff = JUMP_BACKWARD_INITIAL_BACKOFF;
1534+
_tstate->jit_metrics.side_exit_initial_value = SIDE_EXIT_INITIAL_VALUE;
1535+
_tstate->jit_metrics.side_exit_initial_backoff = SIDE_EXIT_INITIAL_BACKOFF;
1536+
1537+
char *env = Py_GETENV("PYTHON_JIT_JUMP_BACKWARD_INITIAL_VALUE");
1538+
if (env && *env != '\0') {
1539+
long value = atol(env);
1540+
if (value > 0 && value <= MAX_VALUE) {
1541+
_tstate->jit_metrics.jump_backward_initial_value = (uint16_t)value;
1542+
}
1543+
}
1544+
1545+
env = Py_GETENV("PYTHON_JIT_JUMP_BACKWARD_INITIAL_BACKOFF");
1546+
if (env && *env != '\0') {
1547+
long value = atol(env);
1548+
if (value >= 0 && value <= MAX_BACKOFF) {
1549+
_tstate->jit_metrics.jump_backward_initial_backoff = (uint16_t)value;
1550+
}
1551+
}
1552+
1553+
env = Py_GETENV("PYTHON_JIT_SIDE_EXIT_INITIAL_VALUE");
1554+
if (env && *env != '\0') {
1555+
long value = atol(env);
1556+
if (value > 0 && value <= MAX_VALUE) {
1557+
_tstate->jit_metrics.side_exit_initial_value = (uint16_t)value;
1558+
}
1559+
}
1560+
1561+
env = Py_GETENV("PYTHON_JIT_SIDE_EXIT_INITIAL_BACKOFF");
1562+
if (env && *env != '\0') {
1563+
long value = atol(env);
1564+
if (value >= 0 && value <= MAX_BACKOFF) {
1565+
_tstate->jit_metrics.side_exit_initial_backoff = (uint16_t)value;
1566+
}
1567+
}
15291568
#endif
15301569
tstate->delete_later = NULL;
15311570

Python/specialize.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters
4747
#if ENABLE_SPECIALIZATION_FT
4848
_Py_BackoffCounter jump_counter, adaptive_counter;
4949
if (enable_counters) {
50-
jump_counter = initial_jump_backoff_counter();
50+
PyThreadState *tstate = _PyThreadState_GET();
51+
_PyThreadStateImpl *tstate_impl = (_PyThreadStateImpl *)tstate;
52+
jump_counter = initial_jump_backoff_counter(
53+
tstate_impl->jit_metrics.jump_backward_initial_value,
54+
tstate_impl->jit_metrics.jump_backward_initial_backoff);
5155
adaptive_counter = adaptive_counter_warmup();
5256
}
5357
else {

0 commit comments

Comments
 (0)