【问题标题】:Flyweight pattern - Memory footprint享元模式 - 内存占用
【发布时间】:2015-06-13 13:09:43
【问题描述】:

我正在学习 Python,我认为这将是一个很好的借口来更新我的模式知识,在这种情况下,是 Flyweight 模式。

我创建了两个小程序,一个没有优化,一个是实现享元模式。出于测试目的,我正在创建一个由 1'000'000 Enemy 对象组成的军队。每个敌人可以是三种类型(士兵、忍者或酋长),我为每种类型分配了座右铭。

我想检查的是,在我未优化的程序中,我得到了 1'000'000 个敌人,每个敌人都有一个类型和一个包含座右铭的“长”字符串。 使用优化的代码,我只想创建三个对象 (EnemyType) 匹配每种类型,并且只包含 3 倍的座右铭字符串。然后,我向每个Enemy 添加一个成员,指向所需的EnemyType

现在是代码(仅摘录):

  1. 未优化的程序

    在这个版本中,每个敌人都会存储自己的类型和座右铭。

    enemyList = []
    enemyTypes = {'Soldier' : 'Sir, yes sir!', 'Ninja' : 'Always behind you !', 'Chief' : 'Always behind ... lot of lines '}
    for i in range(1000000):
      randomPosX = 0 # random.choice(range(1000))
      randomPosY = 0 # random.choice(range(1000))
      randomTypeIndex = 0 # random.choice(range(0,len(enemyTypes)))
      enemyType = enemyTypes.keys()[randomTypeIndex]
    
      # Here, the type and motto are parameters of EACH enemy object.
      enemyList.append(Enemy(randomPosX, randomPosY, enemyType, enemyTypes[enemyType]))
    
  2. 优化方案

    在这个版本中,每个敌人都有一个 EnemyType 对象的成员,该对象存储其类型和座右铭。只创建了三个 EnemyType 实例,我应该会看到对内存占用的影响。

    enemyList = []
    soldierEnemy = EnemyType('Soldier', 'Sir, yes sir!')         
    ninjaEnemy = EnemyType('Ninja', 'Always behind you !')
    chiefEnemy = EnemyType('Chief', 'Always behind ... lot of lines.')
    enemyTypes = {'Soldier' : soldierEnemy, 'Ninja' : ninjaEnemy, 'Chief' : chiefEnemy}
    
    enemyCount = {}
    
    for i in range(1000000):
    randomPosX = 0 # random.choice(range(1000))
    randomPosY = 0 # random.choice(range(1000))
    randomTypeIndex = 0 #random.choice(range(0,len(enemyTypes)))
    enemyType = enemyTypes.values()[randomTypeIndex]
    
    # Here, each enemy only has a reference on its type.
    enemyList.append(Enemy(randomPosX, randomPosY, enemyType))
    

现在我正在使用它来获取我的内存占用量(在我的应用程序自行关闭之前的最后一行):

import os
import psutil
...
# return the memory usage in MB
process = psutil.Process(os.getpid())
print process.get_memory_info()[0] / float(2 ** 20)

我的问题是,我看不出我的两个程序的输出有什么区别:

优化 = 384.0859375 Mb
未优化 = 383.40234375 Mb

它是获取内存占用的正确工具吗?我是 Python 新手,所以我的代码可能有问题,但我在第二个解决方案中检查了我的 EnemyType 对象,我确实只有三个出现。因此,我应该有 3 个座右铭字符串而不是 1'000'000。

我读过一个名为 Heapy 的 Python 工具,这里会更准确吗?

【问题讨论】:

    标签: python python-2.7 design-patterns ubuntu-14.04 flyweight-pattern


    【解决方案1】:

    据我从问题中的代码可以看出,无论如何,在这两种情况下,您都只是对相同数量的实例使用引用。

    采用“未优化”版本:

    enemyList.append(Enemy(randomPosX, randomPosY, enemyType, enemyTypes[enemyType]))
    

    确实enemyTypes[enemyType] 是一个字符串,这可能会让您认为您有很多字符串实例。但实际上,您的每个对象都有三个相同的字符串对象之一


    您可以通过比较成员的ids 来检查这一点。做一个set的id,看看是否大于3。

    【讨论】:

    • 非常感谢您的回答。现在你说的似乎很明显 :) 我进行了更改,检查了 id(我不知道它存在,太酷了!)实际上我的集合中只有 1 个 id。我改变了一些东西,现在我可以看到不同了。非常感谢朋友!
    猜你喜欢
    • 1970-01-01
    • 2012-03-14
    • 1970-01-01
    • 2015-12-12
    • 1970-01-01
    • 2015-03-05
    • 2019-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多