Avant que quiconque remette en question le fait d'utiliser string.intern()
en général, laissez-moi dire que je en ai besoin dans mon application particulière pour des raisons de mémoire et de performances. [1]
Donc, jusqu'à présent, j'ai utilisé String.intern()
en pensant que c'était la manière la plus efficace de le faire. Cependant, j'ai remarqué depuis des lustres que c'était un goulot d'étranglement dans le logiciel. [2]
Ensuite, récemment, j'ai essayé de remplacer le String.intern()
par une énorme map où je mets/récupère les chaînes de caractères afin d'obtenir à chaque fois une instance unique. Je m'attendais à ce que cela soit plus lent... mais c'était exactement le contraire! C'était extrêmement plus rapide! Remplacer le intern()
par pousser/tirer d'une map (qui réalise exactement la même chose) a résulté en une vitesse plus de dix fois plus rapide.
La question est : pourquoi intern()
est-il si lent ?!? Pourquoi n'est-il pas simplement soutenu par une map (ou en fait, juste un ensemble personnalisé) et serait-il extrêmement plus rapide ? Je suis perplexe.
[1] : Pour ceux qui ne sont pas convaincus : il s'agit de traitement de langage naturel et doit traiter des gigaoctets de texte, donc il doit éviter de nombreuses instances d'une même chaîne de caractères pour éviter de faire exploser la mémoire et pour que la comparaison de chaînes de caractères référentielles soit suffisamment rapide.
[2] : sans lui (chaînes de caractères normales) c'est impossible, avec lui, cette étape particulière reste la plus intensive en calcul
ÉDITION :
En raison de l'intérêt surprenant pour ce post, voici un peu de code pour le tester :
Et les résultats de la mise en intern de un peu plus d'un million de chaînes de caractères :
HashMap
: 4 secondesString.intern()
: 54 secondes
Pour éviter tout préchauffage / mise en cache E/S du système d'exploitation et des choses comme ça, l'expérience a été répétée en inversant l'ordre des deux tests :
String.intern()
: 69 secondesHashMap
: 3 secondes
Comme vous pouvez le constater, la différence est très remarquable, plus de dix fois. (En utilisant OpenJDK 1.6.0_22 64bits ... mais en utilisant celui de Sun a donné des résultats similaires je pense)