mirror of
https://github.com/python/cpython.git
synced 2025-07-07 19:35:27 +00:00
gh-132952: Speed up startup by importing _io instead of io (#132957)
This commit is contained in:
parent
7f16f1bc11
commit
58567cc18c
11 changed files with 50 additions and 6 deletions
|
@ -1023,6 +1023,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(intern));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(intern));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(intersection));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(intersection));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(interval));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(interval));
|
||||||
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(io));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(is_running));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(is_running));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(is_struct));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(is_struct));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(isatty));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(isatty));
|
||||||
|
|
|
@ -514,6 +514,7 @@ struct _Py_global_strings {
|
||||||
STRUCT_FOR_ID(intern)
|
STRUCT_FOR_ID(intern)
|
||||||
STRUCT_FOR_ID(intersection)
|
STRUCT_FOR_ID(intersection)
|
||||||
STRUCT_FOR_ID(interval)
|
STRUCT_FOR_ID(interval)
|
||||||
|
STRUCT_FOR_ID(io)
|
||||||
STRUCT_FOR_ID(is_running)
|
STRUCT_FOR_ID(is_running)
|
||||||
STRUCT_FOR_ID(is_struct)
|
STRUCT_FOR_ID(is_struct)
|
||||||
STRUCT_FOR_ID(isatty)
|
STRUCT_FOR_ID(isatty)
|
||||||
|
|
1
Include/internal/pycore_runtime_init_generated.h
generated
1
Include/internal/pycore_runtime_init_generated.h
generated
|
@ -1021,6 +1021,7 @@ extern "C" {
|
||||||
INIT_ID(intern), \
|
INIT_ID(intern), \
|
||||||
INIT_ID(intersection), \
|
INIT_ID(intersection), \
|
||||||
INIT_ID(interval), \
|
INIT_ID(interval), \
|
||||||
|
INIT_ID(io), \
|
||||||
INIT_ID(is_running), \
|
INIT_ID(is_running), \
|
||||||
INIT_ID(is_struct), \
|
INIT_ID(is_struct), \
|
||||||
INIT_ID(isatty), \
|
INIT_ID(isatty), \
|
||||||
|
|
|
@ -1844,6 +1844,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
|
||||||
_PyUnicode_InternStatic(interp, &string);
|
_PyUnicode_InternStatic(interp, &string);
|
||||||
assert(_PyUnicode_CheckConsistency(string, 1));
|
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||||
assert(PyUnicode_GET_LENGTH(string) != 1);
|
assert(PyUnicode_GET_LENGTH(string) != 1);
|
||||||
|
string = &_Py_ID(io);
|
||||||
|
_PyUnicode_InternStatic(interp, &string);
|
||||||
|
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||||
|
assert(PyUnicode_GET_LENGTH(string) != 1);
|
||||||
string = &_Py_ID(is_running);
|
string = &_Py_ID(is_running);
|
||||||
_PyUnicode_InternStatic(interp, &string);
|
_PyUnicode_InternStatic(interp, &string);
|
||||||
assert(_PyUnicode_CheckConsistency(string, 1));
|
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||||
|
|
|
@ -60,9 +60,6 @@ from _io import (DEFAULT_BUFFER_SIZE, BlockingIOError, UnsupportedOperation,
|
||||||
IncrementalNewlineDecoder, text_encoding, TextIOWrapper)
|
IncrementalNewlineDecoder, text_encoding, TextIOWrapper)
|
||||||
|
|
||||||
|
|
||||||
# Pretend this exception was created here.
|
|
||||||
UnsupportedOperation.__module__ = "io"
|
|
||||||
|
|
||||||
# for seek()
|
# for seek()
|
||||||
SEEK_SET = 0
|
SEEK_SET = 0
|
||||||
SEEK_CUR = 1
|
SEEK_CUR = 1
|
||||||
|
|
|
@ -73,7 +73,7 @@ import sys
|
||||||
import os
|
import os
|
||||||
import builtins
|
import builtins
|
||||||
import _sitebuiltins
|
import _sitebuiltins
|
||||||
import io
|
import _io as io
|
||||||
import stat
|
import stat
|
||||||
|
|
||||||
# Prefixes for site-packages; add additional prefixes like /usr/local here
|
# Prefixes for site-packages; add additional prefixes like /usr/local here
|
||||||
|
|
|
@ -445,6 +445,25 @@ class IOTest(unittest.TestCase):
|
||||||
self.assertRaises(exc, fp.seek, 1, self.SEEK_CUR)
|
self.assertRaises(exc, fp.seek, 1, self.SEEK_CUR)
|
||||||
self.assertRaises(exc, fp.seek, -1, self.SEEK_END)
|
self.assertRaises(exc, fp.seek, -1, self.SEEK_END)
|
||||||
|
|
||||||
|
@support.cpython_only
|
||||||
|
def test_startup_optimization(self):
|
||||||
|
# gh-132952: Test that `io` is not imported at startup and that the
|
||||||
|
# __module__ of UnsupportedOperation is set to "io".
|
||||||
|
assert_python_ok("-S", "-c", textwrap.dedent(
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
assert "io" not in sys.modules
|
||||||
|
try:
|
||||||
|
sys.stdin.truncate()
|
||||||
|
except Exception as e:
|
||||||
|
typ = type(e)
|
||||||
|
assert typ.__module__ == "io", (typ, typ.__module__)
|
||||||
|
assert typ.__name__ == "UnsupportedOperation", (typ, typ.__name__)
|
||||||
|
else:
|
||||||
|
raise AssertionError("Expected UnsupportedOperation")
|
||||||
|
"""
|
||||||
|
))
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
|
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
|
||||||
def test_optional_abilities(self):
|
def test_optional_abilities(self):
|
||||||
# Test for OSError when optional APIs are not supported
|
# Test for OSError when optional APIs are not supported
|
||||||
|
|
|
@ -8,6 +8,7 @@ import unittest
|
||||||
import test.support
|
import test.support
|
||||||
from test import support
|
from test import support
|
||||||
from test.support.script_helper import assert_python_ok
|
from test.support.script_helper import assert_python_ok
|
||||||
|
from test.support import import_helper
|
||||||
from test.support import os_helper
|
from test.support import os_helper
|
||||||
from test.support import socket_helper
|
from test.support import socket_helper
|
||||||
from test.support import captured_stderr
|
from test.support import captured_stderr
|
||||||
|
@ -574,6 +575,17 @@ class ImportSideEffectTests(unittest.TestCase):
|
||||||
code = e.code
|
code = e.code
|
||||||
self.assertEqual(code, 200, msg="Can't find " + url)
|
self.assertEqual(code, 200, msg="Can't find " + url)
|
||||||
|
|
||||||
|
@support.cpython_only
|
||||||
|
def test_lazy_imports(self):
|
||||||
|
import_helper.ensure_lazy_imports("site", [
|
||||||
|
"io",
|
||||||
|
"locale",
|
||||||
|
"traceback",
|
||||||
|
"atexit",
|
||||||
|
"warnings",
|
||||||
|
"textwrap",
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
class StartupImportTests(unittest.TestCase):
|
class StartupImportTests(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Speed up startup with the ``-S`` argument by importing the
|
||||||
|
private ``_io`` module instead of :mod:`io`. This fixes a performance
|
||||||
|
regression introduced earlier in Python 3.14 development and restores performance
|
||||||
|
to the level of Python 3.13.
|
|
@ -661,6 +661,11 @@ iomodule_exec(PyObject *m)
|
||||||
"UnsupportedOperation", PyExc_OSError, PyExc_ValueError);
|
"UnsupportedOperation", PyExc_OSError, PyExc_ValueError);
|
||||||
if (state->unsupported_operation == NULL)
|
if (state->unsupported_operation == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (PyObject_SetAttrString(state->unsupported_operation,
|
||||||
|
"__module__", &_Py_ID(io)) < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (PyModule_AddObjectRef(m, "UnsupportedOperation",
|
if (PyModule_AddObjectRef(m, "UnsupportedOperation",
|
||||||
state->unsupported_operation) < 0)
|
state->unsupported_operation) < 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2755,7 +2755,7 @@ init_set_builtins_open(void)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(wrapper = PyImport_ImportModuleAttrString("io", "open"))) {
|
if (!(wrapper = PyImport_ImportModuleAttrString("_io", "open"))) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2800,7 +2800,7 @@ init_sys_streams(PyThreadState *tstate)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!(iomod = PyImport_ImportModule("io"))) {
|
if (!(iomod = PyImport_ImportModule("_io"))) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue