<div dir="ltr">Robert, <div><br></div><div><br></div><div>Thanks for sharing this!</div><div>Now I know how to speed up start of Rally ;) </div><div><br></div><div><br></div><div>Best regards,</div><div>Boris Pavlovic </div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Mar 17, 2015 at 2:23 AM, Robert Collins <span dir="ltr"><<a href="mailto:robertc@robertcollins.net" target="_blank">robertc@robertcollins.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">So, one of the things that we sometimes do in an __init__.py is this:<br>
<br>
all = ["submodule"]<br>
import submodule<br>
<br>
This means users can do<br>
<br>
import mymodule<br>
mymodule.submodule<br>
<br>
and it works.<br>
<br>
This is actually a bit of an anti-pattern in the Python space, because<br>
to import mymodule.othersubmodule we'll always pay the import cost of<br>
mymodule.submodule whether or not any code from it is used.<br>
<br>
And the import cost can be substantial.<br>
<br>
Take for instance <a href="http://pad.lv/1431649" target="_blank">http://pad.lv/1431649</a> which is about osc being slow,<br>
and some of the slowness is likely due to the cost of importing unused<br>
modules from python-keystoneclient.<br>
<br>
In general, it is important for snappy short lived processes that only<br>
the needed code is imported. And that implies a few things in library<br>
code that they consume. CLI's are the most prevalent example of such<br>
short lived processes (including rootwrap's CLI thunk still).<br>
<a href="https://files.bemusement.org/talks/OSDC2008-FastPython/" target="_blank">https://files.bemusement.org/talks/OSDC2008-FastPython/</a> is a nice<br>
summary of this btw by one of the other bzr cores back in the day -<br>
and not much has changed since then. We'll likely want to port the<br>
profile-imports facility over to our tooling to really track things<br>
down, since the default Python tools don't give us timestamps (hey,<br>
someone want to add that to python -v ?).<br>
<br>
So - the constraints I'd propose for libraries we use from CLI's,<br>
including our python-*client:<br>
 - import libraryname should be fast - no more than a ms or so. Timing<br>
with .pyc files is ok.<br>
   To time it (hot cache) - something like the following<br>
     python -m timeit -s 'import sys; o=dict(sys.modules)' 'import<br>
keystoneclient; sys.modules.clear();sys.modules.update(o)'<br>
   right now keystoneclient is somewhat slow: 10 loops, best of 3: 220<br>
msec per loop<br>
   Timing cold cache is harder, something like:<br>
    import datetime<br>
    import subprocess<br>
    subprocess.call('echo 3 | sudo tee /proc/sys/vm/drop_caches', shell=True)<br>
    start = datetime.datetime.now()<br>
    import keystoneclient<br>
    stop = datetime.datetime.now()<br>
    print stop-start<br>
<br>
   should get a decent approximation. Right now I see 0:00:00.506059 -<br>
or 500ms. On an SSD. Try it on spinning rust and I think you'll cry.<br>
<br>
 - as a corollary, __init__ should not import things unless *every use<br>
of the library ever* will need it.<br>
<br>
-Rob<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
Robert Collins <<a href="mailto:rbtcollins@hp.com">rbtcollins@hp.com</a>><br>
Distinguished Technologist<br>
HP Converged Cloud<br>
<br>
__________________________________________________________________________<br>
OpenStack Development Mailing List (not for usage questions)<br>
Unsubscribe: <a href="http://OpenStack-dev-request@lists.openstack.org?subject:unsubscribe" target="_blank">OpenStack-dev-request@lists.openstack.org?subject:unsubscribe</a><br>
<a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
</font></span></blockquote></div><br></div>