gh-108753: Enhance pystats (#108754)

Statistics gathering is now off by default. Use the "-X pystats"
command line option or set the new PYTHONSTATS environment variable
to 1 to turn statistics gathering on at Python startup.

Statistics are no longer dumped at exit if statistics gathering was
off or statistics have been cleared.

Changes:

* Add PYTHONSTATS environment variable.
* sys._stats_dump() now returns False if statistics are not dumped
  because they are all equal to zero.
* Add PyConfig._pystats member.
* Add tests on sys functions and on setting PyConfig._pystats to 1.
* Add Include/cpython/pystats.h and Include/internal/pycore_pystats.h
  header files.
* Rename '_py_stats' variable to '_Py_stats'.
* Exclude Include/cpython/pystats.h from the Py_LIMITED_API.
* Move pystats.h include from object.h to Python.h.
* Add _Py_StatsOn() and _Py_StatsOff() functions. Remove
  '_py_stats_struct' variable from the API: make it static in
  specialize.c.
* Document API in Include/pystats.h and Include/cpython/pystats.h.
* Complete pystats documentation in Doc/using/configure.rst.
* Don't write "all zeros" stats: if _stats_off() and _stats_clear()
  or _stats_dump() were called.
* _PyEval_Fini() now always call _Py_PrintSpecializationStats() which
  does nothing if stats are all zeros.

Co-authored-by: Michael Droettboom <mdboom@gmail.com>
This commit is contained in:
Victor Stinner 2023-09-06 17:54:59 +02:00 committed by GitHub
parent 8ff1142578
commit a0773b89df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 403 additions and 184 deletions

View file

@ -9,6 +9,7 @@
#include "pycore_pylifecycle.h" // _Py_PreInitializeFromConfig()
#include "pycore_pymem.h" // _PyMem_SetDefaultAllocator()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_pystats.h" // _Py_StatsOn()
#include "osdefs.h" // DELIM
@ -186,7 +187,11 @@ static const char usage_envvars[] =
"PYTHONSAFEPATH : don't prepend a potentially unsafe path to sys.path (-P)\n"
"PYTHONUNBUFFERED : disable stdout/stderr buffering (-u)\n"
"PYTHONVERBOSE : trace import statements (-v)\n"
"PYTHONWARNINGS=arg : warning control (-W arg)\n";
"PYTHONWARNINGS=arg : warning control (-W arg)\n"
#ifdef Py_STATS
"PYTHONSTATS : turns on statistics gathering\n"
#endif
;
#if defined(MS_WINDOWS)
# define PYTHONHOMEHELP "<prefix>\\python{major}{minor}"
@ -630,6 +635,9 @@ config_check_consistency(const PyConfig *config)
assert(config->int_max_str_digits >= 0);
// config->use_frozen_modules is initialized later
// by _PyConfig_InitImportConfig().
#ifdef Py_STATS
assert(config->_pystats >= 0);
#endif
return 1;
}
#endif
@ -951,6 +959,9 @@ _PyConfig_Copy(PyConfig *config, const PyConfig *config2)
COPY_WSTRLIST(orig_argv);
COPY_ATTR(_is_python_build);
COPY_ATTR(int_max_str_digits);
#ifdef Py_STATS
COPY_ATTR(_pystats);
#endif
#undef COPY_ATTR
#undef COPY_WSTR_ATTR
@ -1058,6 +1069,9 @@ _PyConfig_AsDict(const PyConfig *config)
SET_ITEM_INT(safe_path);
SET_ITEM_INT(_is_python_build);
SET_ITEM_INT(int_max_str_digits);
#ifdef Py_STATS
SET_ITEM_INT(_pystats);
#endif
return dict;
@ -1365,6 +1379,9 @@ _PyConfig_FromDict(PyConfig *config, PyObject *dict)
GET_UINT(safe_path);
GET_UINT(_is_python_build);
GET_INT(int_max_str_digits);
#ifdef Py_STATS
GET_UINT(_pystats);
#endif
#undef CHECK_VALUE
#undef GET_UINT
@ -2116,7 +2133,13 @@ config_read(PyConfig *config, int compute_path_config)
#ifdef Py_STATS
if (config_get_xoption(config, L"pystats")) {
_py_stats = &_py_stats_struct;
config->_pystats = 1;
}
else if (config_get_env(config, "PYTHONSTATS")) {
config->_pystats = 1;
}
if (config->_pystats < 0) {
config->_pystats = 0;
}
#endif
@ -2254,6 +2277,13 @@ _PyConfig_Write(const PyConfig *config, _PyRuntimeState *runtime)
{
return _PyStatus_NO_MEMORY();
}
#ifdef Py_STATS
if (config->_pystats) {
_Py_StatsOn();
}
#endif
return _PyStatus_OK();
}