• [^] # Re: Questions

    Posté par . En réponse au journal OpenJDK JEP 180: HashMap, collisions & attaques par la complexité. Évalué à 10.

    Mais pourquoi Java documente ainsi la triperie interne ?

    En général ce n'est pas le cas. Les contrats sont du type "Chaque opération à cette complexité", "l'ordre d'itération est garantie ou non" etc.

    Pour l'histoire spécifique de hashCode je ne sais pas pourquoi ça a été documenté. On trouve dans le bug tacker que l'implémentation actuelle est apparue entre 1997 et 1999 avec Java 1.2. Ils ont donc déjà fait le changement une fois mais le contexte était différent, d'ailleurs l'analyse est rigolote:

    Risk Assessment: Surprisingly small. Serialization of Hashtables does
     not depend on consistent hash values. It is possible
     that some customer has implemented some persistent data
     structure that relies on the String hash function not
     changing, but it is highly unlikely that more than a
     handful of customers have done so.
    

    Maintenant même si la javadoc n'avait pas documenté l'algo noir sur blanc je ne sais pas si ils auraient fait le changement. D'une manière générale Java est très conservateur sur les changements de comportement même pour des choses qui ne sont pas écrite noir sur blanc. Le but est de ne pas casser le code existant même si il est en tord. (pour le meilleur ou pour le pire donc). En théorie changer hashCode ne change pas grand chose, en pratique du code pourri qui fait des supposition sur l'ordre des iterateurs, qui le persiste ou fait d'autres merdes avec ça se trouve malheureusement.

    D'un autre côté dans la même 7u6 ils ont discrètement balancé un autre changement nucléaire sur les String: changer l'implémentation de substring. Là le changement était permis par le contrat mais l'impact sur les applis est réel. En gros, avant un substring créait un objet qui pointait sur le byte buffer original (on partage donc la mémoire et c'est O(1)) maintenant il fait une copie du byte buffer original (on ne partage donc plus la mémoire et c'est O(n)). Le rationnel était qu'il est facile de faire des fuites mémoire par error avec l'ancienne implémentation. Maintenant tout le code qui reposait intensivement sur substring (parser etc.) à vu son profile à l'exécution bien changer... Comme quoi le choix de le faire où non peut être variable et est en général bien analysé.

    Tu fais comment pour générer les graphiques qui semblent dessinés à la main ?

    C'est le mode xkcd de matplotlib. Si ca t'intéresse le code qui a servi à générer les graphiques est dans le notebook IPython sur github (dernier lien).

    Il ne faut pas en abuser, mais je trouve qu'il indique clairement que l'intention du graphe est de donner une idée générale ou un ordre de grandeur et non de focaliser sur des chiffres précis: "Si deux courbes sont proches, ne vas pas chercher plus loin que tu as le même comportement". À l'inverse le style ggplot2 indique clairement que si tu as envie d'analyser précisément le graphique tu peux: "Si deux courbes sont proches tu peux analyser chaque couple de point individuellement et creuser pourquoi".