防止动态绑定,节省大量空间

高级编程技巧 学习笔记

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


1.1、问题

        在游戏中,定义了玩家类 player,每有一个在线玩家,在服务器内则有一个 player 的实例,当在线人数很多时,将产生大量实例(百万级)

        如何降低这些大量实例的内存开销?(动态绑定属性问题)

1.2、解决方案

定义类的__slots__属性,声明实例有哪些属性 (关闭动态绑定属性)

  • 什么是动态绑定属性(__dict__方法实现,相当于在实例方法里添加了一个属性)
import sys

# 两个类, Player1 开启动态绑定, Player2 关闭动态绑定
class Player1(object):
    def __init__(self, uid, name, status=0, level=1):
        self.uid = uid
        self.name = name
        self.status = status
        self.level = level


class Player2(object):
	# 相当于实现规定了 __init__ 方法只能包含哪些属性
    __slots__ = ('uid', 'name', 'status', 'level')

    def __init__(self, uid, name, status=0, level=1):
        self.uid = uid
        self.name = name
        self.status = status
        self.level = level

# 实例化
p1 = Player1('0001', 'p1')
p2 = Player2('0002', 'p2')

# 开启动态绑定 
p1.x = 6
p1.__dict__['y'] = 7
print(p1.__dict__)

# 关闭动态绑定, 报错 
p2.y = 7

# 查看占用的内存, 发现 '动态绑定属性的操作' 所占内存多得多
print(sys.getsizeof(p1.__dict__))
print(sys.getsizeof(p1.name))
print(sys.getsizeof(p1.uid))

1.3、tracemalloc 模块

  • 主要用来分析程序内存占用时使用
import sys
import tracemalloc


class Player1(object):
    def __init__(self, uid, name, status=0, level=1):
        self.uid = uid
        self.name = name
        self.status = status
        self.level = level


class Player2(object):
    __slots__ = ('uid', 'name', 'status', 'level')

    def __init__(self, uid, name, status=0, level=1):
        self.uid = uid
        self.name = name
        self.status = status
        self.level = level


p1 = Player1('0001', 'p1')
p2 = Player2('0002', 'p2')


# # 跟踪内存的使用

tracemalloc.start()

# 分别执行以下两句
p1 = [Player1(1, 2, 3) for _ in range(100000)]          # 20.6 MiB
# p2 = [Player2(1, 2, 3) for _ in range(100000)]          # 7837 KiB

end = tracemalloc.take_snapshot()
# top = end.statistics('lineno')        				# 分析每一行代码
top = end.statistics('filename')        				# 分析整个文件

for stat in top[:10]:
    print(stat)
发布了85 篇原创文章 · 获赞 0 · 访问量 1235

猜你喜欢

转载自blog.csdn.net/qq_43621629/article/details/104033719
今日推荐