Pattern.split plus lent que Ssortingng.split

Il y a deux méthodes:

private static void normalSplit(Ssortingng base){ base.split("\\."); } private static final Pattern p = Pattern.comstack("\\."); private static void patternSplit(Ssortingng base){ //use the static field above p.split(base); } 

Et je les teste comme ceci dans la méthode principale:

 public static void main(Ssortingng[] args) throws Exception{ long start = System.currentTimeMillis(); Ssortingng longstr = "abcdefghij";//use any long ssortingng you like for(int i=0;i<300000;i++){ normalSplit(longstr);//switch to patternSplit to see the difference } System.out.println((System.currentTimeMillis()-start)/1000.0); } 

Intuitivement, je pense que Ssortingng.split appellera finalement Pattern.comstack.split (après beaucoup de travail supplémentaire) pour faire la vraie chose. Je peux construire l’object Pattern à l’avance (il est thread-safe) et accélérer la division.

Mais le fait est que l’utilisation du motif pré-construit est beaucoup plus lente que d’appeler directement Ssortingng.split . J’ai essayé d’utiliser une chaîne de 50 caractères (avec MyEclipse). L’appel direct ne consum que la moitié du temps nécessaire pour utiliser un object Pattern pré-construit.

S’il vous plaît quelqu’un peut-il me dire pourquoi cela se produit?

Cela peut dépendre de l’implémentation réelle de Java. J’utilise OpenJDK 7, et ici, Ssortingng.split effectivement Pattern.comstack(regex).split(this, limit) , mais uniquement si la chaîne à scinder, regex , est plus qu’un seul caractère.

Voir ici pour le code source, ligne 2312.

 public Ssortingng[] split(Ssortingng regex, int limit) { /* fastpath if the regex is a (1)one-char Ssortingng and this character is not one of the RegEx's meta characters ".$|()[{^?*+\\", or (2)two-char Ssortingng and the first char is the backslash and the second is not the ascii digit or ascii letter. */ char ch = 0; if (((regex.count == 1 && // a bunch of other checks and lots of low-level code return list.subList(0, resultSize).toArray(result); } return Pattern.comstack(regex).split(this, limit); } 

Comme vous vous séparez par "\\." , il utilise le “raccourci”. C’est-à-dire si vous utilisez OpenJDK.

Voici le changement de comportement de Ssortingng.split , effectué dans Java 7 . Voici ce que nous avons dans 7u40 :

 public Ssortingng[] split(Ssortingng regex, int limit) { /* fastpath if the regex is a (1)one-char Ssortingng and this character is not one of the RegEx's meta characters ".$|()[{^?*+\\", or (2)two-char Ssortingng and the first char is the backslash and the second is not the ascii digit or ascii letter. */ char ch = 0; if (((regex.value.length == 1 && ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) || (regex.length() == 2 && regex.charAt(0) == '\\' && (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 && ((ch-'a')|('z'-ch)) < 0 && ((ch-'A')|('Z'-ch)) < 0)) && (ch < Character.MIN_HIGH_SURROGATE || ch > Character.MAX_LOW_SURROGATE)) { //do stuff return list.subList(0, resultSize).toArray(result); } return Pattern.comstack(regex).split(this, limit); } 

Et c’est ce que nous avions en 6-b14

 public Ssortingng[] split(Ssortingng regex, int limit) { return Pattern.comstack(regex).split(this, limit); } 

Je pense que cela ne peut être expliqué que par l’optimisation JIT, Ssortingng.split en interne est implémenté comme suit:

 Pattern.comstack(regex).split(this, limit); 

et ça marche plus vite quand on est dans Ssortingng.class, mais quand j’utilise le même code dans le test:

  for (int i = 0; i < 300000; i++) { //base.split("\\.");// switch to patternSplit to see the difference //p.split(base); Pattern.compile("\\.").split(base, 0); } 

p.split(base) le même résultat que p.split(base)