2009-11-18 3 views
1

Nous avons l'exemple de code suivant: nous pouvons obtenir différents problèmes de performancecharge paresseuse ou début de charge pour python?

big_static_data = { 
    "key1" : { 
    "subkey1" : "subvalue1", 
    ... 
    }, 
    "key2" : 
    ... 
} 
class StaticDataEarlyLoad: 
    def __init__(self): 
     self.static_data = big_static_data 
     # other init 
    def handle_use_id(self, id): 
     return complex_handle(self.static_data, id) 
    ... 
class StaticDataLazyLoad: 
    def __init__(self): 
     # not init static data 
     # other init 
    def handle_use_id(self, id): 
     return complex_handle(big_static_data, id) 
    ... 

Tout comme les codes ci-dessus dit, chaque fois que nous appelons handle_use_id de l'instance,.

OMI, au début de la charge charge les données lorsque l'instance est créée, et sera en mémoire jusqu'à ce que l'instance est garbaged. Et pour le chargement tardif, les données statiques ne seront pas chargées jusqu'à ce que nous appelions la méthode handle_use_id. Ai-je raison? (Puisque je ne suis pas très clair avec l'interne de Python, je ne sais pas combien de temps l'instance durera jusqu'à garbaged). Et si j'ai raison, le chargement précoce signifie une grosse mémoire et le chargement tardif signifie que nous devons charger les données chaque fois que nous invoquons la méthode (un gros overhead?)

Maintenant, nous sommes un projet web , Alors qui devrait être choisi comme la meilleure approche? (handle_use_id sera invoqué très fréquemment.)

Merci.

+0

Sans cas d'utilisation spécifique, il n'y a aucun moyen de répondre à cette question. À quelle fréquence est-ce utilisé? Deux fois par jour? Deux fois par seconde? Quel est le rapport des différentes méthodes invoquées sur cette grande structure? Il n'y a pas de «meilleur» sans profils spécifiques et détaillés de la façon dont il sera utilisé. –

+0

** très souvent ** signifie que cela dépend des comportements des utilisateurs. Je pense que ce sera une fois par 10 secondes si l'utilisateur se connecte. –

+0

@Tower Joo: "très souvent" ne veut rien dire. Une fois en 10 secondes, cela signifie cependant quelque chose. –

Répondre

3

Dans votre exemple, StaticDataLazyLoad (une fois que la syntaxe pour init est correcte) ne fera pas une grande différence.

"big_static_data" est initialisé ("chargé") lorsque le module est importé. Cela nécessitera immédiatement de la mémoire, peu importe si une instance de vos classes est créée ou non.

Une instance de StaticDataEarlyLoad va simplement créer une nouvelle référence à big_static_data, pas une nouvelle copie. Par conséquent, une recherche dans StaticDataEarlyLoad peut être légèrement plus rapide, puisque les données sont référencées via self dans la portée locale (lookup "self", puis recherche "self.static_data").

Une recherche dans StaticDataLazyLoad ne trouvera pas "big_static_data" dans la portée locale, python la recherchera dans la portée globale et la trouvera. Étant donné que la portée globale est probablement plus grande, cette recherche peut prendre plus de temps que la recherche de "self.static_data".

+0

merci. Mais je me demande s'il existe une meilleure approche pour améliorer la performance? Si je mets les grandes données statiques à une classe, alors l'utiliser dans les approches dans la poste (chargement précoce et charge paresseuse), de sorte que la première charge est bonne pour la vitesse, mais utilise plus de mémoire? et la charge en retard est le contraire? –

+0

Si big_static_data est chargé pendant une méthode de classe (StaticDataEarlyLoad :: __ init__ ou StaticDataLazyLoad :: handle_use_id) aucune mémoire ne sera utilisée avant que cette méthode ne soit invoquée. Cette version de StaticDataLazyLoad présente des inconvénients de performance si les données sont chargées à chaque invocation de méthode. Vous pouvez envisager une combinaison des deux classes, où les données ne sont chargées qu'une seule fois, probablement lors du premier appel de handle_use_id. – resi

+0

@Tower Joo: Correct: La charge initiale est bonne pour la vitesse mais utilise plus de mémoire. La charge tardive est mauvaise pour la vitesse en utilisant moins de mémoire. Correct. Qu'est-ce que tu veux savoir de plus? Quelle est votre question? Voulez-vous une "solution" magique qui brise cette loi fondamentale du logiciel? –

3

big_static_data est créé une fois au début du fichier (au moins dans le code que vous montrer).

Ceci consomme de la mémoire.

Lorsque vous créez une instance de StaticDataEarlyLoad,

StaticDataEarlyLoad(). Static_data est une référence à big_static_data. Il consomme une très petite quantité de mémoire. Il pointe simplement vers le même dictionnaire que pointé par big_static_data. Aucune copie de big_static_data n'est faite, il n'y a pas de véritable "chargement" en cours.

Quand exemple StaticDataEarlyLoad() obtient le ramasse-miettes, un peu de mémoire est libérée, mais le reste big_static_data.

StaticDataLazyLoad fait la même chose, mais ne crée pas un attribut static_data. Il fait juste référence à big_static_data directement. La différence de consommation de mémoire entre StaticDataEarlyLoad et StaticDataLazyLoad est très mineure. Et il n'y aura essentiellement aucune différence de vitesse.

Il est toujours préférable de rendre explicite ce dont dépend une classe. StaticDataEarlyLoad dépend de big_static_data. Par conséquent, vous devez définir

class StaticDataEarlyLoad: 
    def __init__(self,static_data): 
     self.static_data = static_data 

et initialiser les instances avec StaticDataEarlyLoad(big_static_data).

Il n'y a essentiellement aucune différence de vitesse entre cette définition et celle que vous avez affichée. Mettre des dépendances dans la signature d'appel de __init__ est juste une bonne idée pour le bien de l'organisation, et après tout, vous utilisez la POO de Python pour un bon contrôle de l'organisation, n'est-ce pas?

+0

merci. Vous avez mentionné de changer la signature init, que je ne suis pas d'accord, au moins dans ce cas d'utilisation. Puisque ce fichier (ou classe) est juste pour aller chercher des données, et les utilisateurs de cette classe n'ont pas ** besoin ** de savoir beaucoup de choses sur ce que sont les données. Ils se soucient seulement des méthodes qu'ils peuvent utiliser pour obtenir les données appropriées (peut-être un peu comme une base de données). –

Questions connexes