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

Python Discussion :

[serial] performances de l'uart


Sujet :

Python

  1. #1
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    946
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 946
    Points : 1 351
    Points
    1 351
    Par défaut [serial] performances de l'uart
    Salut,

    J'ai un problème assez inattendu. J'utilise un interface can sur USB qui crée une uart virtuelle. En clair, tout les messages circulant sur le bus can sont envoyés sur cette uart sous forme de chaines, il faut ensuite les décoder. On peut aussi envoyer des messages sur le bus can, mais il faut d'abord les réencoder sous forme de chaines.

    Le driver en python marche plutôt bien, mais quand la communication est très chargée, je perds des octets en réception. L'uart est à 115200 bauds, le driver est une encapsulation de la classe serial avec un thread pour la réception, et dans ce thread j'ai un time.sleep(0.001) à chaque fois que le tampon de réception est vide. Sans le sleep, je ne perds aucun octet, mais la conso du thread est quasiment 20% de la cpu.

    Et là, je m'aperçois dans le gestionnaire de périphériques que la taille max du buffer en réception est 4096 et que j'y suis par défaut. Quelqu'un à une idée pour augmenter ce buffer ou diminuer le temps minimum du sleep?

    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 canReceiver(self):
            """ this is a thread dedicated to messages reception"""
            while self.running:
                if self.gateway.inkey():
                    car = self.gateway.getchar()
                    if car == '':
                        # a timeout has occured
                        self.incoming = ''
                    else:
                        self.incoming += car
                    if car == miStick_uart.UART_NEWLINE:
                        # line completed
                        self.parseIncoming(self.incoming.strip())
                        self.incoming = ''
                time.sleep(0.001)
            self.can_reader._Thread__stop()
            self.stopping = False
    A+

    Pfeuh

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Techniquement pour ne pas "pooler" en attendant que le caractère suivant arrive et bouffer du CPU inutilement, on fait une attente passive via "select" sur le fd associé au keyboard (sous Unix).

    Reste à voir comment a été codé "self.gateway" pour y ajouter un select avec timeout.

    - W

    Ps: il y a des méthodes plus efficaces que "select" mais comme il n'y a pas des milliers d'UART, çà suffira.
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    En supposant que self.gateway.getchar() attend indéfiniment l'arrivée d'un caractère, pourquoi ne pas encapsuler la lecture caractère/caractère dans
    un sous-thread: les caractères lus pourraient aller dans une Queue partagée.
    Queue dispose de méthodes pour attendre avec timeout.
    C'est un peu "luxe" mais plus simple que d'aller dépiauter le driver/OS.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    946
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 946
    Points : 1 351
    Points
    1 351
    Par défaut
    En fait, je suis sous windows, je ne vois pas ce qu'est une attente passive via "select". Je ne fais un getchar que si un caractère a été reçu, grâce à la méthode inkey. Du coup, je me rends compte que le thread de réception n'est pas bon. Une fois qu'un octet a été détecté, il faudrait boucler sur du getchar jusqu'à la fin de la réception de la chaine. Tel que c'est là, je n'ai pas la moindre chance de détecter un timeout!

    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
        def canReceiver(self):
            """ this is a thread dedicated to messages reception"""
            while self.running:
                if self.gateway.inkey():
                    while 1:
                        car = self.gateway.getchar()
                        if car == '':
                            # a timeout has occured
                            self.incoming = ''
                            break
                        else:
                            self.incoming += car
                        if car == miStick_uart.UART_NEWLINE:
                            # line completed
                            self.parseIncoming(self.incoming.strip())
                            self.incoming = ''
                            break
                time.sleep(0.001)
            self.can_reader._Thread__stop()
            self.stopping = False
    Bon, effectivement, modifié comme ci-dessus, ça marche mieux!

    A+

    Pfeuh

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [serial.fread] gain de performance
    Par tubaas dans le forum MATLAB
    Réponses: 5
    Dernier message: 19/03/2010, 11h01
  2. [ POSTGRESQL ] Problème de performance
    Par Djouls64 dans le forum PostgreSQL
    Réponses: 6
    Dernier message: 26/05/2003, 16h18
  3. [JDBC][connexion persistante] performances avec JDBC
    Par nawac dans le forum Connexion aux bases de données
    Réponses: 6
    Dernier message: 06/05/2003, 10h37
  4. Problème de serialization
    Par bruno270579 dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 30/04/2003, 18h11
  5. performance entre 3DS, ase, asc ...
    Par amaury pouly dans le forum OpenGL
    Réponses: 3
    Dernier message: 24/03/2003, 11h41

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