Skip to content

Commit b05afdd

Browse files
authored
gh-115168: Add pystats counter for invalidated executors (GH-115169)
1 parent 96c10c6 commit b05afdd

File tree

11 files changed

+31
-14
lines changed

11 files changed

+31
-14
lines changed

Include/cpython/optimizer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ void _Py_ExecutorClear(_PyExecutorObject *);
100100
void _Py_BloomFilter_Init(_PyBloomFilter *);
101101
void _Py_BloomFilter_Add(_PyBloomFilter *bloom, void *obj);
102102
PyAPI_FUNC(void) _Py_Executor_DependsOn(_PyExecutorObject *executor, void *obj);
103-
PyAPI_FUNC(void) _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj);
104-
extern void _Py_Executors_InvalidateAll(PyInterpreterState *interp);
103+
PyAPI_FUNC(void) _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int is_invalidation);
104+
extern void _Py_Executors_InvalidateAll(PyInterpreterState *interp, int is_invalidation);
105105

106106
/* For testing */
107107
PyAPI_FUNC(PyObject *)PyUnstable_Optimizer_NewCounter(void);

Include/cpython/pystats.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ typedef struct _optimization_stats {
115115
uint64_t inner_loop;
116116
uint64_t recursive_call;
117117
uint64_t low_confidence;
118+
uint64_t executors_invalidated;
118119
UOpStats opcode[512];
119120
uint64_t unsupported_opcode[256];
120121
uint64_t trace_length_hist[_Py_UOP_HIST_SIZE];

Modules/_testinternalcapi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,7 @@ static PyObject *
10351035
invalidate_executors(PyObject *self, PyObject *obj)
10361036
{
10371037
PyInterpreterState *interp = PyInterpreterState_Get();
1038-
_Py_Executors_InvalidateDependency(interp, obj);
1038+
_Py_Executors_InvalidateDependency(interp, obj, 1);
10391039
Py_RETURN_NONE;
10401040
}
10411041

Python/instrumentation.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,7 +1599,7 @@ _Py_Instrument(PyCodeObject *code, PyInterpreterState *interp)
15991599
if (code->co_executors != NULL) {
16001600
_PyCode_Clear_Executors(code);
16011601
}
1602-
_Py_Executors_InvalidateDependency(interp, code);
1602+
_Py_Executors_InvalidateDependency(interp, code, 1);
16031603
int code_len = (int)Py_SIZE(code);
16041604
/* Exit early to avoid creating instrumentation
16051605
* data for potential statically allocated code
@@ -1820,7 +1820,7 @@ _PyMonitoring_SetEvents(int tool_id, _PyMonitoringEventSet events)
18201820
return -1;
18211821
}
18221822
set_global_version(tstate, new_version);
1823-
_Py_Executors_InvalidateAll(interp);
1823+
_Py_Executors_InvalidateAll(interp, 1);
18241824
return instrument_all_executing_code_objects(interp);
18251825
}
18261826

@@ -1850,7 +1850,7 @@ _PyMonitoring_SetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEvent
18501850
/* Force instrumentation update */
18511851
code->_co_instrumentation_version -= MONITORING_VERSION_INCREMENT;
18521852
}
1853-
_Py_Executors_InvalidateDependency(interp, code);
1853+
_Py_Executors_InvalidateDependency(interp, code, 1);
18541854
if (_Py_Instrument(code, interp)) {
18551855
return -1;
18561856
}

Python/optimizer.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,7 +1348,7 @@ _Py_Executor_DependsOn(_PyExecutorObject *executor, void *obj)
13481348
* May cause other executors to be invalidated as well
13491349
*/
13501350
void
1351-
_Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj)
1351+
_Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int is_invalidation)
13521352
{
13531353
_PyBloomFilter obj_filter;
13541354
_Py_BloomFilter_Init(&obj_filter);
@@ -1360,14 +1360,17 @@ _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj)
13601360
_PyExecutorObject *next = exec->vm_data.links.next;
13611361
if (bloom_filter_may_contain(&exec->vm_data.bloom, &obj_filter)) {
13621362
_Py_ExecutorClear(exec);
1363+
if (is_invalidation) {
1364+
OPT_STAT_INC(executors_invalidated);
1365+
}
13631366
}
13641367
exec = next;
13651368
}
13661369
}
13671370

