0

Я изучаю Python, и я подумал, что это было бы хорошим предлогом для обновления знаний о шаблонах и в этом случае шаблона Flyweight.Flyweight pattern - Memory footprint

Я создал две небольшие программы, которые не оптимизированы, и один из них реализует шаблон Flyweight. Для моих целей тестирования я создаю армию размером 1 000 000 000 000 000 000 000 000 000 000 Каждый враг может быть трех типов (Солдат, Ниндзя или Начальник), и я назначаю девиз каждому типу.

Что я хотел бы проверить, так это то, что с моей не оптимизированной программой я получаю 1'000'000 противников, для каждого и каждого из них, тип и длинную строку, содержащую девиз. С оптимизированным кодом я хотел бы создать только три объекта (EnemyType), соответствующие каждому типу и содержащие только 3 раза строки девиза. Затем добавляю элемент к каждому Enemy, указывая на нужный EnemyType.

Теперь (только отрывки) код:

  1. Un-оптимизированная программа

    В этой версии, каждый враг сохраняет свой тип и девиз.

    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
Un-оптимизированной = 383.40234375 Mb

Это правильный инструмент для получения памяти? Я новичок в Python, так что это может быть проблемой с моим кодом, но я проверил объекты EnemyType во втором решении, и у меня действительно есть только три события. Поэтому я должен иметь 3 строки девиза вместо 1'000'000.

Я читал об инструменте под названием Heapy для Python, было бы здесь более точным?

ответ

2

Насколько я могу судить по коду в вопросе, в обоих случаях вы просто используете ссылки для одного и того же небольшого количества экземпляров.

Возьмите «неоптимизированная» версия'S:

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

Действительно enemyTypes[enemyType] является строкой, которая, возможно, сделали вы думаете, у вас есть много примеров строк. Но на самом деле каждый из ваших объектов имеет один из трех одинаковых строковых объектов.


Вы можете проверить это, сравнивая id S членов. Сделайте set идентификаторов, и посмотрите, больше ли это. 3.

+0

Большое спасибо за ваш ответ. Кажется настолько очевидным, что вы сказали это :) Я внес изменения, проверил идентификатор (я не знал, что это было, классно!), И действительно, у меня только 1 идентификатор в моем наборе. Я изменил несколько вещей, и теперь я вижу разницу. Большое спасибо! –