zoukankan      html  css  js  c++  java
  • 如何为创建大量实例节省内存?

    需求:
    某网络游戏中,定义了玩家类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
    
    =====================================================================
    >>> class Player1:
    ...     def __init__(self,uid,name,level):
    ...         self.uid = uid
    ...         self.name = name
    ...         self.level = level
    ... 
    >>> class Player2:
    ...     __slots__=['uid','name','level']
    ...     def __init__(self,uid,name,level):
    ...         self.uid = uid
    ...         self.name = name
    ...         self.level = level
    ... 
    >>> p1 = Player1('0001','Jim',20)
    >>> p2 = Player2('0001','Jim',20)
    >>> dir(p1)
    ['__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', 'uid']
    >>> dir(p2)
    ['__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', 'uid']
    >>> set(dir(p1)) - set(dir(p2))
    {'__weakref__', '__dict__'}
    >>> p1.x = 100
    >>> p1.y = 200
    >>> p1.x
    100
    >>> p1.xy
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Player1' object has no attribute 'xy'
    >>> p1.y
    200
    >>> p1.__dict__
    {'uid': '0001', 'name': 'Jim', 'level': 20, 'x': 100, 'y': 200}
    >>> p1.__dict__['z'] = 300
    >>> p1.z
    300
    >>> p1.__dict__.pop('x')
    100
    >>> p1.x
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Player1' object has no attribute 'x'
    >>> import sys
    >>> sys.getsizeof(p1.__dict__)
    648
    >>> sys.getsizeof(p1.name)
    52
    >>> sys.getsizeof(p1.level)
    28
    >>> sys.getsizeof(p1.uid)
    53
    >>> p2.x = 1
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Player2' object has no attribute 'x'
    >>> p2.name='abc'
    
    =====================================================================================================
    
    class Player1:
        def __init__(self,uid,name,level):
            self.uid = uid
            self.name = name
            self.level = level
    
    class Player2:
        __slots__=['uid','name','level']
        def __init__(self,uid,name,level):
            self.uid = uid
            self.name = name
            self.level = level
    
    import tracemalloc
    tracemalloc.start()
    # start
    la = [Player1(1,2,3) for _ in range(100000)]
    #lb = [Player2(1,2,3) for _ in range(100000)]
    # end
    snapshot = tracemalloc.take_snapshot()
    top_stats = snapshot.statistics('filename')  # 统计整个文件占用内存的大小,通过对比可以发现lb占用的内在更小
    for stat in top_stats[:10]:print(stat)
    
    
  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    mac flutter 创建过程及遇到的问题
    MAC 终端编辑完成后如何保存:
    mac下添加环境变量
    beanstalkd队列
    小程序真机上报错 for developer: some selectors are not allowed in component wxss , including tag name selectors, id selectors, and attribute selectors
    小程序通过web-view实现与h5页面之间的交互
    小程序中的web-view与h5网页之间的交互
  • 原文地址:https://www.cnblogs.com/Richardo-M-Q/p/13350168.html
Copyright © 2011-2022 走看看