[issue22557] Local import is too slow

2016-08-06 Thread Serhiy Storchaka

Changes by Serhiy Storchaka :


--
resolution:  -> fixed
stage: patch review -> resolved
status: open -> closed

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2016-08-02 Thread Roundup Robot

Roundup Robot added the comment:

New changeset 64f195790a3a by Serhiy Storchaka in branch 'default':
Issue #22557: Now importing already imported modules is up to 2.5 times faster.
https://hg.python.org/cpython/rev/64f195790a3a

--
nosy: +python-dev

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2016-08-02 Thread Serhiy Storchaka

Serhiy Storchaka added the comment:

Thank you for your review Brett.

--
assignee:  -> serhiy.storchaka

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2016-07-24 Thread Serhiy Storchaka

Serhiy Storchaka added the comment:

Seems not all such easy. Looking in sys.module is not enough, we should check 
__spec__._initializing.

Following patch moves optimizations to PyImport_ImportModuleLevelObject (C 
implementation of standard __import__). Main optimizations:

1. PyImport_ImportModuleLevelObject is called directly if builtins.__import__ 
is standard __import__.

2. Import lock is not acquired for looking up in sys.modules and other 
operations. Some of these operations are atomic in C (guarded by GIL), others 
are used only for optimization and race condition can cause only insignificant 
slow down.

3. Avoided creating empty dict for globals, looking up __package__ and __spec__ 
if they are not needed.

4. Saving standard __import__ in interpreter state.

Microbenchmarking results:

$ ./python -m timeit 'import os'
Unpatched:  100 loops, best of 3: 0.845 usec per loop
Patched:100 loops, best of 3: 0.338 usec per loop

$ ./python -m timeit 'import os.path'
Unpatched:  10 loops, best of 3: 2.07 usec per loop
Patched:100 loops, best of 3: 0.884 usec per loop

$ ./python -m timeit 'from os import path'
Unpatched:  10 loops, best of 3: 3.7 usec per loop
Patched:10 loops, best of 3: 2.77 usec per loop

--
Added file: http://bugs.python.org/file43869/faster_import_6.patch

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2016-06-27 Thread Serhiy Storchaka

Serhiy Storchaka added the comment:

faster_import_pkg.patch optimizes also an import of names with dots.

$ ./python -m timeit 'import os.path'
Unpatched:10 loops, best of 3: 2.08 usec per loop
faster_import_5.patch:100 loops, best of 3: 1.79 usec per loop
faster_import_pkg.patch:  100 loops, best of 3: 0.474 usec per loop

--
Added file: http://bugs.python.org/file43567/faster_import_pkg.patch

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2016-06-20 Thread Serhiy Storchaka

Serhiy Storchaka added the comment:

Thanks Victor.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2016-06-20 Thread STINNER Victor

STINNER Victor added the comment:

I rebased  faster_import_4.patch on default.

--
Added file: http://bugs.python.org/file43491/faster_import_4.patch

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2016-06-20 Thread STINNER Victor

STINNER Victor added the comment:

> Do you happen to know why you didn't get a review link for your patch, Serhiy?

faster_import_4.patch is based on the revision d736c9490333 which is not part 
of the CPython repository.

--
nosy: +haypo

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2016-06-20 Thread Brett Cannon

Brett Cannon added the comment:

Do you happen to know why you didn't get a review link for your patch, Serhiy?

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2016-06-19 Thread Serhiy Storchaka

Serhiy Storchaka added the comment:

Fixed bugs making test_importlib failing.

Microbenchmark results on faster machine:

$ ./python -m timeit 'import locale'
Unpatched:  100 loops, best of 3: 0.839 usec per loop
Patched:1000 loops, best of 3: 0.176 usec per loop

$ ./python -m timeit 'import os.path'
Unpatched:  10 loops, best of 3: 2.02 usec per loop
Patched:100 loops, best of 3: 1.77 usec per loop

$ ./python -m timeit 'from locale import getlocale'
Unpatched:  10 loops, best of 3: 3.69 usec per loop
Patched:10 loops, best of 3: 3.39 usec per loop

