Skip to content

Commit f55273b

Browse files
authored
GH-116968: Remove branch from advance_backoff_counter (GH-124469)
1 parent 31516c9 commit f55273b

File tree

4 files changed

+29
-33
lines changed

4 files changed

+29
-33
lines changed

Include/internal/pycore_backoff.h

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,7 @@ extern "C" {
1515

1616

1717
typedef struct {
18-
union {
19-
struct {
20-
uint16_t backoff : 4;
21-
uint16_t value : 12;
22-
};
23-
uint16_t as_counter; // For printf("%#x", ...)
24-
};
18+
uint16_t value_and_backoff;
2519
} _Py_BackoffCounter;
2620

2721

@@ -38,17 +32,19 @@ typedef struct {
3832
and a 4-bit 'backoff' field. When resetting the counter, the
3933
backoff field is incremented (until it reaches a limit) and the
4034
value is set to a bit mask representing the value 2**backoff - 1.
41-
The maximum backoff is 12 (the number of value bits).
35+
The maximum backoff is 12 (the number of bits in the value).
4236
4337
There is an exceptional value which must not be updated, 0xFFFF.
4438
*/
4539

46-
#define UNREACHABLE_BACKOFF 0xFFFF
40+
#define BACKOFF_BITS 4
41+
#define MAX_BACKOFF 12
42+
#define UNREACHABLE_BACKOFF 15
4743

4844
static inline bool
4945
is_unreachable_backoff_counter(_Py_BackoffCounter counter)
5046
{
51-
return counter.as_counter == UNREACHABLE_BACKOFF;
47+
return counter.value_and_backoff == UNREACHABLE_BACKOFF;
5248
}
5349

5450
static inline _Py_BackoffCounter
@@ -57,52 +53,52 @@ make_backoff_counter(uint16_t value, uint16_t backoff)
5753
assert(backoff <= 15);
5854
assert(value <= 0xFFF);
5955
_Py_BackoffCounter result;
60-
result.value = value;
61-
result.backoff = backoff;
56+
result.value_and_backoff = (value << BACKOFF_BITS) | backoff;
6257
return result;
6358
}
6459

6560
static inline _Py_BackoffCounter
6661
forge_backoff_counter(uint16_t counter)
6762
{
6863
_Py_BackoffCounter result;
69-
result.as_counter = counter;
64+
result.value_and_backoff = counter;
7065
return result;
7166
}
7267

7368
static inline _Py_BackoffCounter
7469
restart_backoff_counter(_Py_BackoffCounter counter)
7570
{
7671
assert(!is_unreachable_backoff_counter(counter));
77-
if (counter.backoff < 12) {
78-
return make_backoff_counter((1 << (counter.backoff + 1)) - 1, counter.backoff + 1);
72+
int backoff = counter.value_and_backoff & 15;
73+
if (backoff < MAX_BACKOFF) {
74+
return make_backoff_counter((1 << (backoff + 1)) - 1, backoff + 1);
7975
}
8076
else {
81-
return make_backoff_counter((1 << 12) - 1, 12);
77+
return make_backoff_counter((1 << MAX_BACKOFF) - 1, MAX_BACKOFF);
8278
}
8379
}
8480

8581
static inline _Py_BackoffCounter
8682
pause_backoff_counter(_Py_BackoffCounter counter)
8783
{
88-
return make_backoff_counter(counter.value | 1, counter.backoff);
84+
_Py_BackoffCounter result;
85+
result.value_and_backoff = counter.value_and_backoff | (1 << BACKOFF_BITS);
86+
return result;
8987
}
9088

9189
static inline _Py_BackoffCounter
9290
advance_backoff_counter(_Py_BackoffCounter counter)
9391
{
94-
if (!is_unreachable_backoff_counter(counter)) {
95-
return make_backoff_counter((counter.value - 1) & 0xFFF, counter.backoff);
96-
}
97-
else {
98-
return counter;
99-
}
92+
_Py_BackoffCounter result;
93+
result.value_and_backoff = counter.value_and_backoff - (1 << BACKOFF_BITS);
94+
return result;
10095
}
10196

10297
static inline bool
10398
backoff_counter_triggers(_Py_BackoffCounter counter)
10499
{
105-
return counter.value == 0;
100+
/* Test whether the value is zero and the backoff is not UNREACHABLE_BACKOFF */
101+
return counter.value_and_backoff < UNREACHABLE_BACKOFF;
106102
}
107103

108104
/* Initial JUMP_BACKWARD counter.
@@ -136,7 +132,7 @@ initial_temperature_backoff_counter(void)
136132
static inline _Py_BackoffCounter
137133
initial_unreachable_backoff_counter(void)
138134
{
139-
return forge_backoff_counter(UNREACHABLE_BACKOFF);
135+
return make_backoff_counter(0, UNREACHABLE_BACKOFF);
140136
}
141137

142138
#ifdef __cplusplus

Python/bytecodes.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4705,7 +4705,7 @@ dummy_func(
47054705
printf("SIDE EXIT: [UOp ");
47064706
_PyUOpPrint(&next_uop[-1]);
47074707
printf(", exit %u, temp %d, target %d -> %s]\n",
4708-
exit - current_executor->exits, exit->temperature.as_counter,
4708+
exit - current_executor->exits, exit->temperature.value_and_backoff,
47094709
(int)(target - _PyCode_CODE(code)),
47104710
_PyOpcode_OpName[target->op.code]);
47114711
}
@@ -4794,7 +4794,7 @@ dummy_func(
47944794
printf("DYNAMIC EXIT: [UOp ");
47954795
_PyUOpPrint(&next_uop[-1]);
47964796
printf(", exit %u, temp %d, target %d -> %s]\n",
4797-
exit - current_executor->exits, exit->temperature.as_counter,
4797+
exit - current_executor->exits, exit->temperature.value_and_backoff,
47984798
(int)(target - _PyCode_CODE(_PyFrame_GetCode(frame))),
47994799
_PyOpcode_OpName[target->op.code]);
48004800
}

Python/executor_cases.c.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/instrumentation.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -643,8 +643,8 @@ de_instrument(PyCodeObject *code, int i, int event)
643643
CHECK(_PyOpcode_Deopt[deinstrumented] == deinstrumented);
644644
FT_ATOMIC_STORE_UINT8_RELAXED(*opcode_ptr, deinstrumented);
645645
if (_PyOpcode_Caches[deinstrumented]) {
646-
FT_ATOMIC_STORE_UINT16_RELAXED(instr[1].counter.as_counter,
647-
adaptive_counter_warmup().as_counter);
646+
FT_ATOMIC_STORE_UINT16_RELAXED(instr[1].counter.value_and_backoff,
647+
adaptive_counter_warmup().value_and_backoff);
648648
}
649649
}
650650

@@ -719,8 +719,8 @@ instrument(PyCodeObject *code, int i)
719719
assert(instrumented);
720720
FT_ATOMIC_STORE_UINT8_RELAXED(*opcode_ptr, instrumented);
721721
if (_PyOpcode_Caches[deopt]) {
722-
FT_ATOMIC_STORE_UINT16_RELAXED(instr[1].counter.as_counter,
723-
adaptive_counter_warmup().as_counter);
722+
FT_ATOMIC_STORE_UINT16_RELAXED(instr[1].counter.value_and_backoff,
723+
adaptive_counter_warmup().value_and_backoff);
724724
instr[1].counter = adaptive_counter_warmup();
725725
}
726726
}

0 commit comments

Comments
 (0)