More detailed information: ## With annotations
=== tracemalloc stat === traced: (46969277, 46983753) 18,048,888 / 181112 File "<frozen importlib._bootstrap_external>", line 488 File "<frozen importlib._bootstrap_external>", line 780 File "<frozen importlib._bootstrap_external>", line 675 === size by types === dict 9,083,816 (8,870.91KB) / 21846 = 415.811bytes (21.38%) tuple 6,420,960 (6,270.47KB) / 86781 = 73.990bytes (15.11%) str 6,050,213 (5,908.41KB) / 77527 = 78.040bytes (14.24%) function 2,772,224 (2,707.25KB) / 20384 = 136.000bytes (6.53%) code 2,744,888 (2,680.55KB) / 18987 = 144.567bytes (6.46%) type 2,713,552 (2,649.95KB) / 2769 = 979.975bytes (6.39%) bytes 2,650,838 (2,588.71KB) / 38723 = 68.456bytes (6.24%) set 2,445,280 (2,387.97KB) / 6969 = 350.880bytes (5.76%) weakref 1,255,600 (1,226.17KB) / 15695 = 80.000bytes (2.96%) list 707,336 (690.76KB) / 6628 = 106.719bytes (1.66%) === dict stat === t, size, total (%) / count 3, 256, 1,479,424 (15.68%) / 5779.0 3, 1,200, 1,330,800 (14.11%) / 1109.0 3, 1,310,832, 1,310,832 (13.90%) / 1.0 3, 664, 1,287,496 (13.65%) / 1939.0 7, 128, 756,352 (8.02%) / 5909.0 3, 384, 707,328 (7.50%) / 1842.0 3, 2,296, 642,880 (6.81%) / 280.0 0, 256, 378,112 (4.01%) / 1477.0 7, 168, 251,832 (2.67%) / 1499.0 3, 4,720, 221,840 (2.35%) / 47.0 3, 9,336, 130,704 (1.39%) / 14.0 7, 88, 105,072 (1.11%) / 1194.0 * t=7 key-sharing dict, t=3 interned string key only, t=1 string key only, t=0 non string key is used ## Stripped annotations === tracemalloc stat === traced: (42383739, 42397983) 18,069,806 / 181346 File "<frozen importlib._bootstrap_external>", line 488 File "<frozen importlib._bootstrap_external>", line 780 File "<frozen importlib._bootstrap_external>", line 675 === size by types === dict 7,913,144 (7,727.68KB) / 17598 = 449.662bytes (20.62%) tuple 6,149,120 (6,005.00KB) / 82734 = 74.324bytes (16.02%) str 6,070,083 (5,927.82KB) / 77741 = 78.081bytes (15.82%) code 2,744,312 (2,679.99KB) / 18983 = 144.567bytes (7.15%) type 2,713,552 (2,649.95KB) / 2769 = 979.975bytes (7.07%) bytes 2,650,464 (2,588.34KB) / 38715 = 68.461bytes (6.91%) function 2,547,280 (2,487.58KB) / 18730 = 136.000bytes (6.64%) set 1,423,520 (1,390.16KB) / 4627 = 307.655bytes (3.71%) list 634,472 (619.60KB) / 5454 = 116.331bytes (1.65%) int 608,784 (594.52KB) / 21021 = 28.961bytes (1.59%) === dict stat === t, size, total (%) / count 3, 1,200, 1,316,400 (16.06%) / 1097.0 3, 1,310,832, 1,310,832 (16.00%) / 1.0 3, 664, 942,216 (11.50%) / 1419.0 3, 256, 861,184 (10.51%) / 3364.0 3, 384, 657,024 (8.02%) / 1711.0 3, 2,296, 640,584 (7.82%) / 279.0 7, 128, 606,464 (7.40%) / 4738.0 0, 256, 379,904 (4.64%) / 1484.0 7, 168, 251,832 (3.07%) / 1499.0 3, 4,720, 221,840 (2.71%) / 47.0 3, 9,336, 130,704 (1.59%) / 14.0 7, 88, 105,248 (1.28%) / 1196.0 7, 256, 86,784 (1.06%) / 339.0 ## Stripped annotation + without pydebug === tracemalloc stat === traced: (37371660, 40814265) 9,812,083 / 111082 File "<frozen importlib._bootstrap>", line 205 File "<frozen importlib._bootstrap_external>", line 742 File "<frozen importlib._bootstrap_external>", line 782 6,761,207 / 85614 File "<frozen importlib._bootstrap_external>", line 488 File "<frozen importlib._bootstrap_external>", line 780 File "<frozen importlib._bootstrap_external>", line 675 ## Ideas about memory optimize a) Split PyGC_Head from object Reduces 2words (16byte) from each tuples. >>> 82734 * 16 / 1024 1292.71875 So estimated -1.2MB b) concat co_consts, co_names, co_varnames, co_freevars into one tuple, or embed them into code. Each tuple has 3 (gc head) + 3 (refcnt, *type, length) = 6 words overhead. (or 4 words if (a) is applied) If we can reduce 3 tuples, 18 words = 144byte (or 12 words=96byte) can be reuduced. >>> 18983 * 144 2733552 >>> 18983 * 96 1822368 But co_freevars is empty tuple in most cases. So real effect is smaller than 2.7MB. If we can embed them into code object, we can estimate -2.7MB. (There are co_cellvars too. But I don't know about it much, especially it is GC tracked or not) c) (interned) string key only dict. 20% of memory is used for dict, and 70% of dict has interned string keys. Current DictKeyEntry is 3 words: {key, hash, value}. But if we can assume all key is string, hash can be get from the key. If we use 2 words entry: {key, value} for such dict, I think dict can be 25% smaller. >>> 7913144 * 0.25 / 1024 1931.919921875 So I estimate -1.9MB If we can implement (a)~(c) I estimate memory usage on Python (--without-pydebug) can be reduced from 35.6MB to 30MB, roughly. But I think -Onoannotation option is top priority. It can reduce 4MB, even we use annotations only in our code. If major libraries start using annotations, this number will be larger. _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com