]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-46072: Add --with-pystats configure option to simplify gathering of VM stats...
authorMark Shannon <mark@hotpy.org>
Wed, 15 Dec 2021 15:32:32 +0000 (15:32 +0000)
committerGitHub <noreply@github.com>
Wed, 15 Dec 2021 15:32:32 +0000 (15:32 +0000)
* Simplify specialization stats collection macros.

* Add --enable-pystats option to configure.

* Update specialization summary script to handle larger number of kinds

Include/internal/pycore_code.h
Misc/NEWS.d/next/Build/2021-12-15-10-37-44.bpo-46072.GgeAU3.rst [new file with mode: 0644]
Modules/_opcode.c
Python/ceval.c
Python/specialize.c
Tools/scripts/summarize_specialization_stats.py
configure
configure.ac
pyconfig.h.in

index b0463e361718a536dce83361f1b6e90da748c598..e9b1ad406496a39cb7aad11bfe26f57da9e52fc3 100644 (file)
@@ -276,22 +276,11 @@ void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
                              SpecializedCacheEntry *cache);
 void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache);
 
-#define PRINT_SPECIALIZATION_STATS 0
-#define PRINT_SPECIALIZATION_STATS_DETAILED 0
-#define PRINT_SPECIALIZATION_STATS_TO_FILE 0
 
-#ifdef Py_DEBUG
-#define COLLECT_SPECIALIZATION_STATS 1
-#define COLLECT_SPECIALIZATION_STATS_DETAILED 1
-#else
-#define COLLECT_SPECIALIZATION_STATS PRINT_SPECIALIZATION_STATS
-#define COLLECT_SPECIALIZATION_STATS_DETAILED PRINT_SPECIALIZATION_STATS_DETAILED
-#endif
+#ifdef Py_STATS
 
 #define SPECIALIZATION_FAILURE_KINDS 30
 
-#if COLLECT_SPECIALIZATION_STATS
-
 typedef struct _stats {
     uint64_t specialization_success;
     uint64_t specialization_failure;
@@ -300,15 +289,13 @@ typedef struct _stats {
     uint64_t miss;
     uint64_t deopt;
     uint64_t unquickened;
-#if COLLECT_SPECIALIZATION_STATS_DETAILED
     uint64_t specialization_failure_kinds[SPECIALIZATION_FAILURE_KINDS];
-#endif
 } SpecializationStats;
 
 extern SpecializationStats _specialization_stats[256];
 #define STAT_INC(opname, name) _specialization_stats[opname].name++
 #define STAT_DEC(opname, name) _specialization_stats[opname].name--
-void _Py_PrintSpecializationStats(void);
+void _Py_PrintSpecializationStats(int to_file);
 
 PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void);
 
diff --git a/Misc/NEWS.d/next/Build/2021-12-15-10-37-44.bpo-46072.GgeAU3.rst b/Misc/NEWS.d/next/Build/2021-12-15-10-37-44.bpo-46072.GgeAU3.rst
new file mode 100644 (file)
index 0000000..9cc8b6c
--- /dev/null
@@ -0,0 +1,2 @@
+Add a --with-pystats configure option to turn on internal statistics
+gathering.
index 39e30669559518c068ed1b5a62f2dc61b80af609..4812716c672718ba331fd05468d878e03a695ec3 100644 (file)
@@ -85,7 +85,7 @@ static PyObject *
 _opcode_get_specialization_stats_impl(PyObject *module)
 /*[clinic end generated code: output=fcbc32fdfbec5c17 input=e1f60db68d8ce5f6]*/
 {
-#if COLLECT_SPECIALIZATION_STATS
+#ifdef Py_STATS
     return _Py_GetSpecializationStats();
 #else
     Py_RETURN_NONE;
index b9444b22138f020f670c1c674e7e3291664e4220..87d6a2288e0dd03232edf8bf1408dec893594a0b 100644 (file)
@@ -349,8 +349,8 @@ PyEval_InitThreads(void)
 void
 _PyEval_Fini(void)
 {
-#if PRINT_SPECIALIZATION_STATS
-    _Py_PrintSpecializationStats();
+#ifdef Py_STATS
+    _Py_PrintSpecializationStats(1);
 #endif
 }
 
index 5cf327df475c7c5e22d992b95d0da71abdcbd68a..7d4387b1639a5d6b905e3ab7b951ea7fab380f3a 100644 (file)
@@ -39,7 +39,7 @@
 */
 
 Py_ssize_t _Py_QuickenedCount = 0;
-#if COLLECT_SPECIALIZATION_STATS
+#ifdef Py_STATS
 SpecializationStats _specialization_stats[256] = { 0 };
 
 #define ADD_STAT_TO_DICT(res, field) \
@@ -71,7 +71,6 @@ stats_to_dict(SpecializationStats *stats)
     ADD_STAT_TO_DICT(res, miss);
     ADD_STAT_TO_DICT(res, deopt);
     ADD_STAT_TO_DICT(res, unquickened);
-#if COLLECT_SPECIALIZATION_STATS_DETAILED
     PyObject *failure_kinds = PyTuple_New(SPECIALIZATION_FAILURE_KINDS);
     if (failure_kinds == NULL) {
         Py_DECREF(res);
@@ -92,7 +91,6 @@ stats_to_dict(SpecializationStats *stats)
         return NULL;
     }
     Py_DECREF(failure_kinds);
-#endif
     return res;
 }
 #undef ADD_STAT_TO_DICT
