IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau/Web Python Discussion :

Utilisation massive du CPU


Sujet :

Réseau/Web Python

  1. #1
    Membre très actif
    Avatar de ProgVal
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2006
    Messages
    636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2006
    Messages : 636
    Par défaut Utilisation massive du CPU
    Bonjour,

    J'ai un problème, lié à ces deux bouts de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    def _get_from_server(socketObject, input):
        stopFetching=False
        while not stopFetching:
            try:
                datas=""
                while datas == "" or datas[-2:] != "\r\n":
                    datas=datas+socketObject.recv(1024)
                datas=datas.split("\r\n")
                for data in datas:
                    if data != "":
                        if data[0:19] == "ERROR :Closing Link": # Message que le serveur nous envoie (parfois) avant de nous déconnecter
                            stopFetching=True
                        input.put(item=data, block=True)
            except socket.error: # Dans le cas où on n'a rien reçu
                pass
            time.sleep(0.1)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
        def main_thread(output, input, sockets):
            import Queue
            while True:
                try:
                    data=input.get(block=False)
                    if data.error:
                        IO.connect_to_server(sockets, data.serverName, output, input, continueToRun)
                    else:
                        # bla bla bla
                except Queue.Empty:
                    time.sleep(1)
    Ces deux codes sont lancés dans des threads différents.

    Et, il semblerait que, lorsque l'on est déconnecté du serveur, l'utilisation du CPU passe à 100% (à moins que ce ne soit l'inverse).
    Ce qui m'embête particulièrement, c'est que ce problème survient aléatoirement, la plupart du temps plusieurs jours après le lancement du script.

    Avez-vous une idée ?

    Merci d'avance,
    ProgVal

  2. #2
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    Permettez-moi de commencer par la fin
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
        def main_thread(output, input, sockets):
            import Queue
            while True:
                try:
                    data=input.get(block=False)
                    if data.error:
                        IO.connect_to_server(sockets, data.serverName, output, input, continueToRun)
                    else:
                        # bla bla bla
                except Queue.Empty:
                    time.sleep(1)
    Pourquoi vouloir prendre quelque chose dans la queue en non bloquant si c'est pour bloquer quand il n'y a rien ?
    De plus, l'import devrait être en tête de fichier. certainement pas ici.
    D'où sort cette variable continueToRun, et à qui dit-elle de continuer à tourner ?

    Ceci me parait plus cohérent:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
        def main_thread(output, input, sockets):
            while True:
                try:
                    data = input.get()
     
                    if data.error:
                        IO.connect_to_server(sockets, data.serverName, output, input, continueToRun)
                    else:
                        # bla bla bla

    Continuons avec le commencement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    while datas == "" or datas[-2:] != "\r\n":
        datas = datas + socketObject.recv(1024)
    socketObject.recv est-il bloquant ?
    Si c'est le cas, le while est une erreur: un recv dont le résultat est vide signifie que le socket a été déconnecté de l'autre côté.
    Si ce n'est pas le cas, ça n'a pas lieu d'être dans ce code. Remettez le en mode bloquant.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if data[0:19] == "ERROR :Closing Link":
    Comme dit plus haut, si le socket est déconnecté de l'autre côté, le recv renverra un résultat vide. Pas besoin donc de signaler la déconnexion dans ce cas. De plus, ce code risque de lancer une IndexError si cette ligne de données est trop courte.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    except socket.error: # Dans le cas où on n'a rien reçu
                pass
    Une socket.error, c'est pire que ça. En général, on coupe la connexion. Dans la plupart des cas, c'est même déjà fait

    Si j'ai bien compris, ce code parse des headers textes style http, de la forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Content-type: text/html\r\n
    Content-lenght: 347\r\n
    \r\n
    La fonction n'est sensée quitter que si le lien avec le serveur est rompu, autrement il attend la suite des headers.
    Voici comment je réécrirais ce bout de code.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    def _get_from_server(socket, input):
        try:
            left = ""
            while 1:
                raw = socket.recv(1024)
     
                if not raw:
                    # Le socket est mort
                    break
     
                left = left + raw
                lines = left.split("\r\n")
                # Note: est-on certains de recevoir des \r\n ?
                # Certains clients ou serveurs http ne mettent que \n
     
                # Vider left : les données sont exploitées
                left = ""
     
                for line in lines[:-1]:
                    input.put(line) # Une queue bloque par défaut si elle est pleine
     
                # Attention, il se peut qu'il y ait eu des données après les headers
                # Auquel cas ce code n'est plus valide, puisque les données peuvent
                #   aussi contenir des \r\n
                if line[-1] == "":
                    # La ligne est vide marque sans doute la fin des headers 
                    faire_quelquechose()
                else:
                    # Il reste quelques données dans cette ligne
                    # Mais la réception n'est pas complète
                    # Ex : "Content-ty"
                    left = line
     
        except socket.error:
            # Le socket est ptet mort
            pass
     
        finally: # Quoi qu'il en soit, faut être sur que le socket est fermé
            try:
                socket.close()
            except:
                pass

    Pour conclure, à mon avis cette utilisation absusive du cpu vient de là:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    # Message que le serveur nous envoie (parfois) avant de nous déconnecter
    Et quand il ne l'envoie pas, une fois revenu au recv, il renvoie une chaine vide. Du coup, le while boucle, encore, et encore...

    Edit : j'avais glissé une erreur a niveau du raw et de l'arret de la boucle. Vérifiez le code. D'ailleurs il peut encore y avoir des erreurs.

  3. #3
    Membre très actif
    Avatar de ProgVal
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2006
    Messages
    636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2006
    Messages : 636
    Par défaut
    Effectivement, c'est exact.

    Le fait que le code semble non optimisé, c'est parce que j'ai enlevé des lignes, pour faciliter la compréhension (raté).

    J'ai modifié le script pour corriger le bug, on verra bien ce que ça donnera...

  4. #4
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    Attention toutefois si vous vous inspirez de mon code : j'y ai remarqué une erreur. C'est corrigé

Discussions similaires

  1. Problème utilisation de ressources (CPU / RAM)
    Par CAML dans le forum Administration
    Réponses: 2
    Dernier message: 09/07/2008, 08h41
  2. Réponses: 3
    Dernier message: 21/12/2007, 17h34
  3. Process utilise 99% du cpu
    Par yakotey dans le forum Administration système
    Réponses: 5
    Dernier message: 27/02/2007, 20h03
  4. Récuperer la valeur de l'utilisation totale du cpu
    Par xodeax dans le forum Administration système
    Réponses: 5
    Dernier message: 05/07/2006, 15h24
  5. Utilisation total du CPU
    Par programmerPhil dans le forum Administration système
    Réponses: 5
    Dernier message: 20/12/2005, 02h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo