Programmation » Les threads, c'est mal?
Les threads, c'est mal?
Publié le 18/04/2006 @ 12:17:24,
Par zionhttp://www.informaticien.be/forum_topic-2201-21817-Posix_Threads___Condition_Variables__Cpu_Usage.html#p21817
Hormis le vrai temps réel, ou la vraie concurrence cpu-intensive, la plupart des problèmes résolus aujourd'hui avec des threads peuvent en général être résolus par select() ou assimilé... Et c'est une tendance que j'observe de plus en plus dans les applications type serveur ou GUI. Je suis prêt à argumenter davantage dans un autre débat bien sûr...
Alors non, je ne suis pas d'accord, les threads c'est bien
Bon, je n'en sais rien pour ce qu'il en est de posix, mais il y a clairement des trucs qui seraient une merde sans thread en Delphi sous W32. Si tu persistes, on continue le débat avec plaisir
Citation de: philfr
Cela dit, les threads c'est mal ...Hormis le vrai temps réel, ou la vraie concurrence cpu-intensive, la plupart des problèmes résolus aujourd'hui avec des threads peuvent en général être résolus par select() ou assimilé... Et c'est une tendance que j'observe de plus en plus dans les applications type serveur ou GUI. Je suis prêt à argumenter davantage dans un autre débat bien sûr...
Alors non, je ne suis pas d'accord, les threads c'est bien
Bon, je n'en sais rien pour ce qu'il en est de posix, mais il y a clairement des trucs qui seraient une merde sans thread en Delphi sous W32. Si tu persistes, on continue le débat avec plaisir
Je suis le Roy
Les threads, c'est mal?
Publié le 18/04/2006 @ 12:38:20,
Par ovhOui philfr nous attendons tes arguments, développe à fond, ça m'intéresse
Je n'ai rien à voir avec www.ovh.com
Les threads, c'est mal?
Publié le 18/04/2006 @ 13:03:41,
Par philfrBon, ben comme je ne développe ni avec Delphi et encore moins sur W32 je suis prêt à mettre des limites à mon affirmation par manque de connaissances.
Mais comme le post initial parlait des Posix threads, je suppose qu'il ne s'agit pas de W32 (encore que je puisse me tromper sur ce point là également)
Ce disclaimer étant établi, voici mon point de vue résumé:
- les threads permettent de résoudre un problème de concurrence en n'y réfléchissant pas: on développe chaque thread comme s'il était tout seul et c'est bien parce que c'est facile;
- on se trouve très vite confronté au problème de l'accès partagé à des données (ou à toute autre chose partageable, comme du hardware pour ceux qui comme moi font de l'embarqué), et toutes les implémentations de threads apportent une solution, avec des mécanismes de synchronisation (mutex, sémaphores, variables de condition, ...) qui sont assez simples, en apparence en tout cas;
- on développe son système, on le teste au fur et à mesure de son développement, et tout va bien, jusqu'au jour où on le met en production, que la charge augmente, et que des bugs inconnus à ce jour apparaissent mystérieusement;
- on se rend compte que les mécanismes de synchronisation ne sont pas si simples, et surtout qu'ils ne peuvent pas être testés de façon exhaustive. Les conditions de course sont très rarement reproductibles de façon systématique;
- le comportement d'un système thread-based ne peut pas être facilement prédit par la lecture de son code (un comble !) car ce comportement se trouve plus dans les interactions entre composants que dans chaque composant individuel;
- ma conclusion troll: si j'ai un problème de concurrence et que j'utilise des threads pour le résoudre, je me retrouve avec deux problèmes au lieu d'un.
Les seuls problèmes qui peuvent être résolus simplement et élégamment par des threads, sont les problèmes où les threads n'interagissent pas (ex: un long calcul RSA dans son coin jusqu'à rendre la réponse, pendant ce temps le reste du programme continue à réagir à l'utilisateur)
Pour la plupart des autres cas, où ce que l'on veut est un programme qui réagit à beaucoup d'inputs possibles, mais qui autrement passe le plus clair de son temps à attendre ces inputs, le ractor pattern est bien plus approprié. Son utilisation se fait en général avec une librairie "callback-based", où les APIs ne sont jamais bloquants, mais auxquels on passe un pointeur de fonction à appeler quand le résultat est disponible. L'implémentation en Unix se fait en passant par le system call select() ou poll() qui permet d'attendre simultanément sur plusieurs file descriptors, et de traiter en série les événements au fur et à mesure de leur arrivée.
Si l'application n'est pas cpu-bound, la réactivité sera toujours meilleure avec ce genre d'architecture qu'avec un système threadé (le scheduling lui-même apporte un overhead pour le cpu). L'occupation de ressources (mémoire) est également bien plus faible en général.
La courbe d'apprentissage des threads est rapide, et c'est son danger parce qu'il faut beaucoup d'expérience pour développer correctement avec des threads, et encore plus pour débugger quand ça ne va pas, alors qu'un programmeur débutant a l'impression de suite de comprendre ce qu'il fait tant qu'il est dans son thread.
La courbe d'apprentissage d'une librairie event/callback-based est plus lente, juste parce que les langages ne sont pas conçus avec ce paradigme. Avec un langage OO de haut niveau (qui a dit python ?), en peut rendre la chose presque naturelle. En C (et j'ai développé un tel framework), un certain nombre de problèmes persistent, mais le développement est néanmoins incroyablement plus rapide et moins bug-prone (le management a d'ailleurs fini par me croire sur ces points). Les problèmes qui subsistent sont ceux inhérents au C (allocation de mémoire et pointeurs).
Voilà , j'arrête ici pour l'instant, parce qu'il y a sûrement d'autres réactions entre temps...
Dernière édition: 18/04/2006 @ 13:07:23
Mais comme le post initial parlait des Posix threads, je suppose qu'il ne s'agit pas de W32 (encore que je puisse me tromper sur ce point là également)
Ce disclaimer étant établi, voici mon point de vue résumé:
- les threads permettent de résoudre un problème de concurrence en n'y réfléchissant pas: on développe chaque thread comme s'il était tout seul et c'est bien parce que c'est facile;
- on se trouve très vite confronté au problème de l'accès partagé à des données (ou à toute autre chose partageable, comme du hardware pour ceux qui comme moi font de l'embarqué), et toutes les implémentations de threads apportent une solution, avec des mécanismes de synchronisation (mutex, sémaphores, variables de condition, ...) qui sont assez simples, en apparence en tout cas;
- on développe son système, on le teste au fur et à mesure de son développement, et tout va bien, jusqu'au jour où on le met en production, que la charge augmente, et que des bugs inconnus à ce jour apparaissent mystérieusement;
- on se rend compte que les mécanismes de synchronisation ne sont pas si simples, et surtout qu'ils ne peuvent pas être testés de façon exhaustive. Les conditions de course sont très rarement reproductibles de façon systématique;
- le comportement d'un système thread-based ne peut pas être facilement prédit par la lecture de son code (un comble !) car ce comportement se trouve plus dans les interactions entre composants que dans chaque composant individuel;
- ma conclusion troll: si j'ai un problème de concurrence et que j'utilise des threads pour le résoudre, je me retrouve avec deux problèmes au lieu d'un.
Les seuls problèmes qui peuvent être résolus simplement et élégamment par des threads, sont les problèmes où les threads n'interagissent pas (ex: un long calcul RSA dans son coin jusqu'à rendre la réponse, pendant ce temps le reste du programme continue à réagir à l'utilisateur)
Pour la plupart des autres cas, où ce que l'on veut est un programme qui réagit à beaucoup d'inputs possibles, mais qui autrement passe le plus clair de son temps à attendre ces inputs, le ractor pattern est bien plus approprié. Son utilisation se fait en général avec une librairie "callback-based", où les APIs ne sont jamais bloquants, mais auxquels on passe un pointeur de fonction à appeler quand le résultat est disponible. L'implémentation en Unix se fait en passant par le system call select() ou poll() qui permet d'attendre simultanément sur plusieurs file descriptors, et de traiter en série les événements au fur et à mesure de leur arrivée.
Si l'application n'est pas cpu-bound, la réactivité sera toujours meilleure avec ce genre d'architecture qu'avec un système threadé (le scheduling lui-même apporte un overhead pour le cpu). L'occupation de ressources (mémoire) est également bien plus faible en général.
La courbe d'apprentissage des threads est rapide, et c'est son danger parce qu'il faut beaucoup d'expérience pour développer correctement avec des threads, et encore plus pour débugger quand ça ne va pas, alors qu'un programmeur débutant a l'impression de suite de comprendre ce qu'il fait tant qu'il est dans son thread.
La courbe d'apprentissage d'une librairie event/callback-based est plus lente, juste parce que les langages ne sont pas conçus avec ce paradigme. Avec un langage OO de haut niveau (qui a dit python ?), en peut rendre la chose presque naturelle. En C (et j'ai développé un tel framework), un certain nombre de problèmes persistent, mais le développement est néanmoins incroyablement plus rapide et moins bug-prone (le management a d'ailleurs fini par me croire sur ces points). Les problèmes qui subsistent sont ceux inhérents au C (allocation de mémoire et pointeurs).
Voilà , j'arrête ici pour l'instant, parce qu'il y a sûrement d'autres réactions entre temps...
Dernière édition: 18/04/2006 @ 13:07:23
Les threads, c'est mal?
Publié le 18/04/2006 @ 13:18:06,
Par zionQuand tu parles d'un système event based pour un calcul important (partons sur le principe du RSA), ta librairie externe est implicitement dans un autre thread, sans quoi, sous Windows en tout cas, ca va tout de même empêcher ton application de réagir rapidement à ton utilisateur.
Pour de petits problèmes qui nécessitent en effet un output user et qui bloquent quand même ses input, un simple appel implicite de temps à autre dans le code pour s'occuper des events est suffisant, mais je suis quand même content de les avoir eu à disposition pour Kapere (quoi que comme tu l'expliques très bien, le débuggage est plutôt hard et je me suis planté dans de nombreux choix à l'époque).
Mais pour le cas de Kapere, ou il y a par exemple 10 connexions en simultané pour télécharger des fichiers, sauver ca sur le disque et après faire un output user pour montrer que ca bouge... C'est vrai, c'était un cauchemard, mais sans thread j'aurais eu aucune chance de m'en sortir vu qu'il y a des APIs bloquantes qui vont te laisser plusieurs secondes sans possibilité de traiter les events pour l'affichage.
Enfin, à refaire, je referais quand même tout autrement
Dernière édition: 18/04/2006 @ 13:19:38
Pour de petits problèmes qui nécessitent en effet un output user et qui bloquent quand même ses input, un simple appel implicite de temps à autre dans le code pour s'occuper des events est suffisant, mais je suis quand même content de les avoir eu à disposition pour Kapere (quoi que comme tu l'expliques très bien, le débuggage est plutôt hard et je me suis planté dans de nombreux choix à l'époque).
Mais pour le cas de Kapere, ou il y a par exemple 10 connexions en simultané pour télécharger des fichiers, sauver ca sur le disque et après faire un output user pour montrer que ca bouge... C'est vrai, c'était un cauchemard, mais sans thread j'aurais eu aucune chance de m'en sortir vu qu'il y a des APIs bloquantes qui vont te laisser plusieurs secondes sans possibilité de traiter les events pour l'affichage.
Enfin, à refaire, je referais quand même tout autrement
Dernière édition: 18/04/2006 @ 13:19:38
Je suis le Roy
Les threads, c'est mal?
Publié le 18/04/2006 @ 13:20:37,
Par philfr
Les threads, c'est mal?
Publié le 18/04/2006 @ 13:26:11,
Par zionFrequently beginning programmers will try to write network programs as multithreaded programs. Granted, this is tempting -- all the convenience of being in one process on one hand, and all the convenience of writing natural, blocking code.
Il l'a écrit pour moi?
Alternatives
* Multiple processes -- if you have relatively few concurrent processes and have little need for communication between them, this is a good solution. There are many variants on the solutions here, and the most common optimization is preforking.
* Event-based programming
* Co-operative threads, such as co-routines.
* Multiple processes -- if you have relatively few concurrent processes and have little need for communication between them, this is a good solution. There are many variants on the solutions here, and the most common optimization is preforking.
* Event-based programming
* Co-operative threads, such as co-routines.
1. Le fork on oublie sous w32 et la communication inter process c'est une merde sans nom.
2. C'est malheureusement pas possible avec tout, y a parfois des fonctions externes bloquantes ou on l'a dans notre * quoi qu'on fasse.
3.
Je suis le Roy
Les threads, c'est mal?
Publié le 18/04/2006 @ 13:27:28,
Par philfrzion> le problème que tu évoques des API existants qui sont bloquants est réel, mais il vient des API bloquants, pas du framework non bloquant qui cherche à les utiliser: il faut en effet réimplémenter tous ces API en version non bloquante pour avoir un framework asynchrone complet.
Les threads, c'est mal?
Publié le 18/04/2006 @ 13:30:56,
Par ovhC'est pas gagné quoi
En tout cas c'est du haut vol ici
PS : merci pour les explications et le débat intéressant les gars
Dernière édition: 18/04/2006 @ 13:31:57
En tout cas c'est du haut vol ici
PS : merci pour les explications et le débat intéressant les gars
Dernière édition: 18/04/2006 @ 13:31:57
Je n'ai rien à voir avec www.ovh.com
Les threads, c'est mal?
Publié le 18/04/2006 @ 13:32:38,
Par zionD'accord, mais d'un autre côté, je me vois mal demander à ce que chaque API renvoie le fait que ce soit fini en event. C'est utopiste, et ce serait pas facilement gérable.
Imagine pour Kapere, tu downloades un fichier de 2gb. Ok?
Pour éviter la fragmentation de ton disque, j'alloue un stream de la taille direct du fichier, 2GB. La création du fichier va prendre plusieurs secondes. Mais c'est un cas extrême et si le "Size := 2gb" du TFileStream était asynchrone, j'aurais l'air con en écrivant un truc en fin de fichier la milliseconde suivante.
Il y a une bonne partie des APIs/fonctions qui doivent rester bloquantes
Dernière édition: 18/04/2006 @ 13:33:17
Imagine pour Kapere, tu downloades un fichier de 2gb. Ok?
Pour éviter la fragmentation de ton disque, j'alloue un stream de la taille direct du fichier, 2GB. La création du fichier va prendre plusieurs secondes. Mais c'est un cas extrême et si le "Size := 2gb" du TFileStream était asynchrone, j'aurais l'air con en écrivant un truc en fin de fichier la milliseconde suivante.
Il y a une bonne partie des APIs/fonctions qui doivent rester bloquantes
Dernière édition: 18/04/2006 @ 13:33:17
Je suis le Roy
Les threads, c'est mal?
Publié le 18/04/2006 @ 13:48:49,
Par philfr1. Le fork on oublie sous w32 et la communication inter process c'est une merde sans nom.
2. C'est malheureusement pas possible avec tout, y a parfois des fonctions externes bloquantes ou on l'a dans notre * quoi qu'on fasse.
3.
2. C'est malheureusement pas possible avec tout, y a parfois des fonctions externes bloquantes ou on l'a dans notre * quoi qu'on fasse.
3.
1. comme dit au début, moi je parle de posix, mes mécanismes interprocess marchent bien et sont performants
2. en effet: la plupart des libs aujourd'hui sont bloquantes Mais ça va changer !
3. Les cooperative threads sont une autre façon de faire de l'asynchrone: il ne se produit de context switch que lors d'appels à des fonctions bloquantes: le tout tourne donc toujours dans un thread, et tu ne peut pas plus utiliser une lib bloquante dans ce genre de framework.
Les threads, c'est mal?
Publié le 18/04/2006 @ 13:55:55,
Par philfrDans les frameworks asynchrones, aucun API n'est bloquant, et tout ceux qui renvoient un résultat le font via un callback ou un event.
Quant à ton problème de préallocation de disque et de fragmentation, c'est dommage que tu doives t'occuper de ce genre de choses dans une application non ? Pour moi c'est le rôle de l'OS de faire le concierge .
Quid si ton fichier est stocké sur le réseau ? Ou si tu ne sais pas quelle taille il aura avant de le charger ?
Dernière édition: 18/04/2006 @ 13:56:26
Quant à ton problème de préallocation de disque et de fragmentation, c'est dommage que tu doives t'occuper de ce genre de choses dans une application non ? Pour moi c'est le rôle de l'OS de faire le concierge .
Quid si ton fichier est stocké sur le réseau ? Ou si tu ne sais pas quelle taille il aura avant de le charger ?
Dernière édition: 18/04/2006 @ 13:56:26
Les threads, c'est mal?
Publié le 18/04/2006 @ 14:01:31,
Par zionSi je ne connais pas la taille tant pis, j'augmente la taille du fichier au fur et à mesure, mais ca augmente largement la fragmentation au niveau du disque.
Ce serait en effet sympa que l'OS se démerde de ce côté, mais si il faut 10s pour créer le fichier et que la ligne suivante tu veux écrire dans le fichier, t'es baisé
A moins évidemment que l'écriture dans le fichier soit bloquée par l'OS jusqu'à ce qu'il soit réellement crée, mais alors il a intérêt a avoir un sacré buffer si tu commences à écrire comme un sauvage...
Ce serait en effet sympa que l'OS se démerde de ce côté, mais si il faut 10s pour créer le fichier et que la ligne suivante tu veux écrire dans le fichier, t'es baisé
A moins évidemment que l'écriture dans le fichier soit bloquée par l'OS jusqu'à ce qu'il soit réellement crée, mais alors il a intérêt a avoir un sacré buffer si tu commences à écrire comme un sauvage...
Je suis le Roy
Les threads, c'est mal?
Publié le 18/04/2006 @ 15:47:20,
Par philfrBah, moi j'utilise un vrai OS, et la fragmentation je ne connais pas
Un fichier chez moi, c'est un truc que j'ouvre, dans lequel je peux lire et écrire, que je ferme, et que je peux rouvrir plus tard pour faire la même chose.
Comme mes connexions TCP pour lesquelles je n'ai pas à me soucier des timeouts ou des MTU...
Un fichier chez moi, c'est un truc que j'ouvre, dans lequel je peux lire et écrire, que je ferme, et que je peux rouvrir plus tard pour faire la même chose.
Comme mes connexions TCP pour lesquelles je n'ai pas à me soucier des timeouts ou des MTU...
Les threads, c'est mal?
Publié le 18/04/2006 @ 15:52:28,
Par zionOui, mais tu vois... les threads c'est important sous Windows
Je suis le Roy
Les threads, c'est mal?
Publié le 18/04/2006 @ 16:07:48,
Par philfrEt Windows, c'est important pour toi ?
Les threads, c'est mal?
Publié le 18/04/2006 @ 16:14:33,
Par zionPour le moment oui, vu que Kylix est assez mauvais comme environnement de dev sous Linux, il n'arrive pas à la cheville de Delphi 7 (y a pleins de soucis dans la gestion des raccourcis). (Puis y a des petits détails et logiciels qui me manqueraient trop )
Je suis le Roy
Les threads, c'est mal?
Publié le 18/04/2006 @ 17:08:30,
Par AltarEt Windows, c'est important pour toi ?
Et quand on code des softwares pour monsieur tout le monde, je dirais qu'il est risqué de se priver de 95% du marché. Enfin ce n'est que mon avis
Les threads, c'est mal?
Publié le 18/04/2006 @ 17:15:00,
Par zionAltar> Ca m'arrive plus vraiment, le seul soft pour monsieur tout le monde que je faisais, c'est fini. Mais il m'arrive de devoir faire des progs pour des clients sous Windows en effet
Je suis le Roy
Les threads, c'est mal?
Publié le 18/04/2006 @ 20:35:16,
Par philfrBen, oui, j'allais dire....
Google est un software pour monsieur tout le monde aussi, mais c'est pas développé sous Windows...
Google est un software pour monsieur tout le monde aussi, mais c'est pas développé sous Windows...
Les threads, c'est mal?
Publié le 18/04/2006 @ 21:14:46,
Par antpPour éviter la fragmentation de ton disque, j'alloue un stream de la taille direct du fichier, 2GB. La création du fichier va prendre plusieurs secondes.
Seulement en FAT32.
En NTFS c'est immédiat normalement (enfin, ça l'était quand j'ai testé).
Sinon pour l'histoire de la fragmentation, même si avec d'autres FS ça fragmente moins il y a des cas où ça fragmente.
Si tu remplis ton fichier, à 100 Mo t'arrives à la fin de la zone libre, tu continues ailleurs. Il va pas bouger les 100 Mo pour passer à 101 Mo contigus. Alors que si dès le début il sait que ça va faire 2 Go il peut attaquer une zone libre de plus de 2 Go.
Dernière édition: 18/04/2006 @ 21:15:57
mes programmes ·· les voitures dans les films ·· champion des excuses bidons