2008-10-30 8 views
5

Je suis relativement nouveau dans le monde de python, mais cela semble très simple.Comment puis-je optimiser ce code Google App Engine?

Google me crie que ce code doit être optimisé:

class AddLinks(webapp.RequestHandler): 
    def post(self): 
      # Hash the textarea input to generate pseudo-unique value 
      hash = md5.new(self.request.get('links')).hexdigest() 

      # Seperate the input by line 
      allLinks = self.request.get('links').splitlines() 

      # For each line in the input, add to the database 
      for x in allLinks: 
       newGroup = LinkGrouping() 
       newGroup.reference = hash 
       newGroup.link = x 
       newGroup.put() 

      # testing vs live 
      #baseURL = 'http://localhost:8080' 
      baseURL = 'http://linkabyss.appspot.com' 

      # Build template parameters 
      template_values = { 
       'all_links': allLinks, 
       'base_url': baseURL, 
       'reference': hash, 
      } 

      # Output the template 
      path = os.path.join(os.path.dirname(__file__), 'addLinks.html') 
      self.response.out.write(template.render(path, template_values)) 

Le tableau de bord me dit que cela utilise une tonne de CPU.

Où devrais-je chercher des améliorations?

Répondre

7

Le principal surcoût ici est les multiples mises individuelles au magasin de données. Si vous le pouvez, stockez les liens en une seule entité, comme le suggère André. Vous pouvez toujours diviser les liens en un tableau et le stocker dans un objet ListProperty.

Si vous avez besoin d'une entité pour chaque lien, essayez ceci:

# For each line in the input, add to the database 
groups = [] 
for x in allLinks: 
    newGroup = LinkGrouping() 
    newGroup.reference = hash 
    newGroup.link = x 
    groups.append(newGroup) 
db.put(groups) 

Il permettra de réduire les allers-retours datastore un, et ce sont les allers-retours qui tuent vraiment votre casquette haute CPU.

3

Cela me semble plutôt serré.

Je vois une chose qui peut faire une petite amélioration. Votre appel, "self.request.get ('links')" deux fois.

Ainsi ajoutant:

unsplitlinks = self.request.get('links') 

et le référencement, "unsplitlinks" pourrait aider. En dehors de cela, la boucle est la seule zone que je vois qui serait une cible pour l'optimisation. Est-il possible de préparer les données, puis de les ajouter à la base de données en même temps, au lieu de faire une addition par lien? (Je suppose que la commande .put() ajoute le lien à la base de données)

0

À quelle fréquence cela est-il appelé? Cela ne semble pas si mauvais ... surtout après avoir supprimé la demande en double.

2

Vous pouvez réduire considérablement l'interaction entre votre application et la base de données en stockant simplement le self.request.get('links') complet dans un champ de texte de la base de données.

  • une seule put() par post(self)
  • le hachage ne sont pas stockées n fois (pour chaque lien, qui n'a pas de sens et est vraiment un gaspillage d'espace)

Et vous sauvez-vous l'analyse syntaxique du champ de texte lorsque quelqu'un appelle réellement la page ...

0

Puis-je effectuer une requête sur ListProperty?

Quelque chose comme

SELECT * FROM LinkGrouping WHERE links.contains('http://www.google.com') 

J'ai des plans futurs où je besoin cette fonctionnalité.

Je vais certainement implémenter le simple db.put() pour réduire l'utilisation.

+1

Oui, ListProperties ont une caractéristique cool. Si vous utilisez LinkGrouping.gql ("WHERE links =: 1", "http://www.google.com"), tous les groupes ayant "http://www.google.com" dans leur liste seront renvoyés. –

0

pas/vous ne pouvez pas utiliser quelque chose comme "links.contains ('http://www.google.com')" GQL ne supportent pas cette