@@ -113,7 +111,7 @@ add_stat_dict(
     return err;
 }
 
-#if COLLECT_SPECIALIZATION_STATS
+#ifdef Py_STATS
 PyObject*
 _Py_GetSpecializationStats(void) {
     PyObject *stats = PyDict_New();
@@ -151,35 +149,34 @@ print_stats(FILE *out, SpecializationStats *stats, const char *name)
     PRINT_STAT(name, miss);
     PRINT_STAT(name, deopt);
     PRINT_STAT(name, unquickened);
-#if PRINT_SPECIALIZATION_STATS_DETAILED
     for (int i = 0; i < SPECIALIZATION_FAILURE_KINDS; i++) {
         fprintf(out, "    %s.specialization_failure_kinds[%d] : %" PRIu64 "\n",
             name, i, stats->specialization_failure_kinds[i]);
     }
-#endif
 }
 #undef PRINT_STAT
 
 void
-_Py_PrintSpecializationStats(void)
+_Py_PrintSpecializationStats(int to_file)
 {
     FILE *out = stderr;
-#if PRINT_SPECIALIZATION_STATS_TO_FILE
-    /* Write to a file instead of stderr. */
+    if (to_file) {
+        /* Write to a file instead of stderr. */
 # ifdef MS_WINDOWS
-    const char *dirname = "c:\\temp\\py_stats\\";
+        const char *dirname = "c:\\temp\\py_stats\\";
 # else
-    const char *dirname = "/tmp/py_stats/";
+        const char *dirname = "/tmp/py_stats/";
 # endif
-    char buf[48];
-    sprintf(buf, "%s%u_%u.txt", dirname, (unsigned)clock(), (unsigned)rand());
-    FILE *fout = fopen(buf, "w");
-    if (fout) {
-        out = fout;
-    }
-#else
-    fprintf(out, "Specialization stats:\n");
-#endif
+        char buf[48];
+        sprintf(buf, "%s%u_%u.txt", dirname, (unsigned)clock(), (unsigned)rand());
+        FILE *fout = fopen(buf, "w");
+        if (fout) {
+            out = fout;
+        }
+    }
+    else {
+        fprintf(out, "Specialization stats:\n");
+    }
     print_stats(out, &_specialization_stats[LOAD_ATTR], "load_attr");
     print_stats(out, &_specialization_stats[LOAD_GLOBAL], "load_global");
     print_stats(out, &_specialization_stats[LOAD_METHOD], "load_method");
@@ -194,7 +191,7 @@ _Py_PrintSpecializationStats(void)
     }
 }
 
-#if COLLECT_SPECIALIZATION_STATS_DETAILED
+#ifdef Py_STATS
 
 #define SPECIALIZATION_FAIL(opcode, kind) _specialization_stats[opcode].specialization_failure_kinds[kind]++
 
@@ -860,7 +857,7 @@ success:
 }
 
 
-#if COLLECT_SPECIALIZATION_STATS_DETAILED
+#ifdef Py_STATS
 static int
 load_method_fail_kind(DesciptorClassification kind)
 {
@@ -1086,7 +1083,7 @@ success:
     return 0;
 }
 
-#if COLLECT_SPECIALIZATION_STATS_DETAILED
+#ifdef Py_STATS
 static int
 binary_subscr_fail_kind(PyTypeObject *container_type, PyObject *sub)
 {
@@ -1380,7 +1377,7 @@ specialize_py_call(
     return 0;
 }
 
-#if COLLECT_SPECIALIZATION_STATS_DETAILED
+#ifdef Py_STATS
 static int
 builtin_call_fail_kind(int ml_flags)
 {
@@ -1459,7 +1456,7 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
     }
 }
 
