mirror of
https://github.com/python/cpython.git
synced 2025-07-08 03:45:36 +00:00
gh-102567: Add -X importtime=2 for logging an importtime message for already-loaded modules (#118655)
Co-authored-by: Adam Turner <9087854+aa-turner@users.noreply.github.com>
This commit is contained in:
parent
e6f8e0a035
commit
c4bcc6a778
15 changed files with 166 additions and 44 deletions
|
@ -103,6 +103,15 @@ static struct _inittab *inittab_copy = NULL;
|
|||
#define FIND_AND_LOAD(interp) \
|
||||
(interp)->imports.find_and_load
|
||||
|
||||
#define _IMPORT_TIME_HEADER(interp) \
|
||||
do { \
|
||||
if (FIND_AND_LOAD((interp)).header) { \
|
||||
fputs("import time: self [us] | cumulative | imported package\n", \
|
||||
stderr); \
|
||||
FIND_AND_LOAD((interp)).header = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*******************/
|
||||
/* the import lock */
|
||||
|
@ -246,9 +255,13 @@ import_ensure_initialized(PyInterpreterState *interp, PyObject *mod, PyObject *n
|
|||
rc = _PyModuleSpec_IsInitializing(spec);
|
||||
Py_DECREF(spec);
|
||||
}
|
||||
if (rc <= 0) {
|
||||
if (rc == 0) {
|
||||
goto done;
|
||||
}
|
||||
else if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Wait until module is done importing. */
|
||||
PyObject *value = PyObject_CallMethodOneArg(
|
||||
IMPORTLIB(interp), &_Py_ID(_lock_unlock_module), name);
|
||||
|
@ -256,6 +269,19 @@ import_ensure_initialized(PyInterpreterState *interp, PyObject *mod, PyObject *n
|
|||
return -1;
|
||||
}
|
||||
Py_DECREF(value);
|
||||
|
||||
done:
|
||||
/* When -X importtime=2, print an import time entry even if an
|
||||
imported module has already been loaded.
|
||||
*/
|
||||
if (_PyInterpreterState_GetConfig(interp)->import_time == 2) {
|
||||
_IMPORT_TIME_HEADER(interp);
|
||||
#define import_level FIND_AND_LOAD(interp).import_level
|
||||
fprintf(stderr, "import time: cached | cached | %*s\n",
|
||||
import_level*2, PyUnicode_AsUTF8(name));
|
||||
#undef import_level
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3686,13 +3712,7 @@ import_find_and_load(PyThreadState *tstate, PyObject *abs_name)
|
|||
* _PyDict_GetItemIdWithError().
|
||||
*/
|
||||
if (import_time) {
|
||||
#define header FIND_AND_LOAD(interp).header
|
||||
if (header) {
|
||||
fputs("import time: self [us] | cumulative | imported package\n",
|
||||
stderr);
|
||||
header = 0;
|
||||
}
|
||||
#undef header
|
||||
_IMPORT_TIME_HEADER(interp);
|
||||
|
||||
import_level++;
|
||||
// ignore error: don't block import if reading the clock fails
|
||||
|
|
|
@ -153,7 +153,7 @@ static const PyConfigSpec PYCONFIG_SPEC[] = {
|
|||
SPEC(home, WSTR_OPT, READ_ONLY, NO_SYS),
|
||||
SPEC(thread_inherit_context, INT, READ_ONLY, NO_SYS),
|
||||
SPEC(context_aware_warnings, INT, READ_ONLY, NO_SYS),
|
||||
SPEC(import_time, BOOL, READ_ONLY, NO_SYS),
|
||||
SPEC(import_time, UINT, READ_ONLY, NO_SYS),
|
||||
SPEC(install_signal_handlers, BOOL, READ_ONLY, NO_SYS),
|
||||
SPEC(isolated, BOOL, READ_ONLY, NO_SYS), // sys.flags.isolated
|
||||
#ifdef MS_WINDOWS
|
||||
|
@ -312,7 +312,8 @@ The following implementation-specific options are available:\n\
|
|||
"-X gil=[0|1]: enable (1) or disable (0) the GIL; also PYTHON_GIL\n"
|
||||
#endif
|
||||
"\
|
||||
-X importtime: show how long each import takes; also PYTHONPROFILEIMPORTTIME\n\
|
||||
-X importtime[=2]: show how long each import takes; use -X importtime=2 to\
|
||||
log imports of already-loaded modules; also PYTHONPROFILEIMPORTTIME\n\
|
||||
-X int_max_str_digits=N: limit the size of int<->str conversions;\n\
|
||||
0 disables the limit; also PYTHONINTMAXSTRDIGITS\n\
|
||||
-X no_debug_ranges: don't include extra location information in code objects;\n\
|
||||
|
@ -1004,6 +1005,7 @@ _PyConfig_InitCompatConfig(PyConfig *config)
|
|||
memset(config, 0, sizeof(*config));
|
||||
|
||||
config->_config_init = (int)_PyConfig_INIT_COMPAT;
|
||||
config->import_time = -1;
|
||||
config->isolated = -1;
|
||||
config->use_environment = -1;
|
||||
config->dev_mode = -1;
|
||||
|
@ -2246,6 +2248,38 @@ config_init_run_presite(PyConfig *config)
|
|||
}
|
||||
#endif
|
||||
|
||||
static PyStatus
|
||||
config_init_import_time(PyConfig *config)
|
||||
{
|
||||
int importtime = 0;
|
||||
|
||||
const char *env = config_get_env(config, "PYTHONPROFILEIMPORTTIME");
|
||||
if (env) {
|
||||
if (_Py_str_to_int(env, &importtime) != 0) {
|
||||
importtime = 1;
|
||||
}
|
||||
if (importtime < 0 || importtime > 2) {
|
||||
return _PyStatus_ERR(
|
||||
"PYTHONPROFILEIMPORTTIME: numeric values other than 1 and 2 "
|
||||
"are reserved for future use.");
|
||||
}
|
||||
}
|
||||
|
||||
const wchar_t *x_value = config_get_xoption_value(config, L"importtime");
|
||||
if (x_value) {
|
||||
if (*x_value == 0 || config_wstr_to_int(x_value, &importtime) != 0) {
|
||||
importtime = 1;
|
||||
}
|
||||
if (importtime < 0 || importtime > 2) {
|
||||
return _PyStatus_ERR(
|
||||
"-X importtime: values other than 1 and 2 "
|
||||
"are reserved for future use.");
|
||||
}
|
||||
}
|
||||
|
||||
config->import_time = importtime;
|
||||
return _PyStatus_OK();
|
||||
}
|
||||
|
||||
static PyStatus
|
||||
config_read_complex_options(PyConfig *config)
|
||||
|
@ -2257,17 +2291,19 @@ config_read_complex_options(PyConfig *config)
|
|||
config->faulthandler = 1;
|
||||
}
|
||||
}
|
||||
if (config_get_env(config, "PYTHONPROFILEIMPORTTIME")
|
||||
|| config_get_xoption(config, L"importtime")) {
|
||||
config->import_time = 1;
|
||||
}
|
||||
|
||||
if (config_get_env(config, "PYTHONNODEBUGRANGES")
|
||||
|| config_get_xoption(config, L"no_debug_ranges")) {
|
||||
config->code_debug_ranges = 0;
|
||||
}
|
||||
|
||||
PyStatus status;
|
||||
if (config->import_time < 0) {
|
||||
status = config_init_import_time(config);
|
||||
if (_PyStatus_EXCEPTION(status)) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (config->tracemalloc < 0) {
|
||||
status = config_init_tracemalloc(config);
|
||||
if (_PyStatus_EXCEPTION(status)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue