Flyweight模式 - 内存占用

时间:2015-06-13 13:09:44

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

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

我创建了两个小程序,一个没有优化,一个是实现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))
    
  3. 现在我正在使用它来获取我的内存占用量(在应用程序关闭之前的最后一行):

    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工具,这里会更准确吗?

1 个答案:

答案 0 :(得分:2)

就我在问题中的代码中所知,在这两种情况下,你只是使用相同数量的实例的引用。

采用“未经优化”的版本:

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

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

您可以通过比较成员的id来检查这一点。制作set个ID,并查看它是否大于3.