Supafresh
Messages postés40Date d'inscriptionsamedi 1 février 2014StatutMembreDernière intervention 7 août 2014
-
2 avril 2014 à 15:48
nagaD.scar
Messages postés4272Date d'inscriptionsamedi 8 septembre 2007StatutMembreDernière intervention 4 janvier 2023
-
17 avril 2014 à 08:03
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.
je vais pas trop parler, au final on dit la même chose avec des termes différents.
Juste comme ca, epoll permet de gérer les événements et donc travaille bien en parallèle (tu n'utilise pas les thread directement mais au final tu en as bien qui gèrent tes connexion / événements / pile / etc. ). Ce n'est pas parce qu'on ne voit ce qu'utilise nos composants qu'il faut l'ignorer.
cptpingu
Messages postés3837Date d'inscriptiondimanche 12 décembre 2004StatutModérateurDernière intervention28 mars 2023123 16 avril 2014 à 18:09
Pour la communication entre client, tu n'utilise pas la classe thread mais tu ordonne toi même le séquencement.
Rien n'est réordonné par moi même. c'est bien le "epoll" qui se charge de l'ordonnancement.
Le soucis dans ce cas c'est qu'une pile se forme : oui tu ne veux pas utiliser un thread, mais quand le client envoi une trame il faut écouter. quand c'est de manière séquentiel, tu créé une latence
Je ne comprends pas ton argument, Le problème est très exactement le même avec du multi-threading. Il ne faut pas confondre concurrence et parallélisme. Ton nombre de coeur n'étant pas infini, tu ne peux pas avoir une parallélisation parfaite. Tu entres donc forcément dans un cas de concurrence, et le phénomène que tu décris se produit tout aussi bien en multi-threading. Si tu as 8 coeurs, et 9 clients, le 9ème client va de toute façon attendre.
mais ca reste assez limité comme solution.
C'est justement la raison pour laquelle je réponds en public: non, ce n'est ni une bidouille, ni une méthode "limitée". Ne pas faire de thread est parfois indispensable. Notamment dans certains domaines embarqués. J'ai un ami qui bosse actuellement sur un projet pour une grosse boîte (T**lès). Il développe une couche réseau pour communiquer efficacement entre deux appareils via des ondes radios (présence de multi-clients, forte charge possible). Il n'y a aucun thread. D'une part parce que ça coute "cher" (en terme de perfs sur des appareils faibles en puissance), d'autre part parce que c'est bien plus lent que de ne pas en faire, pour les raisons que j'ai déjà évoqué.
mais l'écoute est bien dans une tâche différente de ta tâche principale.
En mode mono-threadé, l'écoute est belle et bien en dehors de ta tâche principale. Voir le fonctionnement d'epoll, qui peut tout à fait être au courant de la disponibilité de plusieurs fd en parallèle. Tu peux voir epoll comme étant un outil multi-threadé "dans ton dos" par le kernel (ce qui n'est pas vrai, mais je me permet cette vulgarisation pour faciliter la compréhension).
[...] en effet il faudrait le tourner plutôt en disant que sans utiliser les outils du multitâche, on réinvente ce qui existe
Pas du tout. C'est juste un model différent pour un usage différent. Rien n'est réinventé.
(et il y a peu de chance , dans le cas où l'application est grosse et pourquoi pas interfacé dans une form, que ton code soit aussi performant).
Raison pour laquelle j'insiste: Rien à voir avec la taille de ton application, ou la présence ou non de "form". C'est l'usage que tu en fait qui fait le performance. Encore une fois, si tu as de très nombreuses tâches, très courtes, une appli mono-thread sera plus performante. Quant à la forme, elle aura certes son thread dédié pour ne pas "geler" l'affichage, mais la partie réseau aura aussi son seul thread dédié, si tu te trouves dans ce model.
Ne pas oublier que dans le model où tu reçois une quantité énorme de petites requêtes, tu seras "I/O bound" bien avant d'être "CPU bound". Or, tant que tu n'es pas "CPU bound", avoir 50 coeurs ne vas pas trop te servir...
alors oui dans l'absolu on peu même faire un client serveur en assembleur, mais c'est pas très pratique
Hors-sujet ?
====
Résumé pour le lecteur qui passerait sans vouloir se taper tout le pavé:
- Si nombreux clients donc nombreux appels ET requêtes traitées rapidement => Mono-thread plus rapide. Exemple (serveur de real-time bidding, echo server, etc...)
- Si requêtes moyennes/longues => Multi-thread plus rapide (upload de fichier, serveur de calcul qui répond une fois celui-ci fini, etc...).
ok je vois ton point de vue. Pour la communication entre client, tu n'utilise pas la classe thread mais tu ordonne toi même le séquencement. Le soucis dans ce cas c'est qu'une pile se forme : oui tu ne veux pas utiliser un thread, mais quand le client envoi une trame il faut écouter. quand c'est de manière séquentiel, tu créé une latence : au lieu d'écouter, tu vas vérifier s'il y a eu un message et dans ce cas tu vas le traiter, sinon tu vas checker les autres et tu tourne => il n'y a donc pas de vrai blocage en soit vu qu'on effectue des tests plutôt qu'attendre, mais ca reste assez limité comme solution.
C'est la même chose pour les événements : tu ne gère peu être pas ce qui attends l'événement mais l'écoute est bien dans une tâche différente de ta tâche principale.
ton commentaire qui laisse penser, à tort, que "pas de multi-thread == pas de multi-clients (viable)"
c'est ce que je veux dire, mais en effet il faudrait le tourner plutôt en disant que sans utiliser les outils du multitâche, on réinvente ce qui existe (et il y a peu de chance , dans le cas où l'application est grosse et pourquoi pas interfacé dans une form, que ton code soit aussi performant).
alors oui dans l'absolu on peu même faire un client serveur en assembleur, mais c'est pas très pratique ><
Au début, je fais un client mono-thread (voir la solution "sans thread, ni fork"), puis un multi-thread pour l'exemple (et aussi car le demandeur voulait gérer des demandes lourdes). Mais je précise bien qu'un client mono-threadé est non seulement viable, mais parfois plus adapté.
C'est la méthode kernel utilisée (select ou epoll) non bloquante qui est d'une certaine manière threadée (pour vulgariser) qui se charge de recevoir les clients en parallèle. Ensuite, si ton application mono-threadé ne gère pas des demandes trop lourdes (exit l'upload de fichier, mais ok pour du chat), alors elle va répondre séquentiellement à chacun de tes clients dans un temps imparti plus rapide que si tu te payais les switch de contexte kernel pour gérer X tâches en parallèles (dès le moment ou ton nombre de connexions > nombre de coeurs physiques). En d'autre terme, plus tu as de query par seconde, plus la concurrence coute cher en "context switching". Si tes tâches commencent à couter aussi cher en "context switching" que leur durée, tu perds en perfs.
Pour résumer: oui on peut faire un serveur mono-thread qui accepte plusieurs clients simultanéments (mais qui traite leur demande séquentiellement). C'est aussi la meilleure solution si les tâches a effectuer sont très courtes (quelques ms), mais très nombreuses (> 3000 query/secondes).
Je réponds ici, en écho à ton commentaire qui laisse penser, à tort, que "pas de multi-thread == pas de multi-clients (viable)". Il est important de préciser que le multi-thread et le multi-client sont deux notions différentes, pas forcément liées. Le choix du multi-threading ne doit pas être automatique, mais adaptée à la situation.
nagaD.scar
Messages postés4272Date d'inscriptionsamedi 8 septembre 2007StatutMembreDernière intervention 4 janvier 202317 16 avril 2014 à 13:32
@cptpingu: j'ai pas tout lu vu que je suis au taff, mais de ce que j'ai compris l'idée était de faire un système de pile pour traiter un connexion+demande à la fois. Le problème dans ce cas c'est que tu perds le principe de temps réel et tu va propager l'information de manière asynchrone entre les clients. Dans l'absolu, c'est de toutes facon plus ou moins le cas dans le sens où nos matos ne permettent pas de faire 8000 traitement parallèle (limité au nombre de coeur, donc 8 aujourd'hui si je ne m'abuse) et donc il n'y a pas de vrai synchro (après j'ai pas les compétences pour aller plus loin).
Ensuite, comment gère tu les nouveau clients sans thread (et évènement) ? si tes clients connecté ne peuvent rien faire car on attend une nouvelle connexion c'est pas top, trop procédural ... bon après si tu veux en parler il vaut mieux un post ou mp histoire de pas trop pourrir celui ci ^^
cptpingu
Messages postés3837Date d'inscriptiondimanche 12 décembre 2004StatutModérateurDernière intervention28 mars 2023123 16 avril 2014 à 12:29
@nagashima: Petite précision, car il y a une ambiguïté en te lisant. Il n'est pas nécessaire d'avoir plusieurs threads pour avoir plusieurs clients. On peut tout à fait avoir de nombreux clients, en mono-thread. D'ailleurs pour des tâches courtes, c'est plus performant. Les threads n'ont d'intérêt que si les tâches à effectuer sont longues. Voir cette discussion: http://codes-sources.commentcamarche.net/forum/affich-10017160-thread-semaphore
Supafresh
Messages postés40Date d'inscriptionsamedi 1 février 2014StatutMembreDernière intervention 7 août 20143 5 avril 2014 à 09:12
Merci, ce code est fait pour montrer au débutant comment connecter connecter deux machines via le réseau. Après si ils ont besoin d'un chat, je pourrais les aider mais là n'est pas le but de ce code.
salut,
Je n'ai pas testé ton code, je pense qu'il fonctionne, mais il serai plus intéressant d'utiliser les thread pour avoir plusieurs clients (ce qui permettra de mettre en place une communication entre les clients, tel qu'un chat ou un échange de fichier, par exemple).
Modifié par nagashima le 17/04/2014 à 08:03
je vais pas trop parler, au final on dit la même chose avec des termes différents.
Juste comme ca, epoll permet de gérer les événements et donc travaille bien en parallèle (tu n'utilise pas les thread directement mais au final tu en as bien qui gèrent tes connexion / événements / pile / etc. ). Ce n'est pas parce qu'on ne voit ce qu'utilise nos composants qu'il faut l'ignorer.
16 avril 2014 à 18:09
Je ne comprends pas ton argument, Le problème est très exactement le même avec du multi-threading. Il ne faut pas confondre concurrence et parallélisme. Ton nombre de coeur n'étant pas infini, tu ne peux pas avoir une parallélisation parfaite. Tu entres donc forcément dans un cas de concurrence, et le phénomène que tu décris se produit tout aussi bien en multi-threading. Si tu as 8 coeurs, et 9 clients, le 9ème client va de toute façon attendre.
C'est justement la raison pour laquelle je réponds en public: non, ce n'est ni une bidouille, ni une méthode "limitée". Ne pas faire de thread est parfois indispensable. Notamment dans certains domaines embarqués. J'ai un ami qui bosse actuellement sur un projet pour une grosse boîte (T**lès). Il développe une couche réseau pour communiquer efficacement entre deux appareils via des ondes radios (présence de multi-clients, forte charge possible). Il n'y a aucun thread. D'une part parce que ça coute "cher" (en terme de perfs sur des appareils faibles en puissance), d'autre part parce que c'est bien plus lent que de ne pas en faire, pour les raisons que j'ai déjà évoqué.
En mode mono-threadé, l'écoute est belle et bien en dehors de ta tâche principale. Voir le fonctionnement d'epoll, qui peut tout à fait être au courant de la disponibilité de plusieurs fd en parallèle. Tu peux voir epoll comme étant un outil multi-threadé "dans ton dos" par le kernel (ce qui n'est pas vrai, mais je me permet cette vulgarisation pour faciliter la compréhension).
Pas du tout. C'est juste un model différent pour un usage différent. Rien n'est réinventé.
Raison pour laquelle j'insiste: Rien à voir avec la taille de ton application, ou la présence ou non de "form". C'est l'usage que tu en fait qui fait le performance. Encore une fois, si tu as de très nombreuses tâches, très courtes, une appli mono-thread sera plus performante. Quant à la forme, elle aura certes son thread dédié pour ne pas "geler" l'affichage, mais la partie réseau aura aussi son seul thread dédié, si tu te trouves dans ce model.
Ne pas oublier que dans le model où tu reçois une quantité énorme de petites requêtes, tu seras "I/O bound" bien avant d'être "CPU bound". Or, tant que tu n'es pas "CPU bound", avoir 50 coeurs ne vas pas trop te servir...
Hors-sujet ?
====
Résumé pour le lecteur qui passerait sans vouloir se taper tout le pavé:
- Si nombreux clients donc nombreux appels ET requêtes traitées rapidement => Mono-thread plus rapide. Exemple (serveur de real-time bidding, echo server, etc...)
- Si requêtes moyennes/longues => Multi-thread plus rapide (upload de fichier, serveur de calcul qui répond une fois celui-ci fini, etc...).
Modifié par nagashima le 16/04/2014 à 16:38
C'est la même chose pour les événements : tu ne gère peu être pas ce qui attends l'événement mais l'écoute est bien dans une tâche différente de ta tâche principale.
c'est ce que je veux dire, mais en effet il faudrait le tourner plutôt en disant que sans utiliser les outils du multitâche, on réinvente ce qui existe (et il y a peu de chance , dans le cas où l'application est grosse et pourquoi pas interfacé dans une form, que ton code soit aussi performant).
alors oui dans l'absolu on peu même faire un client serveur en assembleur, mais c'est pas très pratique ><
Modifié par cptpingu le 16/04/2014 à 15:49
C'est la méthode kernel utilisée (select ou epoll) non bloquante qui est d'une certaine manière threadée (pour vulgariser) qui se charge de recevoir les clients en parallèle. Ensuite, si ton application mono-threadé ne gère pas des demandes trop lourdes (exit l'upload de fichier, mais ok pour du chat), alors elle va répondre séquentiellement à chacun de tes clients dans un temps imparti plus rapide que si tu te payais les switch de contexte kernel pour gérer X tâches en parallèles (dès le moment ou ton nombre de connexions > nombre de coeurs physiques). En d'autre terme, plus tu as de query par seconde, plus la concurrence coute cher en "context switching". Si tes tâches commencent à couter aussi cher en "context switching" que leur durée, tu perds en perfs.
Pour résumer: oui on peut faire un serveur mono-thread qui accepte plusieurs clients simultanéments (mais qui traite leur demande séquentiellement). C'est aussi la meilleure solution si les tâches a effectuer sont très courtes (quelques ms), mais très nombreuses (> 3000 query/secondes).
Je réponds ici, en écho à ton commentaire qui laisse penser, à tort, que "pas de multi-thread == pas de multi-clients (viable)". Il est important de préciser que le multi-thread et le multi-client sont deux notions différentes, pas forcément liées. Le choix du multi-threading ne doit pas être automatique, mais adaptée à la situation.
16 avril 2014 à 13:32
Ensuite, comment gère tu les nouveau clients sans thread (et évènement) ? si tes clients connecté ne peuvent rien faire car on attend une nouvelle connexion c'est pas top, trop procédural ... bon après si tu veux en parler il vaut mieux un post ou mp histoire de pas trop pourrir celui ci ^^
16 avril 2014 à 12:29
5 avril 2014 à 09:12
Merci pour le commentaire.
Modifié par nagashima le 4/04/2014 à 13:34
Je n'ai pas testé ton code, je pense qu'il fonctionne, mais il serai plus intéressant d'utiliser les thread pour avoir plusieurs clients (ce qui permettra de mettre en place une communication entre les clients, tel qu'un chat ou un échange de fichier, par exemple).
bon dev.
naga