8000 gh-116996: Add pystats about _Py_uop_analyse_and_optimize (GH-116997) · python/cpython@50369e6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 50369e6

Browse files
authored
gh-116996: Add pystats about _Py_uop_analyse_and_optimize (GH-116997)
1 parent 617158e commit 50369e6

File tree

5 files changed

+56
-3
lines changed

5 files changed

+56
-3
lines changed

Include/cpython/pystats.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
// Define _PY_INTERPRETER macro to increment interpreter_increfs and
2020
// interpreter_decrefs. Otherwise, increment increfs and decrefs.
2121

22+
#include "pycore_uop_ids.h"
23+
2224
#ifndef Py_CPYTHON_PYSTATS_H
2325
# error "this header file must not be included directly"
2426
#endif
@@ -116,14 +118,17 @@ typedef struct _optimization_stats {
116118
uint64_t recursive_call;
117119
uint64_t low_confidence;
118120
uint64_t executors_invalidated;
119-
UOpStats opcode[512];
121+
UOpStats opcode[MAX_UOP_ID];
120122
uint64_t unsupported_opcode[256];
121123
uint64_t trace_length_hist[_Py_UOP_HIST_SIZE];
122124
uint64_t trace_run_length_hist[_Py_UOP_HIST_SIZE];
123125
uint64_t optimized_trace_length_hist[_Py_UOP_HIST_SIZE];
124126
uint64_t optimizer_attempts;
125127
uint64_t optimizer_successes;
126128
uint64_t optimizer_failure_reason_no_memory;
129+
uint64_t remove_globals_builtins_changed;
130+
uint64_t remove_globals_incorrect_keys;
131+
uint64_t error_in_opcode[MAX_UOP_ID];
127132
} OptimizationStats;
128133

