G.bleu a écrit 186 commentaires

  • # On t'as démasqué

    Posté par  (site web personnel) . En réponse au journal 8 mois avec Javascript (ES6) et vue.js : mon retour d'expérience du développement front en 2018. Évalué à 10.

    Sans déconner : après huit mois d'observation, ma conclusion la plus logique est que 95 % de la communauté Javascript est composée de macaques sous cocaïne.

    On t'a démasqué Sam&Max !

  • [^] # Re: Hum...

    Posté par  (site web personnel) . En réponse au journal Le VAE n'est PAS un truc de fainéant. Évalué à 5.

    https://mobilite-mobiliteit.brussels/sites/default/files/2017_bhg_fietsrapport_fr_lr.pdf#page=37

    Selon ton document:

    Gravité :
    • 8 piétons blessés légers
    • 8 cyclistes blessés légers
    • 6 cyclistes et piétons blessés légèrement

    Donc peu de collisions, et de faible gravité

    Et en bonus:

    C’est l’inattention du piéton qui joue un rôle important, il est généralement trop tard pour que le cycliste surpris évite le piéton surgissant subitement devant lui

  • [^] # Re: go

    Posté par  (site web personnel) . En réponse au journal Réduire la taille des exécutables générés avec PyInstaller. Évalué à 1.

    C'est très intéressant !

    Par contre Ça ne pose pas de soucis avec la license de Qt ?

    Autre question: ne serait-ce pas possible d'utiliser le configurateur de Qt pour désactiver tout ce qui n'est pas utile à un projet donner, puis d'utiliser les .so générés à la place de ceux fournis par défaut par PyQt ?

  • [^] # Re: go

    Posté par  (site web personnel) . En réponse au journal Réduire la taille des exécutables générés avec PyInstaller. Évalué à 2.

    Malheureusement ce n'est pas aussi simple: dans le cas présent la majeure partie des dépendances en trop sont dues à Qt, dans le cas d'un programme en Go on aurait donc eu un binding vers les lib dynamiques intégré dans le binaire.

  • [^] # Re: performances RipGrep

    Posté par  (site web personnel) . En réponse au journal softs dev en Rust empaqueté pour Ubuntu & cie. Évalué à 10. Dernière modification le 12 septembre 2018 à 13:49.

    On sait ;-)

    L'auteur de RipGrep a pondu un excellent article sur quels sont les spécificités d'un programme de type grep ainsi que les optimisations utilisées dans RipGrep qui le rend aussi rapide tout en comparant avec les choix techniques des autres greps (git grep, silver searcher, GNU grep etc.).

    Pour ceux qui ont la flemme de cliquer sur le lien, un petit one liner pour piquer votre curiosité :)

    python -c "import re; re.search('(a*)*c', 'a' * 30)"

  • [^] # Re: Argument fallacieux

    Posté par  (site web personnel) . En réponse au journal quand Oracle fait les affaires de Azul.. Évalué à 4. Dernière modification le 21 août 2018 à 13:51.

    LLVM n'a pas eu (et pour l'avoir utilisé, c'est vraiment pas dans l'esprit de LLVM le JIT, j'en ferai un journal à l'occasion)

    Je suis très preneur d'un journal sur LLVM orienté JIT !
    Les p'tits gars de Godotengine (moteur de jeu opensource) sont en train d'évaluer le coût d'un JIT pour leur langage de script custom (https://github.com/godotengine/godot/issues/5049) et LLVM semblait la solution la plus pérenne mais malgré tout assez lourde à maintenir.

    Oui ce post est HS ;-)

  • [^] # Re: Plutôt que du Lua...

    Posté par  (site web personnel) . En réponse à la dépêche Sortie d’OpenMW 0.44. Évalué à 6.

    D'autant plus que ce projet a déjà fait les frais d'un langage "exotique": de ce que j'ai compris il a été commencé en D pour finalement être réécrit en C++ en grande partie pour permettre au plus grand nombre de contribuer (ce qui a bien marché vu qu'après 10ans et le départ de son créateur le projet est toujours vivant et en bonne forme !)

  • [^] # Re: Une défense des autotools

    Posté par  (site web personnel) . En réponse au journal Un petit tour des systèmes de build. Évalué à 0.

    Des heures pour trouver qu’il faut ajouter le nom du fichier à la variable monprogramme_SOURCES dans le fichier Makefile.am ?

    Non, des heures pour se remémorer les commandes et le fonctionnement du truc, pour chercher la doc sur internet et surtout pour comprendre que la version d'autotools de ma Gentoo d'il y a 6mois était incompatible avec celle de mon Ubuntu. Débugger des scripts de plusieurs milliers de lignes c'est tellement facile.

    Rien ne t’oblige à committer les fichiers générés, il est d’ailleurs généralement recommandé de ne pas le faire…

    Tout à fait, comme ça non seulement je ne pouvais plus rajouter de fichiers mais en plus je pouvais plus non plus générer le build ;)

    Sérieusement, tu dis avoir eu à cœur d’apprendre les Autotools, mais ton expérience, soit est une caricature trollesque, soit est typique de celui qui veut utiliser les autotools sans rien comprendre de ce qu’il fait.

    Sérieusement, j'ai publié mon expérience, j'ai pris la peine de mettre un lien vers le projet en question donc me traiter de troll et insinuer que je suis incompétent c'est franchement un gros manque de respect de ta part.

    Les Autotools ne sont pas les outils les plus faciles à utiliser, c’est un fait et c’est une critique tout-à-fait valable.

    Merci, donc au final on arrive à la même conclusion ;-)

  • [^] # Re: Une défense des autotools

    Posté par  (site web personnel) . En réponse au journal Un petit tour des systèmes de build. Évalué à 4.

    Perso mon expérience des autotools ça a été de créer un petit projet avec (https://github.com/touilleMan/mpa_robot).

    Le truc fait grosso modo 1000 lignes de C++, mon projet sur Github est indiqué comme étant composé à 95.5% de shell…
    On a 13 fichiers à la racine du projet dédié aux autotools, plus 2 fichiers pour chaque répertoire (Makefile.in et Makefile.am)

    J'imagine qu'on peut améliorer ça, mais déjà pour en arriver là ça m'avais pris plusieurs heures de travaille (j'avais à cœur d'apprendre à utiliser les autotools).

    Le clou dans le cercueil à été 6 mois plus tard quand j'ai voulu ajouter un nouveau fichier C++ au build. Après plusieurs heures passées pour re-comprendre le bouzin, tenter de réinstaller les outils (oui mais versions incompatibles et rien pour te l'indiquer clairement…), de regénérer les fichiers (comment on met à jour un .am à partir d'un .in ? si ça crash à cause de la version de l'outil, de mon script ou bien de ma commande ? etc.) j'ai fini par abandonner.

    Sérieusement les éditeurs de jeux vidéos devraient mettre Autotools plutôt que SecuRom pour protéger leurs jeux des modifications des hackers.

  • [^] # Re: scons

    Posté par  (site web personnel) . En réponse au journal Un petit tour des systèmes de build. Évalué à 2.

    En effet j'ai découvert scons en contribuant à Godot (http://godotengine.org/) et c'est un système de build assez appréciable (en particulier le script via python qui amène pas mal de puissance et simplifie le débug grace à pdb).

    Au niveau de sa lenteur, c'était vrai il y a quelques années (les articles en parlant date de 2010…) mais ça a été corrigé depuis.
    Perso les soucis que j'ai eu avec été plus dû à la petite communauté (donc plus difficile de trouver des ressources fraîches sur le sujet) et surtout à sa politique de dépendances de compilation.
    Je m'explique: scons considère toujours qu'une cible de compilation (hors alias) est un chemin vers un fichier ou un répertoire. De là cibles de compilations pointant sur un répertoire/fichier parent sont considérées comme des dépendance.
    Ça peut sembler normal (je dois construire tout ce qu'il y a dans un répertoire avant de considérer celui-ci comme généré) mais ça très lourd quand on veut avoir une tache effectuant un traitement sur le répertoire une fois celui-ci généré :(

  • [^] # Re: Rx

    Posté par  (site web personnel) . En réponse au journal La programmation concurrente en mode Goto. Évalué à 2.

    Quelque chose qui n'est visible qu'au runtime est invisible c'est quelque chose qui peut arriver implicitement et ça rend presque impossible une validation par revue du code

    Les exceptions KeyboardInterrupt peuvent arriver à n'importe quelle moment dans ton programme Python et pourtant cela ne pose pas de soucis car on sait qu'il faut utiliser les block try/finally (ou les context manager font la même chose au final) pour gérer le nettoyage de ton code proprement. C'est pour cela que ce code est mauvais:

    fd = open('foo', 'rw')
    data = fd.read()
    ... # si une exception raise fd.close() ne sera pas appelé
    fd.write(result)
    fd.close()
    

    et que celui-ci est bon:

    with open('foo', 'rw') as fd:
        data = fd.read()
        ... # quoi qu'il arrive le with s'occupera de fermer fd
        fd.write(result)
    

    C'est exactement la même chose avec trio, sauf que tu te prends une exception trio.Cancelled au lieu d'une KeyboardInterrupt (et ça te coute rien de plus puisque t'es déjà obligé de gérer le cas KeyboardInterrupt)

    Pourquoi ne pas gérer ça dans une forme de machine à état ?

    En effet si le language le permet c'est très bien de le faire. Toutefois ce n'est pas le cas de Python donc il faut soit recréer un framework pour le faire, soit se taper le code à la main (et là autant dire qu'on a perdu)… soit tout simplement utiliser un paradigme adapté à ce langage.

    « let it crash » c'est particulier. Ça dépend de ce que tu fais comme application.

    Ça dépend surtout du niveau de granularité que tu as mis en place. Si tu crashes tout appli et la relance de zéro c'est sûr que ça ne marchera pas de masse, mais il est tout à fait possible de ne relancer qu'une partie (exemple typique: un serveur web qui ne se relance pas à chaque erreur 500 qui lui arrive, au exemple: dans une appli mobile si le service responsable de multiplexer les requêtes vers ton backend crash tu le redémarres et tu as juste à signifier aux traitements qui était en attente de ce service qu'il y a eu une déconnexion)

    Interrompre son taf c'est déjà modifier son contexte, le fait de sortir manu military des blocs de codes détruits un tas de variables,…

    D'un autre côté son taf a déjà été interrompu par l'erreur à l'origine de l'exception, maintenant c'est juste question de retourner dans un état stable (et donc d'arrêter/relancer tout ce qui a besoin de l'être).

    Au final j'ai l'impression que tu opposes programmation par message avec ce que propose trio.
    De mon point trio est une brique de plus bas niveau qui te donne des outils de qualité (cad qui te font gagner du temps et qui te pousse à faire du code propre) pour faire de l'asynchrone, à charge pour toi de l'utiliser pour faire du passage de messages ou bien du partage de ressources en fonction de ton besoin.

  • [^] # Re: Rx

    Posté par  (site web personnel) . En réponse au journal La programmation concurrente en mode Goto. Évalué à 1.

    Tu te contredis entre ta première et ta seconde phrase…

    C'est bien possible, j'ai galéré pour trouver des définitions de asynchrone/concurrente/parallèle compatibles entre elles !
    Je viens de refaire un tour sur wikipedia:
    - programmation parallèle : plusieurs choses sont traitées à un moment donné physiquement parlant (mais du coup je fais de la programmation parallèle à petite échelle sur un CPU single core mais avec une pipeline superscalaire ? Vous avez 4h !)
    - programmation concurrente : plusieurs traitement logiciels sont menés de front, c'est donc orthogonal à la programmation parallèle (concurrent non parallèle si je fais tourner plusieurs threads logiques sur un CPU monocore)
    - programmation asynchrone : plusieurs traitement sont réalisé au sein d'un même flux de programmation (program flow).

    Du coup ça n'avance pas beaucoup, vu que je voudrais exprimer:
    1) programmation-ou-il-se-passe-plusieurs-choses-de-front: je parlais de programmation parallèle en m'abstrayant des questions physiques, mais il semblerait que c'est le terme concurrente qu'il faut employer ici (et du coup le terme parallèle ne sert à rien. vu qu'il dépend de l'architecture physique dont tout le monde se fout..)
    2) la même que 1) mais en précisant que l'implémentation se fait avec des threads et des locks comme briques de base: Encore une fois en s'arrêtant au kernel je trouve que le terme programmation concurrente marche bien ici (du point du vu de mon programme je vais effectivement avoir plusieurs threads en concurrence). J'imagine qu'il faut dire "programmation concurrente par threads" mais c'est long, et j'entends déjà le premier javaiste me demande où je classe les greenthreads…
    3) la même que 1) mais en précisant que l'implémentation se fait via sur un seul thread en le partageant de manière coopérative: J'imagine que programmation asynchrone marche bien ici

    Les exceptions sont déjà complexe à gérer là ça signifie que n'importe où une exception invisible peut subvenir ?

    C'est comme ça que Python fonctionne. Toutes les exceptions héritant de BaseException (genre SystemExit ou KeyboardInterrupt) sont déjà gérée comme ça. Note que ces exceptions ne sont pas invisible, les bonnes pratiques indiquent juste qu'il faut faire, sauf cas très particulier, un except Exception pour les laisser passer.

    L'énorme avantage de ce système c'est qu'il te suffit de faire un try/finally (ou bien d'utiliser un context manager) pour gérer le nettoyage de ton code (et ce quelque soit la cause: crash de ton code ou bien d'une coroutine sœur qui rend ton traitement caduque)

    Et enfin les exceptions son très peu cher en Python (enfin comparativement à la vitesse de Python bien sûr ), d'ailleurs c'est pour ça qu'elles sont déjà utilisées pour gérer des taches courantes comme les générators.

    La seule façon de survivre correctement à cela est d'avoir un code très défensif et perso ça ne me plaît pas des masses d'écrire ce genre de code.

    Dans tous les cas tu ne peux pas passer sous silence une erreur. L'intérêt d'une exception c'est que tu es obligé de la traiter (sinon ton programme crash), à l'inverse si tu gères tout ton système uniquement avec des passements de messages c'est très tentant de ne pas prendre en compte les crashes globales et de se retrouver avec un état incohérent au moment où ça arrive (typiquement des coroutines qui attendent indéfiniment la réponse de la coroutine ayant crashé).

    Je le répète: les problèmes d'init/teardown (en particulier dans le cas d'un crash) sont ce qu'il y a de plus compliqué en asynchrone, l'intérêt de trio est de te donner un contexte pour gérer ça simplement (on fonctionne avec des paradigmes très proche de ce qu'on ferait en programmation single thread classique). Ce que tu proposes à l'inverse c'est de gérer tout ça à la main via des passement de messages (je ne parle pas du traitement de l'erreur à proprement parler, mais de toute la machinerie qui permettra d'en arriver là), c'est du code complexe. C'est pour ça que erlang a OTP qui fait tout ce travaille pour toi (et dont la philosophie "let it crash" est très défensive de base).

    On parle de lever d'exception. Lever une exception c'est manipuler l'état de ton contexte.

    Au contraire, gérer une base de données par modification directe de l'état du système (ce que fait une levée d'exception) impose de gérer un lock global pour serialiser les opérations.

    L'exception ne modifie que le context de la coroutine touchée, c'est au développeur de choisir si la coroutine en question travaille sur toutes les données ou bien sur un sous ensemble isolé du reste du système.

    Si tu écris une méthode et qu'elle est finalement utilisée dans une tâche nursery, il sera impossible de voir dans le code de cette méthode qu'il manque potentiellement la gestion de cette dernière.

    Il n'y a pas de tâche nursery, tu as une coroutine parente qui veut lancer plusieurs traitements en parallèle. Pour ça elle créé un objet nursery qui permettra de borner le scope d'action des coroutines filles lancées.
    De faite si une fille crash, les autres filles sont arrêté proprement et l'exception d'origine est remontée dans la coroutine parente.
    Je te conseil cet article de l'auteur de trio (tous son blog vaut la peine d'être lu ) qui explique très bien l'intérêt de ce genre de mécanisme quand on cherche à gérer des timeouts.

    Toutes les bases de données ont déjà résolues se problème par la création d'un event log.

    Ou bien des locks à grain fin, ce que la programmation asynchrone rend beaucoup plus simple qu'en utilisant des threads classiques.
    De mémoire Redis fonctionne de cette façon (il implémente sa propre boucle asynchrone et lance une coroutine par connection client), on peut activer un journal de logs mais c'est pour rendre les données persistantes (donc dans tous les cas on se retrouve avec des coroutines qui travaillent sur les même données dans la base).
    Sinon un autre exemple (quoi que plus bas niveau) de ce type de besoin serait le Kernel Linux. Travailler par passement de messages est intéressant mais coûteux (cf. les débat kernel monolithique vs microkernel).

    Merci pour la discussion je la trouve enrichissante (ainsi qu'à Yves et Galndos).

    La même ;-)

  • [^] # Re: Rx

    Posté par  (site web personnel) . En réponse au journal La programmation concurrente en mode Goto. Évalué à 3.

    c'est bien ce que je reproche c'est du parallélisme plus que de l'asynchrone. Le fait que ce soit parallèle ou pas est un détail pas un besoin fonctionnel.

    Pour moi l'asynchrone est un mécanisme de programmation parallèle au même titre de la concurrence. Dans le premier cas (l'asynchrone) un seul traitement est réalisé à un moment donné contre plusieurs dans le second (et encore, à condition d'avoir plusieurs cœurs physiques…), mais ça c'est justement des détails et pas un besoin fonctionnel.
    À contrario parler de parallélisme c'est parler d'un besoin fonctionnel (exemple: j'ai besoin de faire tourner ma gui et mon code applicatif en parallèle)

    ça gère que si l’une des deux branches se plante, il faut interrompre l’autre => ouf ça veut dire quoi ? Je veux dire, il va préempter ton code et tout interrompre ? C'est particulièrement dangereux.

    Si une des deux branches se plante ça veut dire qu'on est dans un état qui mérite un traitement particulier, ça peut être arrêter toutes les coroutines jusqu'à un certain niveau, retenter de zéro la traitement de la coroutine ayant échoué et bien encore ne rien etc.
    L'important c'est surtout de se dire qu'il y a nécessairement besoin de faire quelque chose (ce qui peut être "ne rien faire" mais dans ce cas on le fait en connaissance de cause) et pas juste balancer une stacktrace dans stdout et faire comme si de rien n'était, ce qui est malheureusement la façon de faire de bien trop de frameworks parallèles.

    Ensuite effectivement une fois qu'on sait ce qu'on doit arrêter, encore faut-il le faire proprement. À ce niveau trio injecte une exception CancelledError dans la coroutine à terminer, ce qui permet à celle-ci de se nettoyer proprement, voir même d'annuler son arrêt si le cœur lui en dit (mais encore une fois ça dépend totalement du cas d'usage).

    mais quand tu fais du twist, tu es massivement asynchrone.

    j'imagine que tu parles de twisted ?

    Remonter dans le contexte principal à chaque fois que quelque chose se passe mal est intenable.

    Je n'ai pas compris ce que tu voulais dire par contexte principal ? Dans un framework asynchrone lambda une fois l'event loop lancée il n'y a pas une coroutine plus principale qu'une autre. Et de toute façon l'event loop en question passe déjà son temps à switcher d'une coroutine à une autre donc je ne vois pas en quoi aller dans un contexte supplémentaire serait intenable…

    Il faut réduire le scope de tes actions et chercher à porter les informations dans des messages plus que dans un état.

    C'est justement la force des nursery, cela te permet de créer des scope regroupant tes coroutines. Et donc De fait quand une coroutine plante ça remonte ton arbre de scopes (en arrêtant les coroutines en bonne ordre dans la foulée) jusqu'à ce que un try/except veuille bien s'en occuper. Si personne ne veut s'en occuper, ben ton programme crash. Et c'est bien normal, explicit is better than implicit comme ils disent.

    La gestion d'un état dans un monde asynchrone est sincèrement dangereux parce qu'il est difficile de s'assurer qu'il reste cohérent quelque soit l'ordre dans le quel tes actions asynchrones se résolvent.

    Tout à fait d'accord. Malgré tout c'est parfois difficile de travailler uniquement avec un système de messages (typiquement dans le cas d'une base de donnée qui doit pouvoir traiter plusieurs requêtes en parallèle alors que celles-ci travaillent sur les mêmes données).
    Dans ces cas là l'asynchrone apporte un gros avantage par rapport à la programmation concurrente puisque les points de concurrences sont explicites (i.e. tant qu'on ne met pas un await dans le code on a la garantie que personne ne va faire des choses dans notre dos). Évidemment cela n'est pas gratuit et a ses propres limitations (si la base de donnée de l'exemple précédent fait des traitements lourds en CPU par exemple)

    Et dans tous les cas, tu peux parfaitement utiliser trio pour faire du passement de messages, les nursery te permettent juste de mieux organiser ton système. Comme par exemple pour gérer proprement ce qui doit se passer quand un point de traitement de tes messages crash…

  • [^] # Re: question sur article sametmax

    Posté par  (site web personnel) . En réponse au journal La programmation concurrente en mode Goto. Évalué à 3.

    Ici foo est une fonction asynchrone, du coup appeler cette fonction ne provoque pas son exécution, mais créé un objet coroutine qui doit être passé à boucle d'évènements asynchrone (comme celle de asyncio ou bien de trio) pour être effectivement exécutée.

    C'est exactement le même comportement que ce qui tu aurais avec une fonction générateur (celle contenant le mot clé yield).

  • [^] # Re: sans pour autant savoir faire du dev

    Posté par  (site web personnel) . En réponse au journal Du concombre et du cornichon. Évalué à 2.

    Sur le sujet je conseil l'article de Sam&Max sur le BDD: http://sametmax.com/lettuce-and-cucumber-is-bullshit/

    Le ton est caustique (après tout c'est pour ça qu'on les aime !) mais le fond est intéressant ;-)

  • # Intérêt de refineTH ?

    Posté par  (site web personnel) . En réponse au journal Portage de TapTempo en Haskell. Évalué à 2.

    Déjà bravo pour le journal qui était extrêmement instructif ;-)

    Ensuite je ne comprends pas l'intérêt d'utiliser refineTH pour définir la valeur de "defaultResetTime". Vu que son type "RefinedResetTime" défini déjà les contraintes, j'aurais cru que le compilateur aurait fait la vérification dessus à la compilation automatiquement (un peu comme en C où "int Foo = 3.2" va crasher à la compilation).
    Du coup sans refineTH le ton example de valeur initiale trop grande va compiler puis crasher à la runtime ? Ça me semble étrange…

  • [^] # Re: Emacs

    Posté par  (site web personnel) . En réponse au journal un éditeur de code portable par Microsoft?. Évalué à 5.

    Disclaimer: mon expérience avec Emacs s'est terminée vers 2013, c'est possible que le système de config se soit amélioré depuis.

    Personnellement j'ai arrêté Emacs après m'être rendu compte qu'un sublimetext out-of-the-box répondait mieux à mes besoin que ma conf Emacs dans laquelle j'avais investi des dizaines d'heures sur plusieurs années.

    C'est un peu le syndrome "écosystème javascript" avec des tonnes de paquets faisant tous un petit truc et une lib standard rachitique (ok pas rachitique dans le cas d'Emacs, mais le conservatisme des dévs fait que des fonctionnalités genre multicursors ne sont pas incluses).

    Bien sûr le fun arrive quand on se retrouve avec des fonctionnalités fournies par des paquets différents mais qui s'interpénètrent (exemple: j'ai un module fournissant une minimap du code et j'aimerai qu'il m'indique où se trouve chacun de mes multicurseurs sur celle-ci).

    Au final avec la puissance de Elisp on arrive toujours à s'en sortir… mais à quel prix ! C'est un langage avec une philosophie bien à part, demander à un mec qui veut juste tweaker un truc dans sa conf de l'apprendre c'est un non-sens en terme d’ergonomie.

    Bref on en revient toujours à la courbe d'apprentissage : les anciens ne la voient plus et considèrent les nouveaux qui s'en plaignent comme des incapables. Le fait que j'ai fini par me considérer comme faisant partie de la seconde catégorie après des années d'utilisation régulière d'Emacs témoignera de la dureté de cette courbe (insérer une strip xkcd ici).

  • [^] # Re: Réinvention de la roue

    Posté par  (site web personnel) . En réponse au journal un éditeur de code portable par Microsoft?. Évalué à 5.

    Déjà ce serait bien que Emacs et XEmacs se réconcilies, on verra ensuite pour unifier le reste…

  • [^] # Re: Euhhh...

    Posté par  (site web personnel) . En réponse au journal Le cycle de Qarnot. Évalué à 10.

    Y'a déjà hotmail pour ça !

  • # Distribue les à tes projets préférés !

    Posté par  (site web personnel) . En réponse au journal Que faire avec ses clefs steam inutilisées ?. Évalué à 10.

    Je pense que ça peut être super cool que tu ouvres une issue sur les repos de tes projets préférés pour proposer au mainteneur de choisir un jeu parmi une liste en guise de remerciement ;-)

  • # Une tentative d'explication pour le 3eme test...

    Posté par  (site web personnel) . En réponse au journal Le Firefox nouveau est arrivé !. Évalué à 5.

    Le 3eme test exécute des snippets de code javascript une à une (facile à voir vu que le score de chaque lib se met à jour l'une après l'autre au fur et à mesure du test).
    Du coup j'en déduis que ce benchmark vise uniquement à tester les performances de la vm javascript du navigateur en monothread (javascript ne supporte pas les threads, c'est pour ça que l'api des web workers a été mise en place dans html5).
    À l'inverse le travail d'optimisation sur Firefox a visé la mise en place du parallélisme partout ou c'était possible (https://blog.rust-lang.org/2017/11/14/Fearless-Concurrency-In-Firefox-Quantum.html et https://hacks.mozilla.org/2017/08/inside-a-super-fast-css-engine-quantum-css-aka-stylo/ pour ceux qui ont raté ces super liens).

    tldr: v8, la vm javascript de chrome, est toujours plus performante que celle de firefox. Mais y'a pas que ça qui fait qu'un navigateur est rapide ;-)

  • [^] # Re: Question trollesque (et sincère)

    Posté par  (site web personnel) . En réponse au journal Pythran 0.8.2 — compilation de noyaux scientifiques écrits en Python. Évalué à 10.

    C++ est beaucoup plus complexe que Python, dans le domaine scientifique les utilisateurs ne sont majoritairement pas des développeurs de métier donc cette complexité s'accentue encore d'un cran.
    L'avantage de Cython&co c'est de pouvoir faire une seconde passe d'optimisation sur du code dégueulasse de chercheur une fois qu'il est fonctionnellement correct au lieu de tout devoir redévelopper en C++.

    À titre personnel j'ai des projets d'utilisation de ces outils pour le jeu vidéo avec mon binding Python sur Godot afin de pouvoir scripter rapide en Python, puis d'avoir une passe d'optimisation suffisamment simple et rapide, avant de réécrire en gros C++ qui tache si ce n'est toujours pas assez ;-)

  • # Sauf que en fait non

    Posté par  (site web personnel) . En réponse au journal Recrutons. D'accord, mais sur quels critères ?. Évalué à 10.

    Il faut voir qui est l'auteur de ce billet de blog:

    Il s'agit du CEO de TWD industries AG (aussi nommé parfois TrustLeap, ça dépend des pages…), société bien connue pour G-WAN, un serveur high performances (http://gwan.com/benchmark, ça met un petit x7 à nginx, rien que ça).

    "G-Wan is a revolutionary piece of software for the internet industry." Avait titré Salem-News à l'époque de sa sortie !
    (bon ok, c'est pas la une du Times, mais c'est mieux que Mickey parade non ? http://salem-news.com/print/19923)

    Évidemment, avec une telle technologie d'avant garde, le placement est premium: http://gwan.com/buy comptez entre 150 et 200 000 francs suisse de licence annuelle !

    Bon sauf que c'est bien sûr du bon gros bullshit:
    http://www.olivierdoucet.info/blog/2013/01/12/tests-approfondis-de-g-wan/
    http://tomoconnor.eu/blogish/gwan-snakeoil-beware/
    https://gist.github.com/Samuirai/2932918

    En gros son serveur se contente d'avoir un gros cache activé par défaut qui fait que le script d'une route n'est appelé qu'une fois par seconde (remarque en utilisant CGI comme il y a 20ans heureusement !).

    En ce moment c'est la "post-quantum security (PQE)" (http://twd-industries.com/faq.html) qui est le nouveau cheval de bataille de ce joyau helvète, on ne sait pas comment ils vont le faire, ni ce qu'ils vont faire, mais en tout cas ce sera fait ! (et ça va coûter bonbon)

    Ah et bien sûr quand le mec se présente comme étant R&D director depuis 24ans, c'est à mettre en perspective avec le fait qu'il s'agisse de la boite qu'il a créé lui même (et dont j'imagine qu'il est le seul employé…)

    Bref quand ce mec nous sort que le recruteur de Google est une bille, pour moi c'est (par ordre de probabilité):
    - Il n'y jamais eu d'entretien avec Google et le mec cherche à créer du buzz pour faire tourner sa boutique
    - Sur un quiproquo un entretien à eu lieu et le recruteur de Google s'est vite rendu compte du charlot qu'il avait en face
    - je suis moi même une bille incapable de comprendre le génie de TWD industries AG

  • # Quelques retours sur le code

    Posté par  (site web personnel) . En réponse à la dépêche Owlready : un module Python pour manipuler les ontologies OWL. Évalué à 6.

    Bravo pour l'article, je ne connaissais pas du tout ce type de programmation, maintenant ma curiosité a été piquée ;-)

    Aurais-tu des exemples de d'application non triviaux dans lesquels ce type de programmation fonctionne bien ?

    Sinon j'ai parcouru rapidement le code et j'ai quelques conseils :

    • Ton module utilise java sous le capot. Il serait bien d'en parler dans le READEME (ce n'est vraiment pas une dépendance anodine) et même de permettre à l'utilisateur de configurer quel java utiliser (via variable d'env par exemple).

    • Il aurait été mieux de créer un répertoire owlready dans ton repo contenant le code python, l'avantage étant que la racine du repo est beaucoup moins fournie donc plus lisible, ainsi que le fait de pouvoir utiliser ton module sans avoir à l'installer en se étant dans le répertoire du projet.

    • Ton répertoire test n'utilise pas de framework de test, je te conseil pytest qui est absolument génial (tu créé un fichier commençant par test_, tu mets des fonctions commençant par test_ qui font des assert et tu lances le tout avec avec py.test, c'est brillant de simplicité et extrêmement puissant). L'avantage étant que tu auras des rapport sur tes tests beaucoup plus précis et que tu pourras être beaucoup plus expressif dans tes tests (fixtures, setup/teardown, modules tiers etc.)

    • De même je te conseils d'utiliser travis qui te permettra de faire de l'intégration continue (d'autant plus importante si tu cherches à avoir des contributeurs externes)

    • La PEP8 n'est pas respecté, vu que c'est le standard ça rend tout de suite le code moins lisible. Il y a des outils comme autopep8 qui te permettent de mettre en forme ta base de code automatiquement, et flake8 en linter pour faire de la PEP8 sans y penser ;-)

    • Les import * sont à proscrire (allez, à la rigueur on peut les utiliser dans le __init__.py quand celui-ci se contente de definir l'api exposée), ça rend le code beaucoup plus complexe quand on ne le connait pas, d'autant plus quand on le consulte en ligne et qu'on ne peut pas faire des greps dans le projet :'-(

    • Mettre plusieurs commandes sur une même lignes via les point-virgules rend les choses confus, d'autant plus avec une indentation à 2 espaces, exemple qui m'a fait saigner:

    class CallbackList(FirstList):
      __slots__ = ["_obj", "_callback"]
      def __init__(self, l, obj, callback):
        super().__init__(l)
        self._obj      = obj
        self._callback = callback
      def _set  (self, l):          super().__init__(l)
      def _append(self, x):         super().append(x)
      def _remove(self, x):         super().remove(x)
      def reinit(self, l):          old = list(self); super().__init__(l)       ; self._callback(self._obj, old)
      def append(self, x):          old = list(self); super().append(x)         ; self._callback(self._obj, old)
      def insert(self, i, x):       old = list(self); super().insert(i, x)      ; self._callback(self._obj, old)
      def extend(self, l):          old = list(self); super().extend(l)         ; self._callback(self._obj, old)
      def remove(self, x):          old = list(self); super().remove(x)         ; self._callback(self._obj, old)
      def __delitem__(self, i):     old = list(self); super().__delitem__(i)    ; self._callback(self._obj, old)
      def __setitem__(self, i, x):  old = list(self); super().__setitem__(i, x) ; self._callback(self._obj, old)
      def __delslice__(self, i):    old = list(self); super().__delslice__(i)   ; self._callback(self._obj, old)
      def __setslice__(self, i, x): old = list(self); super().__setslice__(i, x); self._callback(self._obj, old)
      def __iadd__(self, x):        old = list(self); super().__iadd__(x)       ; self._callback(self._obj, old); return self
      def __imul__(self, x):        old = list(self); super().__imul__(x)       ; self._callback(self._obj, old); return self
      def pop(self, i):             old = list(self); r = super().pop(i)        ; self._callback(self._obj, old); return r
    

    Je le répète, j'ai beaucoup apprécié ton article et j'espère que tu ne prendras pas mal ces remarques qui sont plus sur la forme que le fond ;-)

  • [^] # Re: Python pour scripter, C/C++ sous la capot.

    Posté par  (site web personnel) . En réponse au journal Un Python qui rivalise avec du C++. Évalué à 2.

    Une exception : Torch dont l'API est en Lua.

    Et c'est pour ça qu'il y a pytorch maintenant ;-)