* Simplify specialization stats collection macros.
* Add --enable-pystats option to configure.
* Update specialization summary script to handle larger number of kinds
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;
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);
--- /dev/null
+Add a --with-pystats configure option to turn on internal statistics
+gathering.
_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;
void
_PyEval_Fini(void)
{
-#if PRINT_SPECIALIZATION_STATS
- _Py_PrintSpecializationStats();
+#ifdef Py_STATS
+ _Py_PrintSpecializationStats(1);
#endif
}
*/
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) \
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);
return NULL;
}
Py_DECREF(failure_kinds);
-#endif
return res;
}
#undef ADD_STAT_TO_DICT
return err;
}
-#if COLLECT_SPECIALIZATION_STATS
+#ifdef Py_STATS
PyObject*
_Py_GetSpecializationStats(void) {
PyObject *stats = PyDict_New();
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");
}
}
-#if COLLECT_SPECIALIZATION_STATS_DETAILED
+#ifdef Py_STATS
#define SPECIALIZATION_FAIL(opcode, kind) _specialization_stats[opcode].specialization_failure_kinds[kind]++
}
-#if COLLECT_SPECIALIZATION_STATS_DETAILED
+#ifdef Py_STATS
static int
load_method_fail_kind(DesciptorClassification kind)
{
return 0;
}
-#if COLLECT_SPECIALIZATION_STATS_DETAILED
+#ifdef Py_STATS
static int
binary_subscr_fail_kind(PyTypeObject *container_type, PyObject *sub)
{
return 0;
}
-#if COLLECT_SPECIALIZATION_STATS_DETAILED
+#ifdef Py_STATS
static int
builtin_call_fail_kind(int ml_flags)
{
}
}
-#if COLLECT_SPECIALIZATION_STATS_DETAILED
+#ifdef Py_STATS
static int
call_fail_kind(PyObject *callable)
{
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
enable_profiling
with_pydebug
with_trace_refs
+enable_pystats
with_assertions
enable_optimizations
with_lto
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
$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.
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'
])
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], [
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