129134
typedef struct _rare_event_stats {

Include/internal/pycore_code.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ extern int _PyStaticCode_Init(PyCodeObject *co);
308308
#define OPT_STAT_INC(name) do { if (_Py_stats) _Py_stats->optimization_stats.name++; } while (0)
309309
#define UOP_STAT_INC(opname, name) do { if (_Py_stats) { assert(opname < 512); _Py_stats->optimization_stats.opcode[opname].name++; } } while (0)
310310
#define OPT_UNSUPPORTED_OPCODE(opname) do { if (_Py_stats) _Py_stats->optimization_stats.unsupported_opcode[opname]++; } while (0)
311+
#define OPT_ERROR_IN_OPCODE(opname) do { if (_Py_stats) _Py_stats->optimization_stats.error_in_opcode[opname]++; } while (0)
311312
#define OPT_HIST(length, name) \
312313
do { \
313314
if (_Py_stats) { \
@@ -334,6 +335,7 @@ PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void);
334335
#define OPT_STAT_INC(name) ((void)0)
335336
#define UOP_STAT_INC(opname, name) ((void)0)
336337
#define OPT_UNSUPPORTED_OPCODE(opname) ((void)0)
338+
#define OPT_ERROR_IN_OPCODE(opname) ((void)0)
337339
#define OPT_HIST(length, name) ((void)0)
338340
#define RARE_EVENT_STAT_INC(name) ((void)0)
339341
#endif // !Py_STATS

Python/optimizer_analysis.c

Lines changed: 9 additions & 2 deletions
B422
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
139139
PyInterpreterState *interp = _PyInterpreterState_GET();
140140
PyObject *builtins = frame->f_builtins;
141141
if (builtins != interp->builtins) {
142+
OPT_STAT_INC(remove_globals_builtins_changed);
142143
return 1;
143144
}
144145
PyObject *globals = frame->f_globals;
@@ -170,6 +171,7 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
170171
switch(opcode) {
171172
case _GUARD_BUILTINS_VERSION:
172173
if (incorrect_keys(inst, builtins)) {
174+
OPT_STAT_INC(remove_globals_incorrect_keys);
173175
return 0;
174176
}
175177
if (interp->rare_events.builtin_dict >= _Py_MAX_ALLOWED_BUILTINS_MODIFICATIONS) {
@@ -190,6 +192,7 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
190192
break;
191193
case _GUARD_GLOBALS_VERSION:
192194
if (incorrect_keys(inst, globals)) {
195+
OPT_STAT_INC(remove_globals_incorrect_keys);
193196
return 0;
194197
}
195198
uint64_t watched_mutations = get_mutations(globals);
@@ -238,6 +241,7 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
238241
globals = func->func_globals;
239242
builtins = func->func_builtins;
240243
if (builtins != interp->builtins) {
244+
OPT_STAT_INC(remove_globals_builtins_changed);
241245
return 1;
242246
}
243247
break;
@@ -358,6 +362,7 @@ optimize_uops(
358362

359363
_Py_UOpsContext context;
360364
_Py_UOpsContext *ctx = &context;
365+
uint32_t opcode = UINT16_MAX;
361366

362367
if (_Py_uop_abstractcontext_init(ctx) < 0) {
363368
goto out_of_space;
@@ -374,8 +379,7 @@ optimize_uops(
374379
this_instr++) {
375380

376381
int oparg = this_instr->oparg;
377-
uint32_t opcode = this_instr->opcode;
378-
382+
opcode = this_instr->opcode;
379383
_Py_UopsSymbol **stack_pointer = ctx->frame->stack_pointer;
380384

381385
#ifdef Py_DEBUG
@@ -410,6 +414,9 @@ optimize_uops(
410414
error:
411415
DPRINTF(3, "\n");
412416
DPRINTF(1, "Encountered error in abstract interpreter\n");
417+
if (opcode <= MAX_UOP_ID) {
418+
OPT_ERROR_IN_OPCODE(opcode);
419+
}
413420
_Py_uop_abstractcontext_fini(ctx);
414421
return -1;
415422

Python/specialize.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ print_optimization_stats(FILE *out, OptimizationStats *stats)
247247
fprintf(out, "Optimization optimizer successes: %" PRIu64 "\n", stats->optimizer_successes);
248248
fprintf(out, "Optimization optimizer failure no memory: %" PRIu64 "\n",
249249
stats->optimizer_failure_reason_no_memory);
250+
fprintf(out, "Optimizer remove globals builtins changed: %" PRIu64 "\n", stats->remove_globals_builtins_changed);
251+
fprintf(out, "Optimizer remove globals incorrect keys: %" PRIu64 "\n", stats->remove_globals_incorrect_keys);
250252

251253
const char* const* names;
252254
for (int i = 0; i <= MAX_UOP_ID; i++) {
@@ -268,6 +270,17 @@ print_optimization_stats(FILE *out, OptimizationStats *stats)
268270
);
F438 269271
}
270272
}
273+
274+
for (int i = 0; i < MAX_UOP_ID; i++) {
275+
if (stats->error_in_opcode[i]) {
276+
fprintf(
277+
out,
278+
"error_in_opcode[%s].count : %" PRIu64 "\n",
279+
_PyUOpName(i),
280+
stats->error_in_opcode[i]
281+
);
282+
}
283+
}
271284
}
272285

273286
static void

Tools/scripts/summarize_stats.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,8 @@ def get_optimizer_stats(self) -> dict[str, tuple[int, int | None]]:
513513
attempts = self._data["Optimization optimizer attempts"]
514514
successes = self._data["Optimization optimizer successes"]
515515
no_memory = self._data["Optimization optimizer failure no memory"]
516+
builtins_changed = self._data["Optimizer remove globals builtins changed"]
517+
incorrect_keys = self._data["Optimizer remove globals incorrect keys"]
516518

517519
return {
518520
Doc(
@@ -527,6 +529,14 @@ def get_optimizer_stats(self) -> dict[str, tuple[int, int | None]]:
527529
"Optimizer no memory",
528530
"The number of optimizations that failed due to no memory.",
529531
): (no_memory, attempts),
532+
Doc(
533+
"Remove globals builtins changed",
534+
"The builtins changed during optimization",
535+
): (builtins_changed, attempts),
536+
Doc(
537+
"Remove globals incorrect keys",
538+
"The keys in the globals dictionary aren't what was expected",
539+
): (incorrect_keys, attempts),
530540
}
531541

532542
def get_histogram(self, prefix: str) -> list[tuple[int, int]]:
@@ -1177,6 +1187,17 @@ def calc_unsupported_opcodes_table(stats: Stats) -> Rows:
11771187
reverse=True,
11781188
)
11791189

1190+
def calc_error_in_opcodes_table(stats: Stats) -> Rows:
1191+
error_in_opcodes = stats.get_opcode_stats("error_in_opcode")
1192+
return sorted(
1193+
[
1194+
(opcode, Count(count))
1195+
for opcode, count in error_in_opcodes.get_opcode_counts().items()
1196+
],
1197+
key=itemgetter(1),
1198+
reverse=True,
1199+
)
1200+
11801201
def iter_optimization_tables(base_stats: Stats, head_stats: Stats | None = None):
11811202
if not base_stats.get_optimization_stats() or (
11821203
head_stats is not None and not head_stats.get_optimization_stats()
@@ -1223,6 +1244,11 @@ def iter_optimization_tables(base_stats: Stats, head_stats: Stats | None = None)
12231244
)
12241245
],
12251246
)
1247+
yield Section(
1248+
"Optimizer errored out with opcode",
1249+
"Optimization stopped after encountering this opcode",
1250+
[Table(("Opcode", "Count:"), calc_error_in_opcodes_table, JoinMode.CHANGE)],
1251+
)
12261252

12271253
return Section(
12281254
"Optimization (Tier 2) stats",

0 commit comments

Comments
 (0)
0