From f405fa50c50c31f945c7a9bf85d9b3bf2d4f9138 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Fri, 6 Oct 2023 09:39:56 -0400 Subject: [PATCH 1/4] Record opcode misses --- Include/cpython/pystats.h | 1 + Include/internal/pycore_code.h | 2 +- Python/executor.c | 3 ++- Python/specialize.c | 3 +++ Tools/scripts/summarize_stats.py | 2 +- 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Include/cpython/pystats.h b/Include/cpython/pystats.h index 4988caa803723d..294bf1505f0115 100644 --- a/Include/cpython/pystats.h +++ b/Include/cpython/pystats.h @@ -98,6 +98,7 @@ typedef struct _gc_stats { typedef struct _uop_stats { uint64_t execution_count; + uint64_t miss; } UOpStats; #define _Py_UOP_HIST_SIZE 32 diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index d31d8363d771ca..6c968e100eb4cc 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -283,7 +283,7 @@ extern int _PyStaticCode_Init(PyCodeObject *co); do { if (_Py_stats && PyFunction_Check(callable)) _Py_stats->call_stats.eval_calls[name]++; } while (0) #define GC_STAT_ADD(gen, name, n) do { if (_Py_stats) _Py_stats->gc_stats[(gen)].name += (n); } while (0) #define OPT_STAT_INC(name) do { if (_Py_stats) _Py_stats->optimization_stats.name++; } while (0) -#define UOP_EXE_INC(opname) do { if (_Py_stats) _Py_stats->optimization_stats.opcode[opname].execution_count++; } while (0) +#define UOP_STAT_INC(opname, name) do { if (_Py_stats) { assert(opname < 512); _Py_stats->optimization_stats.opcode[opname].name++; } } while (0) #define OPT_UNSUPPORTED_OPCODE(opname) do { if (_Py_stats) _Py_stats->optimization_stats.unsupported_opcode[opname]++; } while (0) #define OPT_HIST(length, name) \ do { \ diff --git a/Python/executor.c b/Python/executor.c index 1630f018626449..e17bb9037d5fe4 100644 --- a/Python/executor.c +++ b/Python/executor.c @@ -25,6 +25,7 @@ #undef DEOPT_IF #define DEOPT_IF(COND, INSTNAME) \ if ((COND)) { \ + UOP_STAT_INC(INSTNAME, miss); \ goto deoptimize; \ } @@ -93,7 +94,7 @@ _PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject (int)(stack_pointer - _PyFrame_Stackbase(frame))); pc++; OPT_STAT_INC(uops_executed); - UOP_EXE_INC(opcode); + UOP_STAT_INC(opcode, execution_count); #ifdef Py_STATS trace_uop_execution_counter++; #endif diff --git a/Python/specialize.c b/Python/specialize.c index 49633b103b3815..0e93897212e6e3 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -247,6 +247,9 @@ print_optimization_stats(FILE *out, OptimizationStats *stats) if (stats->opcode[i].execution_count) { fprintf(out, "uops[%s].execution_count : %" PRIu64 "\n", names[i], stats->opcode[i].execution_count); } + if (stats->opcode[i].miss) { + fprintf(out, "uops[%s].specialization.miss : %" PRIu64 "\n", names[i], stats->opcode[i].miss); + } } for (int i = 0; i < 256; i++) { diff --git a/Tools/scripts/summarize_stats.py b/Tools/scripts/summarize_stats.py index 071b24a59ef44e..7c239c422d55c7 100644 --- a/Tools/scripts/summarize_stats.py +++ b/Tools/scripts/summarize_stats.py @@ -1016,7 +1016,7 @@ def iter_optimization_tables(base_stats: Stats, head_stats: Stats | None = None) ], ) yield Section( - "Uop stats", + "Uop execution stats", "", [ Table( From 8bc674392757a359fb652cb5c63045a469a0a30d Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Mon, 9 Oct 2023 09:52:21 -0400 Subject: [PATCH 2/4] Fix non-pystats compile --- Include/internal/pycore_code.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 6c968e100eb4cc..4f126abf47644a 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -308,7 +308,7 @@ PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void); #define EVAL_CALL_STAT_INC_IF_FUNCTION(name, callable) ((void)0) #define GC_STAT_ADD(gen, name, n) ((void)0) #define OPT_STAT_INC(name) ((void)0) -#define UOP_EXE_INC(opname) ((void)0) +#define UOP_STAT_INC(opname, name) ((void)0) #define OPT_UNSUPPORTED_OPCODE(opname) ((void)0) #define OPT_HIST(length, name) ((void)0) #endif // !Py_STATS From a08a127247539cd9336dc1870347f28894fb0f22 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Mon, 9 Oct 2023 12:01:25 -0400 Subject: [PATCH 3/4] Fix ratio error --- Tools/scripts/summarize_stats.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/Tools/scripts/summarize_stats.py b/Tools/scripts/summarize_stats.py index 7c239c422d55c7..d976e633fc9688 100644 --- a/Tools/scripts/summarize_stats.py +++ b/Tools/scripts/summarize_stats.py @@ -419,8 +419,6 @@ def __init__(self, num: int, den: int | None, percentage: bool = True): self.num = num self.den = den self.percentage = percentage - if den == 0 and num != 0: - raise ValueError("Invalid denominator") def __float__(self): if self.den == 0: From 8f9fe760ab574fdcf43a7b0bf0c17c1f02ab39b5 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Tue, 24 Oct 2023 13:32:54 -0400 Subject: [PATCH 4/4] Don't fix unrelated bug --- Tools/scripts/summarize_stats.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tools/scripts/summarize_stats.py b/Tools/scripts/summarize_stats.py index d976e633fc9688..7c239c422d55c7 100644 --- a/Tools/scripts/summarize_stats.py +++ b/Tools/scripts/summarize_stats.py @@ -419,6 +419,8 @@ def __init__(self, num: int, den: int | None, percentage: bool = True): self.num = num self.den = den self.percentage = percentage + if den == 0 and num != 0: + raise ValueError("Invalid denominator") def __float__(self): if self.den == 0: