python - почему неизменяемые объекты не занимают одну и ту же память - PullRequest
0 голосов
/ 25 сентября 2018

Я использую микропифон, но это не должно иметь значения

>>> b = [None]*40
>>> gc.collect(); gc.mem_free(); dir(); sys.modules
101
7008
['sys', '__name__', 'a', 'gc', 'b']
{}
>>> for i in range(40):
...     b[i] = (255, 0, 0)
...     gc.collect(); gc.mem_free();
...
...
...
5
6800
0
6768
0
6736
0
6704
0
6672
0
6640
0
6608
0
6576
0
6544
0
6512
0
6480
0
6448
0
6416
0
6384
0
6352
0
6320
0
6288
0
6256
0
6224
0
6192
0
6160
0
6128
0
6096
0
6064
0
6032
0
6000
0
5968
0
5936
0
5904
0
5872
0
5840
0
5808
0
5776
0
5744
0
5712
0
5680
0
5648
0
5616
0
5584
0
5552
>>>

Маленькое число - это количество собранных объектов gc.collect(), а большое количество - сколькосуществует свободная память.

(255, 0, 0) - это кортеж, который является неизменным и содержит неизменяемые объекты, так почему объем свободной памяти уменьшается после каждого присваивания?

Если объектнеизменный, какой смысл в Python делать его копии?
Почему бы просто не назначить один и тот же "указатель" каждому b[i]?

ОБНОВЛЕНИЕ

Iв кортеже использовалось большее число (55555555555555555555, 55555555555555555555) и использование памяти было таким же.

    >>> gc.collect(); gc.mem_free(); dir(); sys.modules
5
6368
['sys', '__name__', 'gc', 'i']
{}
>>> b = [None]*40
>>> for i in range(40):
...     b[i] = (55555555555555555555,55555555555555555555)
...     id(b[i])
...     gc.collect(); gc.mem_free()
...
...
...
5347968
10
5824
5347136
0
5808
5347312
0
5792
5347456
0
5776
5347536
0
5760
5347552
0
5744
5347696
0
5728
5347712
0
5712
5347984
0
5696
5348176
0
5680
5348192
0
5664
5348208
0
5648
5348224
0
5632
5348240
0
5616
5348256
0
5600
5348272
0
5584
5348288
0
5568
5348608
0
5552
5348640
0
5536
5348656
0
5520
5348672
0
5504
5348688
0
5488
5348704
0
5472
5348720
0
5456
5348736
0
5440
5348848
0
5424
5348864
0
5408
5348880
0
5392
5348896
0
5376
5348912
0
5360
5348928
0
5344
5348944
0
5328
5349104
0
5312
5349120
0
5296
5349136
0
5280
5349152
0
5264
5349168
0
5248
5349184
0
5232
5349200
0
5216
5349216
0
5200
>>>

Но когда я использую целое число (55555555555555555555), использование памяти НЕ изменяется при итерации.

1 Ответ

0 голосов
/ 25 сентября 2018

Поскольку обобщенное интернирование всех неизменяемых объектов в интерпретаторе является сложным и добавляет тонну кода, который редко сохраняет что-либо стоящее.

Тем не менее, ваш код делает используйте одну копию tuple в ссылочном интерпретаторе CPython.Это деталь реализации, поэтому каждый интерпретатор может принимать здесь свои собственные решения, и я думаю, что Micropython не решил сделать это (возможно, чтобы интерпретатор был достаточно простым для работы на более слабом оборудовании).

Похоже,Micropython выполняет кэширование для int констант, но не для tuple s;tuple с труднее обрабатывать (по крайней мере, изначально, CPython не делал этого в основной фазе AST, он просто запустил оптимизатор глазка над полученным байтовым кодом, чтобы преобразовать прогоны LOAD_CONST с последующим BUILD_TUPLE, используятолько LOAD_CONST приводит к LOAD_CONST из полученного tuple), и дополнительная работа, возможно, считалась не стоящей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...