<div dir="ltr">I've been playing a bit with this trying to collect some data and measure how useful this would be. You can take a look at the script I'm using at: <a href="https://github.com/dmoisset/pycstats">https://github.com/dmoisset/pycstats</a> <div><br></div><div>What I'm measuring is:</div><div>1. Number of objects in the pyc, and how many of those are:</div><div>   * docstrings (I'm using a heuristic here which I'm not 100% sure it is correct)</div><div>   * lnotabs</div><div>   * Duplicate objects; these have not been discussed in this thread before but are another source of optimization I noticed while writing this. Essentially I'm refering to immutable constants that are instanced more than once and could be shared. You can also measure the effect of this optimization across modules and within a single module[1]</div><div>2. Bytes used in memory by the categories above (sum of sys.getsizeof() for each category).</div><div><br></div><div>I'm not measuring anything related to annotations because, as I mentioned before, they are generated piecemeal by executable bytecode so they are hard to separate</div><div><br></div><div>Running this on my python 3.6 pyc cache I get:</div><div><br></div><div><div>$ find /usr/lib/python3.6 -name '*.pyc' |xargs python3.6 pycstats.py </div><div>8645 docstrings, 1705441B</div><div>19060 lineno tables, 941702B</div><div>59382/202898 duplicate objects for 3101287/18582807 memory size</div></div><div><br></div><div>So this means around ~10% of the memory used after loading is used for docstrings, ~5% for lnotabs, and ~15% for objects that could be shared. The sharing assumes we can share betwwen modules, but even doing it within modules, you can get to ~7%. </div><div><br></div><div>In short, this could mean a 25%-35% reduction in memory use for code objects if the stdlib is a good benchmark.</div><div><br></div><div>Best,</div><div>D.</div><div><br></div><div>[1] Regarding duplicates, I've found some unexpected things within loaded code objects, for example instances of the small integer "1" with different id() than the singleton that cpython normally uses for "1", although most duplicates are some small strings, tuples with argument names, or . Something that could be interesting to write is a "pyc optimizer" that removes duplicates, this should be a gain at a minimal preprocessing cost.</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On 12 April 2018 at 15:16, Daniel Moisset <span dir="ltr"><<a href="mailto:dmoisset@machinalis.com" target="_blank">dmoisset@machinalis.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>One implementation difficulty specifically related to annotations, is that they are quite hard to find/extract from the code objects. Both docstrings and lnotab are within specific fields of the code object for their function/class/module; annotations are spread as individual constants (assuming PEP 563), which are loaded in bytecode through separate LOAD_CONST statements before creating the function object, and that can happen in the middle of bytecode for the higher level object (the module or class containing a function definition). So the change for achieving that will be more significant than just "add a couple of descriptors to function objects and change the module marshalling code".<br></div><div><br></div><div>Probably making annotations fit a single structure that can live in co_consts could make this change easier, and also make startup of annotated modules faster (because you just load a single constant instead of one per argument), this might be a valuable change by itself.</div><div><br></div><div><br></div></div><div class="gmail_extra"><div><div class="h5"><br><div class="gmail_quote">On 12 April 2018 at 11:48, INADA Naoki <span dir="ltr"><<a href="mailto:songofacandy@gmail.com" target="_blank">songofacandy@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span>> Finally, loading docstrings and other optional components can be made lazy.<br>
> This was not in my original idea, and this will significantly complicate the<br>
> implementation, but in principle it is possible. This will require larger<br>
> changes in the marshal format and bytecode.<br>
<br>
</span>I'm +1 on this idea.<br>
<br>
* New pyc format has code section (same to current) and text section.<br>
text section stores UTF-8 strings and not loaded at import time.<br>
* Function annotation (only when PEP 563 is used) and docstring are<br>
stored as integer, point to offset in the text section.<br>
* When type.__doc__, PyFunction.__doc__, PyFunction.__annotation__ are<br>
integer, text is loaded from the text section lazily.<br>
<br>
PEP 563 will reduce some startup time, but __annotation__ is still<br>
dict.  Memory overhead is negligible.<br>
<br>
In [1]: def foo(a: int, b: int) -> int:<br>
   ...:     return a + b<br>
   ...:<br>
   ...:<br>
<br>
In [2]: import sys<br>
In [3]: sys.getsizeof(foo)<br>
Out[3]: 136<br>
<br>
In [4]: sys.getsizeof(foo.__annotation<wbr>s__)<br>
Out[4]: 240<br>
<br>
When PEP 563 is used, there are no side effect while building the annotation.<br>
So the annotation can be serialized in text, like<br>
{"a":"int","b":"int","return":<wbr>"int"}.<br>
<br>
This change will require new pyc format, and descriptor for<br>
PyFunction.__doc__, PyFunction.__annotation__<br>
and type.__doc__.<br>
<br>
Regards,<br>
<span class="m_-2482231417507566400HOEnZb"><font color="#888888"><br>
-- <br>
INADA Naoki  <<a href="mailto:songofacandy@gmail.com" target="_blank">songofacandy@gmail.com</a>><br>
</font></span><div class="m_-2482231417507566400HOEnZb"><div class="m_-2482231417507566400h5">______________________________<wbr>_________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/mailma<wbr>n/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/codeofco<wbr>nduct/</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div></div></div><span class="">-- <br><div class="m_-2482231417507566400gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div dir="ltr">Daniel F. Moisset - <span style="font-size:small">UK Country Manager - Machinalis Limited</span><div><a href="http://www.machinalis.com" target="_blank">www.machinalis.co.uk</a></div><div>Skype: @dmoisset T: <span style="background-color:transparent;font-family:Arial;font-size:8pt;white-space:pre-wrap">+ 44 7398 827139</span></div><div><span><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:8pt;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap">1 Fore St, London, EC2Y 9DT</span></p><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="background-color:transparent;font-family:Arial;font-size:8pt;white-space:pre-wrap">Machinalis Limited is a company registered in England and Wales. Registered number: 10574987.</span></p></span></div></div></div></div></div></div>
</span></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div dir="ltr">Daniel F. Moisset - <span style="font-size:small">UK Country Manager - Machinalis Limited</span><div><a href="http://www.machinalis.com" target="_blank">www.machinalis.co.uk</a></div><div>Skype: @dmoisset T: <span style="background-color:transparent;font-family:Arial;font-size:8pt;white-space:pre-wrap">+ 44 7398 827139</span></div><div><span><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:8pt;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap">1 Fore St, London, EC2Y 9DT</span></p><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="background-color:transparent;font-family:Arial;font-size:8pt;white-space:pre-wrap">Machinalis Limited is a company registered in England and Wales. Registered number: 10574987.</span></p></span></div></div></div></div></div></div>
</div>