And it looks to me that there is a bug in existing code (opened separate 
issue27352).

0.839 usec is not very slow by CPython's standards, but is equal to about 50 
assignments to local variable, 15 attribute revolvings or 5 simple function 
calls. If some module is optionally needed in fast function, the overhead of 
local import can be significant. We can lazily initialize global variable (the 
second example in msg228561), but this code looks more cumbersome.

--
stage:  -> patch review
versions: +Python 3.6 -Python 3.5
Added file: http://bugs.python.org/file43471/faster_import_4.patch

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2014-10-14 Thread Serhiy Storchaka

Serhiy Storchaka added the comment:

Yes, my CPU is slow.

Here is a patch which factors out IMPORT_NAME into a separate import_name() 
function and adds optimization for more general case when __import__ is not 
overloaded.

--
Added file: http://bugs.python.org/file36912/faster_import_3.patch

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22557
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2014-10-10 Thread Antoine Pitrou

Antoine Pitrou added the comment:

The issue is local imports, not imports of the locale module :-)

--
title: Locale import is too slow - Local import is too slow

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22557
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2014-10-05 Thread Serhiy Storchaka

Changes by Serhiy Storchaka storch...@gmail.com:


--
title: Locale import is too slow - Local import is too slow

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22557
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2014-10-05 Thread Antoine Pitrou

Antoine Pitrou added the comment:

This would sound reasonable to me, but I wonder if it may change behaviour with 
weird custom __import__ overrides.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22557
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2014-10-05 Thread Nick Coghlan

Nick Coghlan added the comment:

__import__ is intended as an absolute override (including of the sys.modules 
cache lookup), so we can't bypass it without breaking backwards compatibility.

It's possible there is room for other optimisations that don't break the import 
override semantics (such as a fast path for when __import__ is the standard 
import function).

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22557
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2014-10-05 Thread Eric V. Smith

Changes by Eric V. Smith e...@trueblade.com:


--
nosy: +eric.smith

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22557
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2014-10-05 Thread Serhiy Storchaka

Serhiy Storchaka added the comment:

I'm not experienced in import machinery. Here is preliminary patch which 
implements my idea for particular case.

Performance effect is almost so good as manual caching in a global.

 import timeit
 def f():
...  import locale
... 
 min(timeit.repeat(f, number=10, repeat=10))
0.0956359819417

Of course it breaks tests.

 It's possible there is room for other optimisations that don't break the
 import override semantics (such as a fast path for when __import__ is the
 standard import function).

Good idea.

--
keywords: +patch
Added file: http://bugs.python.org/file36814/faster_import.patch

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22557
___diff -r 85de13b746ac Lib/test/test_import.py
--- a/Lib/test/test_import.py   Sat Oct 04 16:09:02 2014 +0300
+++ b/Lib/test/test_import.py   Sun Oct 05 17:15:42 2014 +0300
@@ -312,7 +312,7 @@ class ImportTests(unittest.TestCase):
 
 @cpython_only
 def test_delete_builtins_import(self):
-args = [-c, del __builtins__.__import__; import os]
+args = [-c, del __builtins__.__import__; import this]
 popen = script_helper.spawn_python(*args)
 stdout, stderr = popen.communicate()
 self.assertIn(bImportError, stdout)
