9
votes

Comparaison des performances d'opération de sous-chaînes entre .NET et Java

Prendre des sous-chaînes d'une chaîne est une opération de manipulation de chaîne très courante, mais j'ai entendu dire qu'il pourrait y avoir des différences considérables dans la performance / la mise en œuvre entre la plate-forme Java et .NET. Spécifiquement, j'ai entendu dire qu'en Java, java.lang.string offre constante fonctionnement de l'heure pour SUBSTRIND , mais dans .NET, Système. Chaîne offre linéaire performances SUBSTRING .

sont-ils vraiment le cas? Peut-il être confirmé dans la documentation / code source, etc.? Cette implémentation est-elle spécifique ou spécifiée par la langue et / ou la plate-forme? Quels sont les avantages et les inconvénients de chaque approche? Qu'est-ce que une personne doit migrer d'une plate-forme à un autre cherche à éviter de tomber dans des pièges de performance?


5 commentaires

Pourquoi ne pas exécuter vos propres repères micro pour tester cela? Pouvez-vous créer un lien vers des sources qui disent que cela a une "mauvaise" performance?


@ODed: la source est le commentaire de Danny Chen ici Stackoverflow.com/Questtions/3474254/... ; Honnêtement, je serais étonné si substrant n'est pas O (1) opération de temps et d'espace (comme Java), mais je lui donne l'avantage de la doute depuis que je ne connais pas .net.


Qu'est-ce que cela signifie "mauvaise performance"? Par rapport à quoi? .NET a également une mauvaise performance de comparaison à C ++ par exemple. Devrions-nous laisser tomber .net à cause de cela?


Cela cite donc-t-il un article? Si oui, un lien serait vraiment, aidez vraiment ...


Oups - Je n'avais pas vu votre commentaire précédent.


4 Réponses :


1
votes

Selon cela, pas vraiment: C # Substring


0 commentaires

2
votes

Utilisation du réflecteur C'est ce que vous obtenez de la sous-chaîne (int32, int32) xxx

si vous continuez à entrer dans le dernier appel, c'est à un xxx

qui copie les caractères utilisant des pointeurs. Le code complet a réellement l'air gros mais vous ne verrez pas à quel point il est rapide ou ralentissé jusqu'à ce que vous l'exécutiez et que vous l'assiège.


0 commentaires

0
votes

Cela dépend vraiment de votre charge de travail. Si vous êtes en boucle et que vous faites beaucoup d'appels de sous-chaînes, vous pourriez avoir un problème. Pour le présent article que vous faites référence, je doute que ce serait un problème. Avec cette attitude, cependant, vous pourriez toujours vous retrouver dans une situation de «mort par mille coupes de papier». Dans la présente, vous vous référez, nous avons les suivants:

String after = before.Substring(0, 1).ToUpper() + before.Substring(1);


0 commentaires

11
votes

in .NET, substrant est O (n) plutôt que le O (1) de Java. C'est parce que dans .NET, l'objet String contient toutes les données de caractère réelles elles-mêmes 1 - la prise de sous-chaîne consiste donc à copier toutes les données dans la nouvelle sous-chaîne. En Java, SUBSTRING peut simplement créer un nouvel objet faisant référence au tableau de caractères d'origine, avec un index de départ et une longueur de départ différents.

Il y a des avantages et des inconvénients de chaque approche:

  • L'approche de .NET a une meilleure cohérence de cache, crée moins d'objets 2 et évite la situation où une petite sous-chaîne empêche un très grand chargeur [] étant recueilli. Je crois en certains cas, il peut rendre une interoption très facile aussi, en interne.
  • L'approche de Java rend une sous-chaîne très efficace et probablement des autres opérations trop

    Il y a un peu plus de détails dans mon Article Strings .

    Quant à la question générale consistant à éviter les pièges à la performance, je pense que je devrais avoir une réponse en conserve prête à couper et coller: assurez-vous que votre architecture est efficace et la met en œuvre dans la manière la plus lisible que vous pouvez. Mesurer les performances et optimiser où vous trouvez des goulots d'étranglement.


    1 Incidemment, ceci fait chaîne très spécial - c'est le seul type non-tableau dont l'empreinte mémoire varie par exemple dans le même CLR.

    2 pour les petites chaînes, c'est une grosse victoire. Il est assez grave qu'il y ait toutes les frais générales de un objet , mais lorsqu'il y a une matrice supplémentaire impliquée également, une chaîne unique de caractères pourrait prendre environ 36 octets en Java. (C'est un nombre "doigt-in-the-air" - je ne me souviens pas des frais généraux d'objet exacts. Cela dépendra également du VM que vous utilisez.)


0 commentaires