Journal Grumpy : un nouveau concurrent à pythran

Posté par  . Licence CC By‑SA.
Étiquettes :
16
12
jan.
2017

Salut 'nal !

Il y a des gars chez google qui trouvent que python est trop mou au lieu d'utiliser l'une des dizaines de façon d'accélérer python, ils ont mis au point un transpiler source à source python vers go. Le principe est assez classique. On compile notre code python en go ensuite, on compile ce code go et on obtiens notre exécutable.

Ce n'est pas sans dommage :

  • grumpy est incompatible avec les modules C
  • grumpy n'est pas capable de faire des exec/eval/compile

Le projet est encore asse jeune et il manque pas mal de choses, notamment une grande partie de la bibliothèque standard et les décorateurs (l'évolution des fonctionnalités peut être suivi ici : https://github.com/google/grumpy/wiki/Missing-Features).

Si ce projet est un projet open source sous licence Apache v2 et dispo sur github (https://github.com/google/grumpy), sa raison d'être principale est d'être utilisé pour l'API de Youtube. Il semble que les gars de youtube n'ont pas envie de passer de python 2.7 à python 3 et préféreraient passer à ça.

  • # logique pour Google

    Posté par  . Évalué à 5.

    Cela leur permet de migrer progressivement de Python vers Go (et ils ne sont pas seuls).

    • [^] # Re: logique pour Google

      Posté par  . Évalué à 4.

      C'est l'idée que j'ai, mais ils ne montrent pas la gueule du code go généré histoire de voir si c'est vraiment lisible ou pas (ou s'il y a conservation des commentaires par exemple).

      Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

      • [^] # Re: logique pour Google

        Posté par  (site web personnel) . Évalué à 10.

        La looooongue discussion sur le sujet sur Hacker News(avec intervention du chef de projet!) te donnera probablement plus d'informations; il y a notamment un lien vers un exemple de code généré

        • [^] # Re: logique pour Google

          Posté par  . Évalué à 4.

          Il donne envie l'extrait de code !

          On perd une partie des avantages du Go, simplicité, typage statique…

          • [^] # Re: logique pour Google

            Posté par  . Évalué à 4.

            Hum, tu t'attendais à quoi ? N'importe quel compilateur va forcément générer du code difficile à lire au final, et c'est normal. :-)

            Oui, la génération de code automatisée rend les programmes imbitables, mais j'ai envie de dire, c'est comme ceux qui se plaignent de XML en disant que c'est pas lisible quand c'est généré par une machine. Ben justement, si, c'est lisible, et ça reste plus lisible que de l'assembleur ou du langage machine. Malgré le côté obscur du code (Go ou XML) généré, ça reste un langage dont on peut comprendre la syntaxe, qui permet de faire des choses de haut niveau, etc. Même principe. Par contre, la seule raison de mater le code est si tu veux optimiser quelque chose ou que le générateur de code a mal fait son boulot (le code est pas correct par exemple).

            Le côté simple/facile à lire de Go c'est pour un humain qui génère du code lui-même. Si tu veux la version simple à lire de ce programme, tu prends la version Python. :-)

            • [^] # Re: logique pour Google

              Posté par  . Évalué à 5.

              Hum, tu t'attendais à quoi ? N'importe quel compilateur va forcément générer du code difficile à lire au final, et c'est normal. :-)

              Ça n'est pas du tout une fatalité. C'est plus une question de soin apporté à ça. Tu as coffeescript qui génère du code js compréhensible par exemple.

              Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

              • [^] # Re: logique pour Google

                Posté par  . Évalué à 4.

                Est-ce que CoffeeScript a une ambition de performance ? (Quelque part, puisqu'on parle d'un langage qui génère du JS, qui tourne le plus souvent sur un navigateur, je suppose que non, ou en tout cas qu'on estime que le code généré a une performance acceptable sans être nécessairement proche d'optimale). De ce que j'en avais vu, CoffeeScript est « à peine » (en exagérant un peu j'avoue) plus haut niveau que JavaScript, ce qui aide aussi je pense.

                Si ton but est de générer du code lisible, alors oui tu vas faire un effort pour la génération de code. Mais dans 90% des cas (et je suis généreux, il faudrait plutôt parler de 99%), tu cherches à générer du code-tout-court, voire à générer du code-qui-va-vite. Autant générer du code qui reprend le nom des variables du programme original n'est pas trop compliqué (au pire, tu t'en sers comme d'un préfixe et tu rajoutes des indices si tu dois générer des formes intermédiaires), autant générer du code qui doit créer de nouvelles variables qui ne sont pas utiles dans le langage de plus haut niveau va généralement impliquer l'utilisation d'une variable « anonyme » avec un bête compteur (parce que tout bêtement ton compilateur n'en sait généralement pas assez au niveau de la sémantique du programme pour donner un nom qui fait sens dans un contexte donné).

                Et enfin, même à la main, lorsqu'on commence à réellement optimiser le code généré (je ne suis pas sûr que ce soit l'objectif de ce projet, mais ça pourrait arriver à terme), alors il est quasiment impossible d'obtenir du code lisible. Ou plus exactement : il est lisible pour qui comprend les optimisations appliquées — et encore.

                PS: oui je chipote et je trolle, mais il est « à peine » vendredi ici. :-)

                • [^] # Re: logique pour Google

                  Posté par  (site web personnel, Mastodon) . Évalué à 4.

                  Quand tu génères du JavaScript, derrière il y a plusieurs implémentations de l'interpréteur (au moins une par navigateur - WebKit en a plusieurs et passe de l'une à l'autre à la volée pour chaque fonction, selon plusieurs critères). Elles sont parfois très différentes. Du coup, le principe est plutôt de laisser le runtime faire l'optimisation.

                  On a un peu la même philosophie quand on génère du bytecode Java: le bytecode standard est pas du tout optimal, en fait il est plutôt éloigné de ce que les machines virtuelles font vraiement. Mais, chaque machine virtuelle vient avec une "surcouche" qui s'occupe de faire l'optimisation qui va bien.

                  Cela a un inconvénient: il faut faire cette phase d'optimisation au runtime alors qu'elle aurait pu être faite une fois pour toute à la compilation. Mais ça a un gros avantage: ton code "objet" (bytecode java ou code js généré) sera optimisé pour la machine virtuelle qui l'exécute, même si elle n'existe pas encore lorsque tu écris le code.

                  Du coup, il n'est pas nécessaire et parfois même contre-productif de "pré-optimiser" le code js. Tu ne sais pas quelle machine virtuelle va l'interpréter, de toutes façons.

                  • [^] # Re: logique pour Google

                    Posté par  . Évalué à 1.

                    Quand tu génères du JavaScript, derrière il y a plusieurs implémentations de l'interpréteur […] Du coup, le principe est plutôt de laisser le runtime faire l'optimisation.

                    Oui, c'est pour ça que je demandais. :-)
                    Dans le cas de CoffeeScript → JavaScript, puisque de toute manière la machine virtuelle et son éventuel moteur JIT vont faire le boulot d'optimisation, celui qui écrit le compilateur peut se permettre de se focaliser sur une génération « propre » de code.

                    Je ne suis pas certain que ce soit vrai pour la génération de code Go.

                    On a un peu la même philosophie quand on génère du bytecode Java: le bytecode standard est pas du tout optimal, en fait il est plutôt éloigné de ce que les machines virtuelles font vraiement

                    J'étais surpris par ça, du coup j'ai fait un peu de recherche. Il semblerait que tu aies raison, mais principalement parce que l'optimiseur JIT aurait trop de mal à optimiser quoi que ce soit si le code avait déjà de grosses optimisations faites à la compilation (parce que sinon, comme la machine à pile implémentée par la JVM est complètement spécifiée, y'aurait aucune raison de ne pas faire des transformations optimisantes statiquement sinon).

                    • [^] # Re: logique pour Google

                      Posté par  (site web personnel, Mastodon) . Évalué à 3.

                      Pour compléter: actuellement, les moteurs d'exécution (que ce soit Javascript ou Java) sont configurés pour être performant sur du code écrit "à la main" (ou par javac avec peu de transformations). Il est donc pertinent, quand on génère du code, de générer quelque chose qui ressemble à du code écrit à la main, et qu'ils savent très bien optimiser. Alors que plus on s'éloigne de ça, plus on se retrouve avec des cas ou l'optimiseur n'arrive pas à comprendre ce qu'on a voulu faire.

                      Cela arrive aussi quelquefois avec les compilateurs C. Il y a des cas connus où une fonction memcpy optimisée à la main (pour faire des alignements mémoire, copier des gros bouts d'un coup, etc), finissait par être moins rapide que du code "naïf" optimisé par le compilateur C.

                      Enfin, je précise qu'il existe des optimiseurs de bytecode java. Je pense par exemple à ProGuard: https://www.guardsquare.com/en/proguard , dont la FAQ donne quelques idées de ce qui n'est normalement pas fait par javac, et laissé au soin du runtime. En plus, ProGuard a la bonne idée d'être sous licence GPL ce qui permet de jeter un œuil dedans.

                • [^] # Re: logique pour Google

                  Posté par  . Évalué à 1.

                  Est-ce que CoffeeScript a une ambition de performance ?

                  J'en sais rien et je m'en fou. La question derrière ma recherche de voir le code généré, c'était de savoir si on est devant un outil qui te génère une fois le code go et la nouvelle référence c'est le go ou si ça reste une étape intermédiaire et tu dois alors mettre en œuvre tout un process pour faire ta conversion vers go. Est-ce que c'est mieux ou pas, j'en sais rien (et je m'en fou), c'est juste un choix.

                  Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                  • [^] # Re: logique pour Google

                    Posté par  . Évalué à 3.

                    Je comprends ton point de vue, mais lorsqu'on met en avant des graphes qui montrent que Grumpy va deux fois plus vite que Cython, alors il me semble assez clair que l'idée est aussi de générer du code qui va vite.

                    Tout ce que je dis, c'est que la lisibilité est rarement compatible avec la performance — c'est pas impossible, mais le temps passé à générer du code lisible, c'est autant de temps pas passé à générer du code performant.

                    • [^] # Re: logique pour Google

                      Posté par  . Évalué à 5.

                      Grumpy ne va pas deux fois plus vite que CPython. Sur un benchmark probablement pourri (vu le nom "fib", on peut supposer que c'est un calcul de la suite de Fibonacci), Grumpy est deux fois plus lent en simple thread que CPython, et ne parvient à devenir plus rapide qu'en utilisant plus de cœurs…

                      Maintenant, il y a sûrement du potentiel pour améliorer les perfs. Ce potentiel se situe au niveau de ce à quoi parvient Cython, par exemple.

                      (note : ne pas confondre CPython - l'implémentation principale de Python, écrite en C - et Cython - un compilateur statique de Python vers C)

                      • [^] # Re: logique pour Google

                        Posté par  . Évalué à 4.

                        Grumpy ne va pas deux fois plus vite que CPython. Sur un benchmark probablement pourri (vu le nom "fib", on peut supposer que c'est un calcul de la suite de Fibonacci),

                        Oui, c'est un benchmark classique pour évaluer l'overhead de création de threads/processus pour une application parallèle. Le code « classique » est le suivant :

                        /* J'utilise OpenMP pour paralléliser parce que je suis paresseux */
                        long fib (long n) {
                            long n1 = 0, n2 = 1;
                            if (n < 2) return n;
                        #   pragma omp task shared(n1) firstprivate(n)
                            n1 = fib(n-1);
                        #   pragma omp task shared(n2) firstprivate(n)
                            n2 = fib(n-2);    
                        #   pragma omp taskwait
                            return n1+n2;
                        }

                        À noter que la performance parallèle de ce code est abominable, et qu'une bonne implémentation séquentielle et impérative ira 100 fois plus vite (littéralement).

                        Mais ce code permet d'évaluer la robustesse du runtime/système quand on crée des tâches de façon exponentielle, car il n'y a pratiquement pas de calcul à effectuer. C'est un benchmark classique dans le domaine de l'évaluation de création de tâches. Cependant, je connais aussi pas mal de gens qui n'aiment pas ce benchmark, car il n'est pas forcément représentatif de vrais workloads utilisés pour des applications parallèles, et fait l'impasse sur certaines optimisations qui existent dans les environnement d'exécution qui proposent un système de création de threads/tâches et qui tirent parti de tout un tas d'aspects architecturaux.

                        Mais là n'était pas mon propos. Je n'ai pas analysé la pertinence de ce benchmark dans mon post précédent. Juste que, lorsqu'on publie un graphique pareil, généralement ce n'est pas anodin, et qu'on estime que ça va permettre d'avoir des performances pas obtenues par ailleurs.

                        Grumpy est deux fois plus lent en simple thread que CPython, et ne parvient à devenir plus rapide qu'en utilisant plus de cœurs…

                        C'est relativement classique dans l'implémentation de runtimes pour favoriser les threads : l'avantage ne commence à se voir que lorsqu'on les exécute sur de grands nombres de processeurs/threads matériels.

                        (note : ne pas confondre CPython - l'implémentation principale de Python, écrite en C - et Cython - un compilateur statique de Python vers C)

                        Oups ! Oui tu as complètement raison, j'ai lu vite et mon cerveau a (mal) interpolé.

                        • [^] # Re: logique pour Google

                          Posté par  . Évalué à 2.

                          Le code « classique » est le suivant :

                          Je ne suis pas sûr du tout que ce soit ce qui est mesuré ici. Il n'y a pas de support OpenMP dans Python, ni (probablement) dans Go. Le benchmark ici est probablement beaucoup plus simple : on fait tourner fib(N) sur un certain nombre de threads à la fois, et on graphe le nombre d'exécutions par seconde en fonction du nombre de threads.

                          Surtout qu'en pratique, sur du code serveur, on se fiche pas mal de l'overhead de création de threads ou de processus, parce qu'on crée un pool de threads statique au début de l'application…

              • [^] # Re: logique pour Google

                Posté par  . Évalué à 3.

                Ça n'est pas du tout une fatalité. C'est plus une question de soin apporté à ça. Tu as coffeescript qui génère du code js compréhensible par exemple.

                Tu compares des choses qui n'ont strictement rien à voir. CoffeeScript est un langage qui a été conçu pour générer du code Javascript en sortie, avec donc une sémantique très proche. Là on parle de transformer du Python en Go tout en gardant la sémantique de Python, alors que celle de Go n'a rien à voir…

                En fait le résultat est parfaitement prévisible, car c'est le même genre de code que génère Cython, par exemple (sauf que Cython génère du C là où Grumpy génère du Go).

        • [^] # Re: logique pour Google

          Posté par  . Évalué à 1.

          il y a notamment un lien vers un exemple de code généré

          Tiens, première fois que je vois une erreur HTTP 451 implémentée dans la vie réelle

          HTTP/2.0 451 No Reason Phrase
          
      • [^] # Re: logique pour Google

        Posté par  . Évalué à 0.

        Conserver les commentaires, ça peut être folklo, quand même. Si ton commentaire explique une pythonnerie, il risque d'être plus perturbant qu'autre chose en go…

        • [^] # Re: logique pour Google

          Posté par  . Évalué à 5.

          Qu'importe. Perdre l'ensemble des commentaires pour une hypothèse que celui-ci puisse possiblement inclure une pythonnerie n'est pas acceptables.

          Ca ressemble fortement à une excuse :-)

          Ainsi donc, Python est déclaré obsolète parce que go existe ? il va falloir que je regarde ce truc.

          • [^] # Re: logique pour Google

            Posté par  . Évalué à 5.

            Ainsi donc, Python est déclaré obsolète parce que go existe ? il va falloir que je regarde ce truc.

            De ce qu'ils disent python 2.7 sera déprécié dans 3 ans, ils anticipent et préfèrent partir sur go que sur python3 (si ça leur fait plaisir).

            Les choix de changements de langages c'est toujours assez complexe, comme Mozilla avec rust dans firefox.

            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

      • [^] # Re: logique pour Google

        Posté par  (site web personnel) . Évalué à 6.

        ils ne montrent pas la gueule du code go généré histoire de voir si c'est vraiment lisible ou pas (ou s'il y a conservation des commentaires par exemple).

        Leur objectif n'est pas de faire du code lisible ni avec du commentaire, c'est le code Python qui est la référence et qui le demeurera. C'est comme demander si l'assembleur généré par le compilateur C est vraiment lisible ou avec conservation de commentaires. La maintenance applicative se fait et continuera de se faire en Python. (Source : l'auteur du projet sur Hackernews.)

        • [^] # Re: logique pour Google

          Posté par  (site web personnel, Mastodon) . Évalué à 10.

          gcc arrive très bien à conserver les commentaires C (et même, ajouter les lignes du fichier C en commentaire) dans les fichiers assembleur qu'il génère. D'ailleurs, c'est indispensable qu'il sache faire ça car c'est aussi utilisé pour générer les informations de debug, qui permettent à un debugger de savoir quelle ligne du fichier C est en train de s'exécuter.

          Encore plus fort: quand on génère du C, on peut ajouter des directives #line et #file, et du coup, annoter que le fichier est généré à partir d'un autre. Et cela sera aussi intégré et le debugger pourra afficher où on est dans le fichier source qui a servi à la génération.

          Si Grumpy (et les autres transpileurs ) ne sait pas faire ça, alors comment on fait pour debugger? Obligé de regarder le code généré qui n'a pas de commentaires, et retrouver l'équivalent dans le fichier Python à la main? ça me semble être la moindre des choses, quand même?

  • # Concurent de Nuitka plutôt non ?

    Posté par  (site web personnel) . Évalué à 7.

    Quand je lis la doc du projet, je ne vois aucune mention de typage statique, ça me fait plutôt penser à l'approche de Nuitka qui transforme n'importe quel code Python en programme C++ qui appelle le runtime CPython. Là ils ont ré-implem le runtime CPython il me semble, mais l'idée est la même.

    D'une certaine façon, ça ressemble aussi à Pyston avec le JIT en moins.

    Assez loin de Pythran finalement, puisqu'ils visent une approche générique, pas un embeded Domain Specifc Language, un langage spécialisé pour le calcul scientifique embarqué dans Python.

    Sinon le fait de se concentrer sur Python2.7 (même choix que Pyston !) est discutable. On a mis plusieurs mois à supporter Python3 dans Pythran après avoir fait ce choix, je les plains :-)

    • [^] # Re: Concurent de Nuitka plutôt non ?

      Posté par  (site web personnel) . Évalué à 1.

      Un aspect secondaire, si j'ai bien compris, est de pouvoir mixer du code Go et Python: par exemple, ils peuvent utiliser le serveur HTTP de la bibliothèque standard. Cela leur permet probablement de tirer parti des goroutines (green threads) de Go, et donc de monter en charge plus facilement qu'avec un thread OS par connexion si c'est le paradigme qu'ils utilisaient auparavant (oui, il existe des alternatives en python natives pour faire des serveurs event based). Avec les progrès récents du garbage collector dans Go 1.8 (pauses "stop the world" diminuées à l'échelle de la dizaine de microsecondes), j'imagine ça leur fournit une bonne base pour un système qui doit très probablement être IO bound.

  • # marche pas chez moi

    Posté par  . Évalué à 2.

    ça ne fonctionne pas chez moi :

    echo "print 'hello, world'" | make run
    build/src/grumpy/lib/linecache/module.go:4: can't find import: "grumpy/lib/os"
    Makefile:201 : la recette pour la cible « build/pkg/linux_amd64/grumpy/lib/linecache.a » a échouée
    make: *** [build/pkg/linux_amd64/grumpy/lib/linecache.a] Erreur 1

    et le readme ne donne pas vraiment les bases d'installation, d'après eux ça fonctionne "out of the box" depuis le dossier de grumpy. (mon python par défaut c'est le 2.7.12, linux mint 18)

    « Le pouvoir des Tripodes dépendait de la résignation des hommes à l'esclavage. » -- John Christopher

    • [^] # Re: marche pas chez moi

      Posté par  . Évalué à 2.

      depuis un autre PC (Python 2.7.6 et go1.6), cela fonctionne, peut-être un truc cassé dans mon installation de python…

      « Le pouvoir des Tripodes dépendait de la résignation des hommes à l'esclavage. » -- John Christopher

  • # Du Python au goroutines

    Posté par  . Évalué à 1.

    Je me demande bien quel bout de code en Python peut bien être transformé en goroutine Go. Et s'ils veulent viser du Go, c'est en partie pour ses mécanismes de ce genre je suppose, non ?

    • [^] # Re: Du Python au goroutines

      Posté par  (site web personnel, Mastodon) . Évalué à 4.

      Si j'ai bien compris, le but c'est:

      1) Faire tourner l'application existante en la convertissant en Go
      2) Commencer à réécrire certains morceaux en Go pour migrer petit à petit
      3) à la fin, tout le code est réécrit en Go.

      • [^] # Re: Du Python au goroutines

        Posté par  . Évalué à 2.

        D'accord, je comprends donc mieux. Ce n'est donc pas une fin en soi d'avoir un transpileur Python à Go, mais c'est vraiment un outil pour assister la migration.

  • # L'annonce

    Posté par  . Évalué à 3.

    • [^] # Re: L'annonce

      Posté par  . Évalué à 7.

      Oui, là c'est un peu facile.

      On sait tous qu'il ne faut pas faire du multi-thread en python/CPython et du coup on fait du multi-process qui est très proche en terme d'api, et là on a (en fonction des cas bien sur …) la mise à l'échelle en fonction du nombre de cœur.

      Du coup cela ne fait qu'un rapport deux … pas sur que cela vaille la peine de quitter python pour un rapport deux … et cela sans pythran/cython et consort.

      On fait bien dire ce que l'on veut à un graph ..

      • [^] # Re: L'annonce

        Posté par  . Évalué à 3.

        Je trouve qu'il est plutôt clair et pas "un peu facile", on voit bien que c'est pénalisant en mono-tache et que ça commence à être bénéfique qu'en multi-tache donc dans des cas bien spécifiques.

        Je constate d'ailleurs la même chose en programmant en Go directement, par rapport au Python le gain en vitesse n'est pas toujours évident car en Python on accède bien souvent à du C même sans le savoir. Du parsing json par exemple. Du coup si on veut gagner en perf il faut utiliser les goroutines, c'est assez facile mais pas non plus toujours miraculeux car il faut tout de suite penser aux multiples verrous. En même temps, à utiliser tous les procs on a vite fait de plomber la machine… Donc tout ça est à prendre avec des pincettes !

        • [^] # Re: L'annonce

          Posté par  (site web personnel, Mastodon) . Évalué à 2.

          Parfois il vaut mieux une bibliothèque Python bien optimisée, plutôt qu'un code C écrit à la main. Un exemple qui me revient: https://www.tablix.org/~avian/blog/archives/2016/04/measuring_interrupt_response_times/
          (et dans lequel, finalement, il vaut mieux un driver dans le noyau, mais c'est une autre histoire).

        • [^] # Re: L'annonce

          Posté par  . Évalué à 2.

          Je pense que je n'ai pas dû être clair. Le graph montre que le programme transcrit en go va commencer à être plus rapide si on augmente le nombre de cœur et que du coup c'est bien meilleur en go.

          Le point est que les gens qui veulent des perfs en python (ce qui est bien l'objet d'un compilateur) ne vont jamais le faire en thread en python à cause du GIL. On va plutôt utiliser l'api multiprocess qui elle n'a pas ce souci. Donc comparer un Code écrit en python avec des threads avec un code d'un autre langage avec des threads révèle bien un défaut de l'implémentation de l'interpreteur C mais pas un blocage pour qui voudrait améliorer les choses car il faut suffit d'utiliser le multiprocess.

          Bon dans la vrai vie, ce n'est pas aussi simple. Si le multiprocess sous linux est aussi simple à utiliser que le multithread en python, ce n'est pas vrai en windows car il n'y a pas de mécanisme de fork donc tous les paramétrages des objets sont perdus, on a un interpreteur vierge (spawn). Cela nous a valu bien des problèmes dans le portage de nos codes de linux vers multiplateforme !

          La méthode par défaut dans python3 devrait être spawn ce qui rendra plus facile le multi plateforme mais demandera plus de réflexion dans l'architecture du programme …

          Bon après il reste la possibilité de rester en threads, chercher les goulots d'étranglements et de les compiler les bouts de codes avec plein de boucles et conditions avec les différents outils qui existent …

          • [^] # Re: L'annonce

            Posté par  . Évalué à 3.

            Quelques remarques :

            1. L'article explique que leur traduction Python → Go n'utilise pas de GIL. Ça signifie qu'ils peuvent utiliser de vrais threads et pas de processus. D'un point de vue performance, c'est quelque chose d'extrêmement important, mais en fait je pense que c'est encore plus important d'un point de vue empreinte mémoire : lorsque tu crées de nouveaux processus, tu dupliques tout l'espace mémoire associé (y compris un interpréteur, par exemple…); quand tu crées des threads, l'empreinte mémoire est bien moindre, ce qui a plusieurs implications en termes de nombre de tâches concurrentes que tu peux exécuter à la fois, mais aussi lorsque le système effectue des changements de contexte, les caches sont moins mis à contribution (moins de cache thrashing) ce qui permet d'obtenir une meilleure performance.
            2. Ils disent eux-même que la capacité à utiliser des threads est directement le résultat d'une décision de conception : interdiction d'utiliser les modules écrits en C et exécutés depuis Python. Ils se coupent donc d'une partie de l'écosystème Python pour pouvoir obtenir de bonnes performances depuis Python « pur » (mais bon, en échange, ils peuvent importer les bibliothèques Go, donc ça s'équilibre).

            Sinon, concernant ton explication que Windows n'a pas d'appel à fork : c'est vrai, il n'y a pas de fork POSIX (quoique, c'est plus tout à fait vrai depuis un petit moment, vu qu'il existe une implémentation d'une partie de l'API POSIX en Windows « natif » pour Win10 depuis quelques mois déjà). Mais tu penses bien qu'ils ont un moyen de dupliquer l'espace mémoire d'un processus s'il le faut. :-) C'est juste que l'API est plus complexe. Voir ici par exemple.

            • [^] # Re: L'annonce

              Posté par  . Évalué à 5.

              Pour le point 1 pas vraiment, il y a du COW sur les pages mémoires. Entre les 2 ce qui va faire la différence c'est le temps de création d'un thread et la vitesse des échanges entre les threads àmha.

              Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

              • [^] # Re: L'annonce

                Posté par  . Évalué à 2.

                Complètement d'accord pour dire que COW (et d'autres techniques de recyclage de pages mémoire aussi) permet de réduire une partie du problème. Après tout dépend de la nature de l'application. Si tes processus sont censés partager des données, du point de vue du modèle d'exécution, à moins de passer par des segments de mémoire partagée ou équivalent, tu vas devoir passer par des IPC de type passage de message, socket, ou pipe. À ce moment-là, COW permettra de réduire l'impact de la duplication des données et de l'allocation mémoire (il y a même de bonnes chances pour qu'au moins la partie purement « lecture seule » soit correctement unique à tous les processus dupliqués).

                Cependant, par exemple dans des processus parallèles (je pense notamment à des trucs genre calcul utilisant MPI), il y a souvent des échanges de données (par exemple dans des algos itératifs qui se basent sur des représentations à base de graphes, il faut échanger les « cellules fantôme » (ghost cells) ), et en fonction du nombre, ça peut mener à de grosses sur-consommation mémoire si on passe par des processus plutôt que des threads (j'ai des exemples de collègues qui à l'époque avaient réussi à réduire l'empreinte mémoire de plusieurs giga-octets en utilisant une implémentation de MPI maison basée sur les threads plutôt que les processus).

                Ensuite, je suis complètement d'accord pour dire que les exemples que je peux donner sont relativement marginaux, car ils s'inscrivent dans le cadre d'applications hautement parallèles avec un grand besoin en performance.

                • [^] # Re: L'annonce

                  Posté par  . Évalué à 3.

                  Ensuite, je suis complètement d'accord pour dire que les exemples que je peux donner sont relativement marginaux, car ils s'inscrivent dans le cadre d'applications hautement parallèles avec un grand besoin en performance.

                  Plus que ça, là on parle du frontend de youtube. Le modèle d'exécution est assez précis : on réagis à des requêtes HTTP et on interagis avec différents sous-système (authentification, base/serveur de données,…). Le meilleur modèle pour faire ça c'est d'avoir une boucle d’événements qui fait appel au contrôleur de manière asynchrone. C'est ce que fait twist si je ne me trompe pas (c'est ce qu'on trouve avec node, avec POE, je crois que c'est ce que fais nginx, tous les javaries qui se basent sur netty (play2 par exemple)). Et le reste de youtube c'est surtout de la répartition de tâche pour encoder les vidéos (et si je ne m'abuse c'est go qui fait la répartition de charge).

                  Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

            • [^] # Re: L'annonce

              Posté par  . Évalué à 2.

              Sinon, concernant ton explication que Windows n'a pas d'appel à fork : c'est vrai, il n'y a pas de fork POSIX (quoique, c'est plus tout à fait vrai depuis un petit moment, vu qu'il existe une implémentation d'une partie de l'API POSIX en Windows « natif » pour Win10 depuis quelques mois déjà). Mais tu penses bien qu'ils ont un moyen de dupliquer l'espace mémoire d'un processus s'il le faut. :-) C'est juste que l'API est plus complexe. Voir ici par exemple.

              Bof … ça sent plus le troll qu'autre chose. Les solutions qui sont de passer par cygwin, l'api posix de windows me semblent tout sauf simple. Déjà passer par cygwin pour python nécessite de tout installer dans cet environnement, qui est indépendant du reste de windows. Cela fait une couche logicielle importante. En ce qui concerne les couches posix, il semblerait que ce soit avec interix ou wsl c'est tout sauf simple à faire cohabiter. Donc perso, je pense qu'il vaut mieux coder cross-plateform dès le début que de passer par des mécanismes qui vont te demander un investissement important à chaque fois qu'ils vont les faire évoluer …

              Après concernant Process VS Threads, tu es bien plus pertinent que moi pour pouvoir en juger. Mais je trouve que les outils comme MesgPack, ZMQ, et ZeroRPC, permettent d'étendre la mise en œuvre des process. Par exemple chez nous on envisage d'avoir des services qui tournent sur des PC dédiés et que l'on appelle dans python sur d'autres PC grâce à ZeroRPC. Cela n'est pas si compliqué à faire lorsque l'on s'est mis dans les contraintes du multi-process, c'est bien plus difficile si l'on part du multi-thread (enfin je pense, on ne l'a pas encore fait …).

              Si je suis d'accord avec toi sur l'aspect coût en mémoire, en fait dans mon cas d'utilisation, cela ne va pas changer grand chose de mettre en mémoire les 8 interpréteurs, sur ma machine. C'est sur que s'il faut dupliquer les flux de données important pour émuler la mémoire partagé, cela perd vraiment de l'intérêt. Mais généralement quand tu en es là, tu peux tout à fait partir sur un module cython et relacher le GIL, cela me semble bien moins compliqué que de passer toute sa base de code de python vers Go.

              C'est plutôt un acte politique, ils ont développé un langage haut niveau performant et bien plus simple à maîtriser que le C++, ils veulent donc le promouvoir, ce qui est bien. C'est juste que je trouve la tentative de justification avec python, un peu limite. C'est bien de respecter le travail de ses développeurs et de leur faire confiance, pour moi c'est une raison suffisante.

              • [^] # Re: L'annonce

                Posté par  . Évalué à 5.

                Bof … ça sent plus le troll qu'autre chose. Les solutions qui sont de passer par cygwin, l'api posix de windows me semblent tout sauf simple. […]

                Relis mieux le lien que j'ai posté : on parle de l'implémentation de Cygwin parce qu'il s'agit d'une des implémentations notables qui reproduit une API POSIX, et en particulier fork. Mais le post explique qu'une partie de la lenteur du fork de Cygwin vient du fait qu'ils utilisaient certains appels systèmes purement pour des raisons de compatibilité avec des OS datant du siècle dernier.

                Ensuite, il existait SFU (Services For UNIX) mais qui, à ma connaissance étaient plutôt mal vus par ses utilisateurs (souvent issus du monde Linux/UNIX) car pas forcément performants ou stables (mais qui fournissait une API POSIX: Windows NT implémente une partie de l'API POSIX depuis un moment, et SFU était une bibliothèque écrite par MS qui essayait de compléter ce qui manquait). La solution de MS a été d'introduire SUA, un ensemble d'outils en ligne de commande que MS a directement porté depuis leur source UNIX, et qui utilise l'API standard de Windows (notamment : on peut utiliser Perl, les outils de ligne de commande classique GNU, etc., en ligne de commande).

                Donc non, il ne s'agit pas d'un troll. Il existe bel et bien des méthodes pour ré-implémenter les appels POSIX manquants, mais comme il s'agit d'un OS différent, alors il y a un coût à cela—en particulier, la « vieille » méthode qu'utilisait Cygwin pendant longtemps pour effectuer un fork impliquait d'allouer de nouvelles pages mémoires pour effectuer des copies explicites du processus parent, ce qui avait pour conséquence de ne pas profiter du COW (dont parle barmic dans sa réponse à mon commentaire).

                [processus vs. threads] Par exemple chez nous on envisage d'avoir des services qui tournent sur des PC dédiés et que l'on appelle dans python sur d'autres PC grâce à ZeroRPC. Cela n'est pas si compliqué à faire lorsque l'on s'est mis dans les contraintes du multi-process, c'est bien plus difficile si l'on part du multi-thread (enfin je pense, on ne l'a pas encore fait …).

                En règle générale, lorsqu'on conçoit un logiciel pour être multithreadé, il faut s'imposer des contraintes dès le départ, notamment sur les API qu'on développe. Dès le début on essaie d'expliquer aux nouveaux étudiants en programmation que les variables globales sont à éviter, mais c'est généralement pour des raisons liées au génie logiciel. Dans le cas de programmes multithreadés, c'est aussi une contrainte liée aux risques de conflits d'accès concurrent aux variables, qui peut engendrer des plantages (meilleur cas), comportements imprévisibles (cas déjà beaucoup plus gênant), ou même se comporter « normalement » et sembler calculer tout correctement, sauf que l'accès concurrent (non protégé) mène ensuite à un calcul faux qui n'est pas détecté tout de suite (pire cas : rien ne permet de savoir que quelque chose ne va pas car les jeux de tests ne sont pas assez poussés pour le détecter).

                Donc oui, utiliser un système multi-processus est plus « facile » à implémenter car tu bénéficies de l'isolation de l'espace mémoire entre les processus. En termes de performance, tout dépend vraiment de comment tu utilises ta machine. Quand on sait que ~70% des programmes lancés sur les nœuds de calcul de supercalculateurs sont mono-processus, mono-thread (et que donc ils n'utilisent pas 90% de la machine en termes de puissance de calcul), avoir une vraie conception multi-processus est déjà mieux que la moyenne, et de loin. :-)

                s'il faut dupliquer les flux de données important pour émuler la mémoire partagé, cela perd vraiment de l'intérêt. Mais généralement quand tu en es là, tu peux tout à fait partir sur un module cython et relacher le GIL, cela me semble bien moins compliqué que de passer toute sa base de code de python vers Go.

                Ben pas forcément : dans leur cas, ils n'utilisent plus de modules écrits en C et qui utilisent l'interface Python adéquate, car ils ne peuvent pas gérer les ressources utilisées, mais en retour, ils génèrent du code Go directement en gardant le source Python, ce qui permet aux programmeurs de maintenir un programme avec un langage de haut niveau malgré tout plus simple à utiliser que Go directement. Tout dépend de l'objectif du projet donc. :-) Et surtout, s'ils ont déjà tout un tas de bibliothèques déjà écrites pour Go et qui satisfont leurs besoins, alors l'intérêt des modules C devient « mécaniquement » moins grand.

                • [^] # Re: L'annonce

                  Posté par  . Évalué à 0.

                  Oui les méthodes pour ré-implémenter les appels POSIX ou les émuler existent mais la question est est-ce qu'un langage comme python devrait se baser là dessus ? Je pense qu'ils ont bien fait de ne pas permettre le fork et obliger le spawn sous windows. Dans la version 3 le spawn sera le choix par défaut ! Cela va faire tomber beaucoup de code !

                  C'est sûr que si il y avait une implémentation native kernel windows du fork, ça serait plutôt cool.

                  Donc oui, utiliser un système multi-processus est plus « facile » à implémenter car tu bénéficies de l'isolation de l'espace mémoire entre les processus. En termes de performance, tout dépend vraiment de comment tu utilises ta machine. Quand on sait que ~70% des programmes lancés sur les nœuds de calcul de supercalculateurs sont mono-processus, mono-thread (et que donc ils n'utilisent pas 90% de la machine en termes de puissance de calcul), avoir une vraie conception multi-processus est déjà mieux que la moyenne, et de loin. :-)

                  Oui, ça aussi ça peut être vu comme un troll ! Il existe plein de domaines ou tu peux lancer des tâches indépendantes mais tu as besoin d'en lancer plein, dans ce cas un script bien fait pour lancer un job PBS et c'est parfaitement adapté !

                  • [^] # Re: L'annonce

                    Posté par  . Évalué à 3.

                    C'est sûr que si il y avait une implémentation native kernel windows du fork, ça serait plutôt cool.

                    Ils l'ont pas déjà implémenter pour le sous-système unix (le truc qui permet de lancer bash et des ELF) ?

                    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                    • [^] # Re: L'annonce

                      Posté par  . Évalué à 1.

                      oui mais je ne sais pas à quel point c'est intégré à windows, peux tu appeler ce fork depuis un programme fait sous windows ?
                      Je ne sais pas si il y a un API associé à ce sous-système et comment elle s'intègre dans le système. Mais bon c'est juste que je ne suis pas su tout compétent sur ce sujet. Je ne suis donc pas certain que cela résolve le problème de compatibilité python pour les forks !

                  • [^] # Re: L'annonce

                    Posté par  . Évalué à 2.

                    Oui les méthodes pour ré-implémenter les appels POSIX ou les émuler existent mais la question est est-ce qu'un langage comme python devrait se baser là dessus ?

                    Je ne vois pas où est le problème. Tout dépend de tes attentes en termes d'overhead. Si tu considères que l'overhead des solutions existantes pour reproduire la fonctionnalité de fork est trop grand, alors non, bien entendu, il ne faut pas. Mais si tu considères que c'est un coût acceptable, alors oui, complètement. C'est comme l'optimisation de code : d'abord tu écris un code qui fonctionne (en pensant un minimum en amont à des solutions optimisables sans tout récrire) et ensuite tu optimises.

                    Pour finir sur ce sujet : l'utilisation de fork doit être vue plus comme une façon de permettre une premier port de l'interpréteur sous Windows, pas comme une façon d'avoir le truc le plus efficace. Par exemple, si tu voulais porter Python sous un OS comme VMS, tu serais bien embêté, car il n'y a pas de fork non plus, et l'appel système de création de processus ressemble plus à ce que l'ont trouve sous Windows NT / Win32 API que sous UNIX/Linux (ce qui n'est pas très étonnant, quand on considère qu'une partie des gens qui ont codé le noyau original de NT, et donc spécifié son API ont aussi bossé sur VMS).

                    Oui, ça aussi ça peut être vu comme un troll ! Il existe plein de domaines ou tu peux lancer des tâches indépendantes mais tu as besoin d'en lancer plein, dans ce cas un script bien fait pour lancer un job PBS et c'est parfaitement adapté !

                    Ben la formulation est peut-être trollifère, mais les stats, elles, sont là. Les sysadmin de plein de centres de calcul ont tout bêtement regardé la charge de leurs clusters, et réalisé que si les programmes en eux-mêmes peuvent être gourmands en mémoire, ils ne sont en grande majorité pas parallélisés du tout. On ne parle pas de lancer 4 programmes en parallèle via un script (et même là, tu n'utilises qu'un quart de ta machine au mieux pour des nœuds de calcul récents).

                    Je ne dis donc pas qu'il n'y a pas des domaines où lancer plusieurs programmes n'est pas logique, juste que c'est ultra-rare en moyenne sur les clusters/supercalculateurs.

                    Je te parle d'utiliser un programme mono-processus, mono-thread, et rien d'autre. Il y a peut-être des cas de programmes parallélisés avec MPI mais qui ne font que des communications nœud à nœud et ne cherchent pas à paralléliser dans le nœud (je ne vois pas pourquoi, mais admettons). Ça ne changerait rien au fait que ces processus ne tirent absolument pas partie du parallélisme disponible au niveau du nœud lui-même. Et comme la plupart des jobs soumis dans des calculateurs demandent généralement d'avoir un accès exclusif au nœud de calcul…

                    • [^] # Re: L'annonce

                      Posté par  . Évalué à 3.

                      Avant même de parler de performances, le premier problème est de savoir si cette émulation de fork sous Windows a bien la même sémantique que sous Unix (par exemple sur le comportement des descripteurs de fichiers hérités). Franchement, vu comme fork sous Unix peut mener à des problèmes subtils, j'hésiterais très fort à tenter d'utiliser une émulation officieuse sous Windows, c'est-à-dire un système qui n'a rien à voir.

                      • [^] # Re: L'annonce

                        Posté par  (site web personnel, Mastodon) . Évalué à 2.

                        Et entre différentes implémentations de Unix (à part celle de Microsoft dans Windows), ça marche bien?

                      • [^] # Re: L'annonce

                        Posté par  . Évalué à 2.

                        Ben l'appel CreateProcess sous Windows permet l'héritage/la filiation entre processus non ?

                        Ensuite, c'était un peu le propos de mon post : en supposant que l'API de fork est bien respectée (ie, duplication de l'espace mémoire d'un processus, et création d'une hiérarchie de processus entre le père qui récupère le pid du fils, et le fils, qui récupère 0 comme valeur — ou -1 s'il y a erreur), alors porter Python sous Windows devrait être plus facile dans un premier temps car les appels POSIX sont supportés.

                        Ensuite, évidemment, il serait mieux de pouvoir utiliser les appels natifs, mais c'est une autre histoire…

                    • [^] # Re: L'annonce

                      Posté par  . Évalué à 3.

                      Pour ton second point je crois que Redis est monothread (et mono process). Je me demande si c'est pas le cas de node aussi (avec une bidouille pour pouvoir lancer n instances sur le même port).

                      Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                      • [^] # Re: L'annonce

                        Posté par  . Évalué à 2.

                        Je ne connais pas du tout le système du coup je ne peux pas commenter. Mais ça m'étonnerait que le serveur web sur lequel reddit repose soit mono-process ou mono-thread. Donc peut-être que le backend est mono-* mais entre les possibles caches de données, les sessions en parallèle, etc., je pense qu'il est raisonnable de penser que y'a quand même du parallélisme quelque part. :-)

                        • [^] # Re: L'annonce

                          Posté par  . Évalué à 3.

                          les sessions en parallèle

                          Concurrentes, pas parallèle ;)

                          Du coup j'ai vérifié et c'est bien le cas : https://nodejs.org/en/about/
                          Tu peu éventuellement lancer plusieurs threads pour en avoir autant que de CPU mais pas plus.

                          Comme je le disais plus haut, toutes les techno orienté serveur qui consomme des requêtes et qui ont fait parler d'elles ces dernières années réduisent fortement le parallélisme. L'idée c'est que tu ne peux pas faire plus de 4/8/16 choses en parallèles sur une machine selon la CPU. L'idée derrière ça c'est de faire de l'asynchrone plutôt que du vrai parallélisme. Il y a moins de deadlock et on passe moins de temps à faire des changements de contexte.

                          Tu as ce genre de bench pour le voir : http://blog.octo.com/jusquou-peut-aller-un-simple-ordinateur-de-bureau-avec-une-application-web-java-reactive/

                          Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                          • [^] # Re: L'annonce

                            Posté par  . Évalué à 4.

                            les sessions en parallèle

                            Concurrentes, pas parallèle ;)

                            Alors, j'avais bien précisé « parallèle » parce que si ce n'est « que » concurrent, ben du coup ça veut dire que deux processus ou threads peuvent se partager un cœur ou thread matériel et du coup tu n'exploites toujours pas ta machine (voire, au contraire, tu la rend plus lente, car il y a du coup des changements de contexte, des évictions de lignes de cache, etc.). :-)

                            Ce qui m'intéresse c'est qu'une application exploite la machine au mieux, donc la concurrence c'est bien si tu surcharges la machine de threads (c'est pas forcément une mauvaise idée s'il y a beaucoup d'entrées-sorties), mais si y'a des cœurs dispo, on obtient une machine sous-utilisée.

                            [à propos de node.js] Tu peu éventuellement lancer plusieurs threads pour en avoir autant que de CPU mais pas plus.

                            Donc on a bien un comportement parallèle ! VICTORY !
                            … Ahem.

                            L'idée c'est que tu ne peux pas faire plus de 4/8/16 choses en parallèles sur une machine selon la CPU. L'idée derrière ça c'est de faire de l'asynchrone plutôt que du vrai parallélisme. Il y a moins de deadlock et on passe moins de temps à faire des changements de contexte.

                            c'est quelque chose de « classique » en HPC : on module le parallélisme en fonction des ressources matérielles disponibles. Ça inclut le nombre d'unités de calcul (threads matériels, cœurs, etc.), mais aussi la bande-passante pour accéder à la mémoire vive, voire la bande-passante pour accéder à la mémoire de masse si le programme produit ou consomme beaucoup de données.

                            Bon après dans le cas spécifique du calcul intensif/parallèle, on a aussi des connexions réseau ultra-rapide et spécialisées qui ne nécessitent pas l'utilisation de TCP/IP, ce qui fait que la transmission de données est généralement pas spécialement plus lente qu'accéder à la RAM (voire moins, ça dépend de ce que t'es prêt à payer).

                            Pour l'histoire de deadlocks je suis un peu circonspect. C'est un fait que plus tu augmentes la concurrence d'un programme plus les problèmes de race condition/data race, ainsi que les problèmes d'accès aux verrous apparaissent vite. Mais réduire le nombre de processus ou threads ne fait que limiter le potentiel pour un deadlock, et ne supprime absolument pas le problème en lui-même : si t'as un deadlock, c'est que y'a un bug quelque part ! :-)

                            Bon et sinon, viser l'asynchronie, je suis à fond pour… même pour les threads. Plutôt qu'avoir des gros threads qui tournent et doivent explicitement acquérir 12000 verrous pour modifier l'état du système, je préfère des petits threads qui ne peuvent tourner que si toutes leurs dépendances (notamment en termes de données, mais aussi de ressources) sont satisfaites. Par contre en échange, le thread fait une (« petite ») chose, la fait bien, et ne peut plus être interrompu n'importe comment (donc il faut faire attention à comment on les utilise, sous peine de verrouiller toute la machine).

                            • [^] # Re: L'annonce

                              Posté par  . Évalué à 2. Dernière modification le 19 janvier 2017 à 09:20.

                              Alors, j'avais bien précisé « parallèle » parce que si ce n'est « que » concurrent, ben du coup ça veut dire que deux processus ou threads peuvent se partager un cœur ou thread matériel et du coup tu n'exploites toujours pas ta machine (voire, au contraire, tu la rend plus lente, car il y a du coup des changements de contexte, des évictions de lignes de cache, etc.). :-)

                              Parallèle ça veut dure 4, 8 ou 16. Reddit c'est combien de connexion à la minute ? Tu ne peux pas t'en sortir avec du parallélisme avec des serveurs classiques (→ si tu ne fait pas du HPC ou du serverless).

                              Ce qui m'intéresse c'est qu'une application exploite la machine au mieux, donc la concurrence c'est bien si tu surcharges la machine de threads (c'est pas forcément une mauvaise idée s'il y a beaucoup d'entrées-sorties), mais si y'a des cœurs dispo, on obtient une machine sous-utilisée.

                              Hors HPC et serverless, le CPU est la ressource la plus rare de l'OS. Plus que la mémoire, plus que la bande passante réseau ou disque. Même si tu te débrouille pour en avoir 32 ce sera toujours extrêmement rare.

                              c'est quelque chose de « classique » en HPC

                              Donc pas sur reddit, pas sur nodejs, pas sur des applications dont le boulot c'est de répondre à des requêtes utilisateurs.

                              Pour l'histoire de deadlocks je suis un peu circonspect.

                              C'est parce que je suis aller un peu vite et que du coup je me suis trompé de mot. Ça réduit l'impact des verrous.

                              Si Reddit se permet de faire du js, c'est qu'ils ne sont pas CPU bound, qu'ils ne font pas du calcul intensif.

                              Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

        • [^] # Re: L'annonce

          Posté par  . Évalué à 2.

          Il faut voir ça au niveau global. Quand tu es un serveur il faut voir comment tu traite tes requêtes (un thread/process par connexion ? une boucle d’événements asynchrone ?…) ça a des impacts sur la manière dont tu va devoir gérer tes traitements ensuite pour chaque requête.

          Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

      • [^] # Re: L'annonce

        Posté par  . Évalué à 5.

        Quand tu t'appelles google, et qu'un rapport 2 ca veut dire des centaines ou milliers de machines en moins, ca chiffre vite :)

        Linuxfr, le portail francais du logiciel libre et du neo nazisme.

  • # Jython?

    Posté par  (site web personnel) . Évalué à 5.

    Pour les perfs, pourquoi ne pas tout simplement utiliser Jython vu que le Go est lent?

    Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.