diff -r 85de13b746ac Python/ceval.c
--- a/Python/ceval.cSat Oct 04 16:09:02 2014 +0300
+++ b/Python/ceval.cSun Oct 05 17:15:42 2014 +0300
@@ -2464,16 +2464,42 @@ PyEval_EvalFrameEx(PyFrameObject *f, int
 TARGET(IMPORT_NAME) {
 _Py_IDENTIFIER(__import__);
 PyObject *name = GETITEM(names, oparg);
-PyObject *func = _PyDict_GetItemId(f-f_builtins, 
PyId___import__);
+PyObject *func;
 PyObject *from, *level, *args, *res;
+from = POP();
+level = TOP();
+if (from == Py_None  PyUnicode_Check(name)) {
+if (PyLong_AsLong(level) == 0) {
+Py_ssize_t i = PyUnicode_FindChar(name, '.',
+0, PyUnicode_GET_LENGTH(name), 1);
+if (i == -1) {
+res = PyDict_GetItem(PyImport_GetModuleDict(), name);
+if (res != NULL) {
+Py_INCREF(res);
+Py_DECREF(level);
+Py_DECREF(from);
+SET_TOP(res);
+DISPATCH();
+}
+}
+else if (i == -2) {
+Py_DECREF(level);
+Py_DECREF(from);
+STACKADJ(-1);
+goto error;
+}
+}
+else if (PyErr_Occurred())
+PyErr_Clear();
+}
+func = _PyDict_GetItemId(f-f_builtins, PyId___import__);
 if (func == NULL) {
 PyErr_SetString(PyExc_ImportError,
 __import__ not found);
+STACKADJ(-1);
 goto error;
 }
 Py_INCREF(func);
-from = POP();
-level = TOP();
 if (PyLong_AsLong(level) != -1 || PyErr_Occurred())
 args = PyTuple_Pack(5,
 name,
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2014-10-05 Thread Serhiy Storchaka

Serhiy Storchaka added the comment:

Second version of the patch uses fast patch only when builtin __import__ is 
not overridden. It is slightly slower (due to lookup of __import__).

 import timeit
 def f():
... import locale
... 
 min(timeit.repeat(f, number=10, repeat=10))
0.1050230371179

The code is simpler, but still some cumbersome. It would be good to optimize 
also from locale import getlocale.

--
Added file: http://bugs.python.org/file36816/faster_import_2.patch

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22557
___diff -r 85de13b746ac Python/ceval.c
--- a/Python/ceval.cSat Oct 04 16:09:02 2014 +0300
+++ b/Python/ceval.cSun Oct 05 17:55:26 2014 +0300
@@ -2463,6 +2463,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int
 
 TARGET(IMPORT_NAME) {
 _Py_IDENTIFIER(__import__);
+static PyObject *orig_func = NULL;
 PyObject *name = GETITEM(names, oparg);
 PyObject *func = _PyDict_GetItemId(f-f_builtins, 
PyId___import__);
 PyObject *from, *level, *args, *res;
@@ -2474,6 +2475,29 @@ PyEval_EvalFrameEx(PyFrameObject *f, int
 Py_INCREF(func);
 from = POP();
 level = TOP();
+if (orig_func == NULL)
+orig_func = _PyDict_GetItemId(
+PyThreadState_GET()-interp-builtins_copy,
+PyId___import__);
+if (func == orig_func  from == Py_None 
+PyLong_Check(level)  Py_SIZE(level) == 0 
+PyUnicode_Check(name)) {
+Py_ssize_t i = PyUnicode_FindChar(name, '.',
+0, PyUnicode_GET_LENGTH(name), 1);
+if (i == -1) {
+res = PyDict_GetItem(PyImport_GetModuleDict(), name);
+if (res != NULL) {
+Py_INCREF(res);
+Py_DECREF(func);
+Py_DECREF(level);
+Py_DECREF(from);
+SET_TOP(res);
+DISPATCH();
+}
+}
+else if (i == -2)
+PyErr_Clear();
+}
 if (PyLong_AsLong(level) != -1 || PyErr_Occurred())
 args = PyTuple_Pack(5,
 name,
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2014-10-05 Thread Antoine Pitrou

Antoine Pitrou added the comment:

I would suggest factoring out IMPORT_NAME into a separate import_name() 
function, like is already one for import_from().

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22557
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue22557] Local import is too slow

2014-10-05 Thread Antoine Pitrou

Antoine Pitrou added the comment:

Some more general comments about this:

- Let's keep in mind the absolute numbers. 0.450120013341 for 10 
iterations is 4.5ms per iteration. This is not very slow by CPython's standards.

- I wonder if you ran your benchmark in debug mode or if your CPU is slow :-) I 
get around 0.5ms per iteration here.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue22557
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com