如何为创建大量实例节省内存?

Posted richardo-m-q

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何为创建大量实例节省内存?相关的知识,希望对你有一定的参考价值。

需求:
某网络游戏中,定义了玩家类Player(id,name,status,...)每有一个在线玩家,在服务器程序内则有一个Player的实例,当在线人数很多时,将产生大量实例(如百万级)
如何降低这些大量实例的内存开销?

思路:
定义类的__slots__属性,它是用来声明实例属性名字的列表。

代码:

e.py:
class Player(object):
    def __init__(self,uid,name,status=0,level=1):
        self.uid = uid
        self.name = name
        self.stat = status
        self.level = level

class Player2(object):
    __slots__ = [‘uid‘,‘name‘,‘stat‘,‘level‘] # 声明类实例化对象所有的属性名,禁止实例属性的动态绑定。即该实例没有了__dict__属性。
    def __init__(self,uid,name,status=0,level=1):
        self.uid = uid
        self.name = name
        self.stat = status
        self.level = level

==============================================
测试:
In [3]: from e import Player, Player2

In [4]: p1 = Player(‘001‘,‘Jim‘)

In [5]: p2 = Player2(‘002‘,‘Tom‘)

In [6]: dir(p1)
Out[6]:
[‘__class__‘,
 ‘__delattr__‘,
 ‘__dict__‘,
 ‘__dir__‘,
 ‘__doc__‘,
 ‘__eq__‘,
 ‘__format__‘,
 ‘__ge__‘,
 ‘__getattribute__‘,
 ‘__gt__‘,
 ‘__hash__‘,
 ‘__init__‘,
 ‘__init_subclass__‘,
 ‘__le__‘,
 ‘__lt__‘,
 ‘__module__‘,
 ‘__ne__‘,
 ‘__new__‘,
 ‘__reduce__‘,
 ‘__reduce_ex__‘,
 ‘__repr__‘,
 ‘__setattr__‘,
 ‘__sizeof__‘,
 ‘__str__‘,
 ‘__subclasshook__‘,
 ‘__weakref__‘,
 ‘level‘,
 ‘name‘,
 ‘stat‘,
 ‘uid‘]

In [7]: dir(p2)
Out[7]:
[‘__class__‘,
 ‘__delattr__‘,
 ‘__dir__‘,
 ‘__doc__‘,
 ‘__eq__‘,
 ‘__format__‘,
 ‘__ge__‘,
 ‘__getattribute__‘,
 ‘__gt__‘,
 ‘__hash__‘,
 ‘__init__‘,
 ‘__init_subclass__‘,
 ‘__le__‘,
 ‘__lt__‘,
 ‘__module__‘,
 ‘__ne__‘,
 ‘__new__‘,
 ‘__reduce__‘,
 ‘__reduce_ex__‘,
 ‘__repr__‘,
 ‘__setattr__‘,
 ‘__sizeof__‘,
 ‘__slots__‘,
 ‘__str__‘,
 ‘__subclasshook__‘,
 ‘level‘,
 ‘name‘,
 ‘stat‘,
 ‘uid‘]

In [8]: set(dir(p1)) - set(dir(p2))  # 取集合的差集,这里是p1比p2多的属性
Out[8]: {‘__dict__‘, ‘__weakref__‘}

In [9]: set(dir(p2)) - set(dir(p1))
Out[9]: {‘__slots__‘}

In [10]: p1.__dict__  # 这里__dict__是一个动态的字典
Out[10]: {‘uid‘: ‘001‘, ‘name‘: ‘Jim‘, ‘stat‘: 0, ‘level‘: 1}

In [11]:  p1.x
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-11-54f8378113e3> in <module>
----> 1 p1.x

AttributeError: ‘Player‘ object has no attribute ‘x‘

In [12]: p1.x = 123  # 可以动态的增加属性

In [13]: p1.x
Out[13]: 123

In [14]: p1.__dict__
Out[14]: {‘uid‘: ‘001‘, ‘name‘: ‘Jim‘, ‘stat‘: 0, ‘level‘: 1, ‘x‘: 123}

In [15]: p1.__dict__[‘y‘] = 99

In [16]: p1.y
Out[16]: 99

In [17]: del p1.__dict__[‘x‘]  # 删除属性

In [18]: p1.x
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-18-54f8378113e3> in <module>
----> 1 p1.x

AttributeError: ‘Player‘ object has no attribute ‘x‘

In [19]: import sys

In [20]: sys.getsizeof(p1.__dict__)  # 获取该属性所占用的内存空间,所以禁用该属性后占用的内存空间减少
Out[20]: 368

In [21]: p2.x = 123
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-21-2c5f7091e7e8> in <module>
----> 1 p2.x = 123

AttributeError: ‘Player2‘ object has no attribute ‘x‘

In [22]: sys.getsizeof(p2.__slot__)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-22-d68996e840e6> in <module>
----> 1 sys.getsizeof(p2.__slot__)

AttributeError: ‘Player2‘ object has no attribute ‘__slot__‘

In [23]: sys.getsizeof(p2.__slots__)
Out[23]: 96



以上是关于如何为创建大量实例节省内存?的主要内容,如果未能解决你的问题,请参考以下文章

7-2 如何为创建大量实例节省内存

如何为 XSLT 代码片段配置 CruiseControl 的 C# 版本?

python基础===创建大量对象是节省内存方法

如何为一长串整数创建优化的迭代器?

如何为 Firestore 创建大量示例数据?

Chart.js - 如何为随时间发生的大量数据创建自动缩放折线图