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

Delphi Discussion :

Debug multi-threads et outils d’analyse


Sujet :

Delphi

  1. #1
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    849
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 849
    Points : 1 174
    Points
    1 174
    Par défaut Debug multi-threads et outils d’analyse
    Bonjour,

    J’ai une appli qui utilise de façon intensive le multi-threads à 3 niveaux d’imbrication.

    Tout fonctionne proprement, jusqu’au moment où le réseau est soit surchargé, soit parasité, et provoque des erreurs dans les échanges avec le serveur de base de données.
    À ce moment-là, le programme ne fait plus rien, sans que malgré touteS les traces possibles et imaginables me permette de trouver ce qui est « planté ».

    J’ai cherché des moyens pour trouver et corriger mon PB, tel que : https://github.com/thatlr/Delphi-StackTrace, mais ÇA ne m’a pas aidé.

    Auriez-vous des outils (Free de préférence) qui pourraient m’aider à analyser la Stack ou qui me permettraient de trouver ce qui plante ?

    Merci d’avance de vos suggestions !

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 612
    Points : 25 303
    Points
    25 303
    Par défaut
    Chaque thread a bien une connexion dédiée à la base de données ?
    En général, faut éviter d'utiliser un même objet connexion dans plusieurs threads, cela s'applique aux Query, qui utilisent la connexion


    Et que veux dire "multi-threads a 3 niveaux d’imbrication", c'est le Main qui lance un thread secondaire qui lance un 3ème thread ?
    J'ai eu ce genre de structure dans un logiciel de supervision avec vidéo-surveillance, le Main et le Thread secondaire était géré par mon Exe mais le 3ème niveau de thread était produit par une DLL, très volatile, je n'avais aucune maitrise dessus, ne supportant pas de long synchronize, j'avais donc mis une FIFO pour récupérer les données et les traiter dans un thread dédié, cela pouvait remonter jusqu'à la DB pour enregistrer des meta data, le flux image étant stocké ailleurs.

    L'abus de Section Critique ou de MREWS avec promotion de verrou peuvent amener à des deadlock, tout traité en asynchrone par FIFO et un dépilement séquentiel évite que certains threads se bloquent qui en bloquent d'autres et que tout s'emballe à la fin.
    Toujours penser à ce que le temps de blocage soit le plus court que possible et penser que les verrous n'entrent pas en collision comme un thread A qui interagit avec threadB avec le VerrouC mais aussi le threadB qui interagit avec threadA avec le VerrouD, là c'est le dead-lock assuré.

    Je n'ai jamais utilisé d'outil, c'était en C++Builder XE3, j'ai tout simplement réécrit des passages entiers.
    Idem en Delphi XE2, pour un problème de libération de données avant d'avoir eu le temps de les utiliser, juste des verrous mieux penser pour éviter que la libération (faite par la lib) avant que le programme ait eu le temps de traiter un event (aussi déclencher par la lib, elle même n'étant pas totalement threadsafe)
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    849
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 849
    Points : 1 174
    Points
    1 174
    Par défaut
    J’ai un Thread qui fait office de chef d’orchestre, en dessous, j’ai des threads qui tournent en tâche de fond pour du spécifique non lié à la database et j’ai un Thread qui gère un pool de threads pour des traitement dédiés, chaque Thread dédié a son sous-Thread pour l’accès à la database.

    En temps ordinaire, même si sur le serveur, la CPU monte à 100% (mais pas lié à mon prog), tout fonctionne parfaitement.

    Là ou cela part en cacahuète, c’est quand le réseau est parasité, et que j’ai des retours du serveur de base de données disant qu’il n’a pas pu traiter la demande à cause des « merdes » qui transitent sur le réseau à ce moment là, le parasitage me pourrit, soit l’envoi, soit la réception des données depuis le serveur de base de données.

    Cela doit faire planter ou verrouiller quelque chose dans mon prog sans que j’arrive déterminer où, ce qui m’amène à la question : existe-t-il un outil capable de me dire en direct ce qui est planté ou verrouillé pour Delphi ?

    Quelle solution utilisez-vous pour ce genre de cas ?

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 612
    Points : 25 303
    Points
    25 303
    Par défaut
    un CPU a 100% n'est jamais bon signe, si l'on fait des calculs très intenses, cela se peut mais dès que l'on a du réseau, du fichier, le CPU baisse puisque cela attend les périphériques lents.
    Qaund tu dis que cela monte à 100% mais pas à cause de ton programme, c'est genre le server SQL qui consomme ?

    Sinon, beaucoup de CPU, tu n'aurais pas des boucles avec des patiences active (genre lire une valeur en boucle sans utiliser de sémaphore)
    un CPU à 100 / Core en permanence, faut surveiller car un thread pourrait consommer inutilement

    Ayant fait bcp de TCP manuellement à haute dose, chaque socket est isolé, il n'y a pas de parasitage, le seul cas de parasitage serait que deux threads utilisent le même socket, là c'est la merde garantie.

    Et comment tu synchronises tous ces threads, cela semble beaucoup, c'est quel genre de programme, même le serveur back-office, accessible en UPD & TCP\IP, en HTTP (REST ou SOAP) n'a pas autant de sous-sous thread, tu as en gros le thread de listen pour chaque port, les threads pour chaque connexion, le gestionnaire de pool DB (attention à la rétention, il faut parfois passer outre et disposer d'un accès direct sans le pool)

    Tu ne dis pas quel provider DB tu utilises, combien d'objet connexion et d'objet query
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    849
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 849
    Points : 1 174
    Points
    1 174
    Par défaut
    Le 100% est exceptionnel !

    pour faire attendre mes threads, j’utilise des TEvent dans le pool de threads qui fait appel à un sous-thread dédié au accès à Firebird et il a sa propre connexion, j’ai isolé au maximum les interactions entre threads !

    c’est vraiment quand le réseau est parasité, que les pb arrivent, comme si les requêtes ou leurs réponses était incomplète (dans le sens datagrams) une fois qu’elles transite sur le réseau a ce moment là.

    Cela doit bloquer quelque part à cause des erreurs en réponse mais pas moyen de mettre le nez dessus malgré un tracé conséquent !

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 612
    Points : 25 303
    Points
    25 303
    Par défaut
    "un sous-thread dédié au accès à Firebird et il a sa propre connexion"
    C'est un seul thread pour tous ou il y en a plusieurs ?

    FireBird via quel provider ?
    FireBird c'est la DB, mais c'est le provider qui là doit supporter le multi-thread, FireDAC par exemple

    Tous ces threads sont vraiment utiles, comment échanges-tu les données ?
    Le TEvent permet de gérer la synchron mais le partage de données, tu utilises des TObjectList par exemple (voir TThreadList, ou TQueue<>) car il ne faut surtout pas échanger de DataSet (Query) entre les threads car tu ne peux pas anticipé à quel moment, il y aura un fetch (ou alors faudrait tout protéger à coup de section critique rendant les threads presque inutiles, tu peux cependant échanger un TClientDataSet contenant déjà toutes les données PackedRecord à -1, il a tout récupéré lors du Open, tu peux même détruire la Query sous jacente (faut jouer avec un TDataSetProvider alloué à la volée)
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    849
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 849
    Points : 1 174
    Points
    1 174
    Par défaut
    Chaque thread du pool a son propre sous-thread qui accède à Firebird en utilisant UIB, aucun sous-thread ne partage sa connexion au serveur de la base de données.

    mettons que le spool a 4 threads, alors il y aura 4 sous-thread avec chacun sa propre connexion a Firebird.

    Aucun partage entre les threads, le traitement des requêtes est propre à chaque thread du spool, j’ai isolé au maximum les traitements de chaque threads, par contre il y a mimimum 1 tcriticalsection dans chaque thread !

Discussions similaires

  1. Debug multi-thread ?
    Par arambelo dans le forum Général Python
    Réponses: 0
    Dernier message: 21/04/2010, 14h52
  2. Debuger du code Java multi-threadé
    Par LGnord dans le forum Tests et Performance
    Réponses: 8
    Dernier message: 15/01/2010, 15h39
  3. Tri multi-threadé
    Par Tifauv' dans le forum C
    Réponses: 8
    Dernier message: 28/06/2007, 09h00
  4. Debug application multi thread
    Par Razowsky dans le forum MFC
    Réponses: 1
    Dernier message: 03/05/2005, 18h14
  5. [Kylix] exception qtinft.dll et multi-threading
    Par leclaudio25 dans le forum EDI
    Réponses: 3
    Dernier message: 27/03/2003, 18h09

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