0

私は Python を学んでおり、パターンの知識を更新する良い言い訳になると思いました。その場合は、Flyweight パターンです。

私は 2 つの小さなプログラムを作成しました。1 つは最適化されておらず、もう 1 つは Flyweight パターンを実装しています。テスト目的で、1'000'000個のEnemyオブジェクトの軍隊を作成しています。各敵には 3 つのタイプ (ソルジャー、ニンジャ、チーフ) があり、各タイプにモットーを割り当てます。

私が確認したいのは、最適化されていないプログラムを使用すると、1'000'000 の敵が、それぞれのタイプと、モットーを含む「長い」文字列を持つことです。EnemyType最適化されたコードを使用して、各タイプに一致し、モットーの文字列の 3 倍だけを含むオブジェクト ( ) を 3 つだけ作成したいと思います。Enemy次に、目的の を指すメンバーを each に追加します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そのタイプとモットーを格納するオブジェクトのメンバーを持っています。の 3 つのインスタンスのみ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)

私の問題は、2 つのプログラムの出力に違いが見られないことです。

最適化 = 384.0859375 Mb
最適化なし = 383.40234375 Mb

メモリフットプリントを取得するための適切なツールですか? 私はPythonを初めて使用するので、コードに問題がある可能性がありますが、2番目のソリューションでEnemyTypeオブジェクトをチェックしましたが、実際には3回しか発生していません。したがって、1'000'000 ではなく 3 つのモットー ストリングを使用する必要があります。

Heapy for Pythonというツールについて読んだことがありますが、こちらの方が正確でしょうか?

4

1 に答える 1

2

質問のコードからわかる限り、どちらの場合も、同じ少数のインスタンスの参照を使用しているだけです。

「最適化されていない」バージョンを取ります:

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

確かenemyTypes[enemyType]に文字列なので、文字列のインスタンスがたくさんあると思われるかもしれません。しかし実際には、各オブジェクトには3 つの同じ string オブジェクトのいずれかが含まれています。


idこれは、メンバーの s を比較することで確認できます。IDの asetを作成し、それが 3 より大きいかどうかを確認します。

于 2015-06-13T13:25:25.537 に答える