-
-
Notifications
You must be signed in to change notification settings - Fork 32k
gh-116968: Reimplement Tier 2 counters #117144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
e7e819b
8c74dfa
79036ff
54c1f8e
015bb00
1730295
95f93b7
7df0f10
925cae7
f0c7fb0
8f79a60
149e9c4
1d76112
a5ffe02
ce7726c
e2c39f2
8d22790
cd8264e
d72c2ef
f6bf194
b991843
9b9f26a
354cd81
c1de44f
1fe27c9
225ea17
63d8bc7
8aa2c75
7bd4daa
3f1c58a
8ce8068
7bb5618
63e286c
7f64392
8eee1b4
42c1f26
a80cd0a
545c60e
6c0bb30
a7c9b6d
3fee35f
df6f34c
72f6b0d
dcee362
f38d922
ef6366b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -448,18 +448,14 @@ write_location_entry_start(uint8_t *ptr, int code, int length) | |
|
||
/** Counters | ||
* The first 16-bit value in each inline cache is a counter. | ||
* When counting misses, the counter is treated as a simple unsigned value. | ||
* | ||
* When counting executions until the next specialization attempt, | ||
* exponential backoff is used to reduce the number of specialization failures. | ||
* The high 12 bits store the counter, the low 4 bits store the backoff exponent. | ||
* On a specialization failure, the backoff exponent is incremented and the | ||
* counter set to (2**backoff - 1). | ||
* Backoff == 6 -> starting counter == 63, backoff == 10 -> starting counter == 1023. | ||
* See pycore_backoff.h for more details. | ||
* On a specialization failure, the backoff counter is reset. | ||
*/ | ||
|
||
/* With a 16-bit counter, we have 12 bits for the counter value, and 4 bits for the backoff */ | ||
#define ADAPTIVE_BACKOFF_BITS 4 | ||
#include "pycore_backoff.h" | ||
|
||
// A value of 1 means that we attempt to specialize the *second* time each | ||
// instruction is executed. Executing twice is a much better indicator of | ||
|
@@ -477,13 +473,9 @@ write_location_entry_start(uint8_t *ptr, int code, int length) | |
#define ADAPTIVE_COOLDOWN_VALUE 52 | ||
#define ADAPTIVE_COOLDOWN_BACKOFF 0 | ||
|
||
#define MAX_BACKOFF_VALUE (16 - ADAPTIVE_BACKOFF_BITS) | ||
|
||
|
||
static inline uint16_t | ||
adaptive_counter_bits(uint16_t value, uint16_t backoff) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe drop the To do that cleanly we will probably need to change typedef union {
uint16_t cache;
struct {
uint8_t code;
uint8_t arg;
} op;
backoff_counter_t counter;
} _Py_CODEUNIT; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I decided to keep them and not expose the backoff counter structure to other places. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I could dispense with |
||
return ((value << ADAPTIVE_BACKOFF_BITS) | ||
| (backoff & ((1 << ADAPTIVE_BACKOFF_BITS) - 1))); | ||
return make_backoff_counter(value, backoff).counter; | ||
} | ||
|
||
static inline uint16_t | ||
|
@@ -500,13 +492,7 @@ adaptive_counter_cooldown(void) { | |
|
||
static inline uint16_t | ||
adaptive_counter_backoff(uint16_t counter) { | ||
uint16_t backoff = counter & ((1 << ADAPTIVE_BACKOFF_BITS) - 1); | ||
backoff++; | ||
if (backoff > MAX_BACKOFF_VALUE) { | ||
backoff = MAX_BACKOFF_VALUE; | ||
} | ||
uint16_t value = (uint16_t)(1 << backoff) - 1; | ||
return adaptive_counter_bits(value, backoff); | ||
return reset_backoff_counter(forge_backoff_counter(counter)).counter; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find this confusing. Is there a way to do this with a single call, rather than two calls and a field read? |
||
} | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -291,10 +291,7 @@ GETITEM(PyObject *v, Py_ssize_t i) { | |
} | ||
|
||
#define ADAPTIVE_COUNTER_IS_ZERO(COUNTER) \ | ||
(((COUNTER) >> ADAPTIVE_BACKOFF_BITS) == 0) | ||
|
||
#define ADAPTIVE_COUNTER_IS_MAX(COUNTER) \ | ||
(((COUNTER) >> ADAPTIVE_BACKOFF_BITS) == ((1 << MAX_BACKOFF_VALUE) - 1)) | ||
backoff_counter_is_zero(forge_backoff_counter((COUNTER))) | ||
|
||
#ifdef Py_GIL_DISABLED | ||
#define DECREMENT_ADAPTIVE_COUNTER(COUNTER) \ | ||
|
@@ -305,14 +302,13 @@ GETITEM(PyObject *v, Py_ssize_t i) { | |
#else | ||
#define DECREMENT_ADAPTIVE_COUNTER(COUNTER) \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace this with the backoff counter function? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am hoping to avoid 30+ diff chunks where I just replace this macro call with another. Also it is (for now) redefined when the GIL is disabled. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wouldn't worry about a few extra lines in the diff (there are 14 uses of |
||
do { \ | ||
assert(!ADAPTIVE_COUNTER_IS_ZERO((COUNTER))); \ | ||
(COUNTER) -= (1 << ADAPTIVE_BACKOFF_BITS); \ | ||
(COUNTER) = decrement_backoff_counter(forge_backoff_counter((COUNTER))).counter; \ | ||
} while (0); | ||
#endif | ||
|
||
#define INCREMENT_ADAPTIVE_COUNTER(COUNTER) \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Likewise There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one I changed, it's much more esoteric. It's now called PAUSE. |
||
do { \ | ||
(COUNTER) += (1 << ADAPTIVE_BACKOFF_BITS); \ | ||
(COUNTER) = increment_backoff_counter(forge_backoff_counter((COUNTER))).counter; \ | ||
} while (0); | ||
|
||
#define UNBOUNDLOCAL_ERROR_MSG \ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.