13681371
/* Invalidate all executors */
13691372
void
1370-
_Py_Executors_InvalidateAll(PyInterpreterState *interp)
1373+
_Py_Executors_InvalidateAll(PyInterpreterState *interp, int is_invalidation)
13711374
{
13721375
while (interp->executor_list_head) {
13731376
_PyExecutorObject *executor = interp->executor_list_head;
@@ -1378,5 +1381,8 @@ _Py_Executors_InvalidateAll(PyInterpreterState *interp)
13781381
else {
13791382
_Py_ExecutorClear(executor);
13801383
}
1384+
if (is_invalidation) {
1385+
OPT_STAT_INC(executors_invalidated);
1386+
}
13811387
}
13821388
}

Python/optimizer_analysis.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ globals_watcher_callback(PyDict_WatchEvent event, PyObject* dict,
405405
{
406406
RARE_EVENT_STAT_INC(watched_globals_modification);
407407
assert(get_mutations(dict) < _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS);
408-
_Py_Executors_InvalidateDependency(_PyInterpreterState_GET(), dict);
408+
_Py_Executors_InvalidateDependency(_PyInterpreterState_GET(), dict, 1);
409409
increment_mutations(dict);
410410
PyDict_Unwatch(GLOBALS_WATCHER_ID, dict);
411411
return 0;

Python/pylifecycle.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ builtins_dict_watcher(PyDict_WatchEvent event, PyObject *dict, PyObject *key, Py
612612
{
613613
PyInterpreterState *interp = _PyInterpreterState_GET();
614614
if (interp->rare_events.builtin_dict < _Py_MAX_ALLOWED_BUILTINS_MODIFICATIONS) {
615-
_Py_Executors_InvalidateAll(interp);
615+
_Py_Executors_InvalidateAll(interp, 1);
616616
}
617617
RARE_EVENT_INTERP_INC(interp, builtin_dict);
618618
return 0;
@@ -1628,7 +1628,7 @@ finalize_modules(PyThreadState *tstate)
16281628
PyInterpreterState *interp = tstate->interp;
16291629

16301630
// Invalidate all executors and turn off tier 2 optimizer
1631-
_Py_Executors_InvalidateAll(interp);
1631+
_Py_Executors_InvalidateAll(interp, 0);
16321632
_PyOptimizerObject *old = _Py_SetOptimizer(interp, NULL);
16331633
Py_XDECREF(old);
16341634

Python/pystate.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2666,7 +2666,7 @@ _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp,
26662666
return;
26672667
}
26682668
if (eval_frame != NULL) {
2669-
_Py_Executors_InvalidateAll(interp);
2669+
_Py_Executors_InvalidateAll(interp, 1);
26702670
}
26712671
RARE_EVENT_INC(set_eval_frame_func);
26722672
interp->eval_frame = eval_frame;

Python/specialize.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ print_optimization_stats(FILE *out, OptimizationStats *stats)
236236
fprintf(out, "Optimization inner loop: %" PRIu64 "\n", stats->inner_loop);
237237
fprintf(out, "Optimization recursive call: %" PRIu64 "\n", stats->recursive_call);
238238
fprintf(out, "Optimization low confidence: %" PRIu64 "\n", stats->low_confidence);
239+
fprintf(out, "Executors invalidated: %" PRIu64 "\n", stats->executors_invalidated);
239240

240241
print_histogram(out, "Trace length", stats->trace_length_hist);
241242
print_histogram(out, "Trace run length", stats->trace_run_length_hist);

Python/sysmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2138,7 +2138,7 @@ sys__clear_internal_caches_impl(PyObject *module)
21382138
/*[clinic end generated code: output=0ee128670a4966d6 input=253e741ca744f6e8]*/
21392139
{
21402140
PyInterpreterState *interp = _PyInterpreterState_GET();
2141-
_Py_Executors_InvalidateAll(interp);
2141+
_Py_Executors_InvalidateAll(interp, 0);
21422142
PyType_ClearCache();
21432143
Py_RETURN_NONE;
21442144
}

0 commit comments

Comments
 (0)