-#if COLLECT_SPECIALIZATION_STATS_DETAILED
+#ifdef Py_STATS
 static int
 call_fail_kind(PyObject *callable)
 {
index cc3ef85933c0265306213b26476df5c85d263bf5..15b1887415e44fd44d37202a733d3880bd58192c 100644 (file)
@@ -24,7 +24,7 @@ def print_stats(name, family_stats):
     for key in ("specialization_success",  "specialization_failure"):
         print(f"  {key}:{family_stats[key]:>12}")
     total_failures = family_stats["specialization_failure"]
-    failure_kinds = [ 0 ] * 20
+    failure_kinds = [ 0 ] * 30
     for key in family_stats:
         if not key.startswith("specialization_failure_kind"):
             continue
index 583e7d1fe3b32c03c135074fb27e55876c8a144e..1ede29989d9481fe73e7321b934b28111e407ea8 100755 (executable)
--- a/configure
+++ b/configure
@@ -1006,6 +1006,7 @@ enable_shared
 enable_profiling
 with_pydebug
 with_trace_refs
+enable_pystats
 with_assertions
 enable_optimizations
 with_lto
@@ -1713,6 +1714,7 @@ Optional Features:
                           no)
   --enable-profiling      enable C-level code profiling with gprof (default is
                           no)
+  --enable-pystats        enable internal statistics gathering (default is no)
   --enable-optimizations  enable expensive, stable optimizations (PGO, etc.)
                           (default is no)
   --enable-loadable-sqlite-extensions
@@ -6913,6 +6915,29 @@ then
 
 $as_echo "#define Py_TRACE_REFS 1" >>confdefs.h
 
+fi
+
+
+# Check for --enable-pystats
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-pystats" >&5
+$as_echo_n "checking for --enable-pystats... " >&6; }
+# Check whether --enable-pystats was given.
+if test "${enable_pystats+set}" = set; then :
+  enableval=$enable_pystats;
+else
+  enable_pystats=no
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_pystats" >&5
+$as_echo "$enable_pystats" >&6; }
+
+if test "x$enable_pystats" = xyes; then :
+
+
+$as_echo "#define Py_STATS 1" >>confdefs.h
+
+
 fi
 
 # Check for --with-assertions.
index 5256a61289e2239ffe4e3f692824db4fae9ce1a1..86404bcadeaba1f32d530692e1eeaccb62685040 100644 (file)
@@ -1387,6 +1387,21 @@ then
   AC_DEFINE(Py_TRACE_REFS, 1, [Define if you want to enable tracing references for debugging purpose])
 fi
 
+
+# Check for --enable-pystats
+AC_MSG_CHECKING([for --enable-pystats])
+AC_ARG_ENABLE([pystats],
+  [AS_HELP_STRING(
+    [--enable-pystats],
+    [enable internal statistics gathering (default is no)])],,
+  [enable_pystats=no]
+)
+AC_MSG_RESULT([$enable_pystats])
+
+AS_VAR_IF([enable_pystats], [yes], [
+  AC_DEFINE([Py_STATS], [1], [Define if you want to enable internal statistics gathering.])
+])
+
 # Check for --with-assertions.
 # This allows enabling assertions without Py_DEBUG.
 assertions='false'
@@ -6323,7 +6338,7 @@ AC_DEFUN([PY_STDLIB_MOD], [
 ])
 
 dnl Define simple stdlib extension module
-dnl Always enable unless the module is listed in py_stdlib_not_available 
+dnl Always enable unless the module is listed in py_stdlib_not_available
 dnl PY_STDLIB_MOD_SIMPLE([NAME], [CFLAGS], [LDFLAGS])
 dnl cflags and ldflags are optional
 AC_DEFUN([PY_STDLIB_MOD_SIMPLE], [
index efad243d0af8aa712fcb53717ba665ff568eeebb..e6e81654699d88cb67f43418e47de2b380918cb5 100644 (file)
    SipHash13: 3, externally defined: 0 */
 #undef Py_HASH_ALGORITHM
 
+/* Define if you want to enable internal statistics gathering. */
+#undef Py_STATS
+
 /* Define if you want to enable tracing references for debugging purpose */
 #undef Py_TRACE_REFS