Conversion d’un entier vers une chaîne de caractères

Au cours d’une relecture de code, je tombe sur cette ligne :

int myInt = 1979;
byte[] foo = ("" + myInt).getBytes();

L’objectif de ce code étant de récupérer un tableau de byte d’un entier en passant par une chaîne de caractères et ça fonctionne ! Mais cela est-il performant ?

Comme je suis curieux, j’ai regardé le bytecode et découvert que ce code créé un StringBuilder pour faire la conversion de l’entier vers la chaîne de caractères :

NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.()V
ILOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append(I)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
INVOKEVIRTUAL java/lang/String.getBytes()[B
ASTORE 2

En parcourant l’API, je découvre la méthode String.valueOf(int i) qui permet de convertir un entier en chaîne de caractères

int myInt = 1979;
byte[] bar = String.valueOf(myInt).getBytes();

Cela semble mieux en analysant le bytecode qui ne créé pas de nouvel objet mais utilise une méthode statique :

ILOAD 1
INVOKESTATIC java/lang/String.valueOf(I)Ljava/lang/String;
INVOKEVIRTUAL java/lang/String.getBytes()[B
ASTORE 2

Cela semble plus performant mais comme je suis très curieux, j’ai regardé l’implémentation de String.valueOf(int i) qui en fait, se contente d’un appel à Integer.toString(int) :

int myInt = 1979;
byte[] bar = Integer.toString(myInt).getBytes();

Le bytecode ressemble beaucoup au précédent mais évite un appel supplémentaire.

ILOAD 1
INVOKESTATIC java/lang/Integer.toString(I)Ljava/lang/String;
INVOKEVIRTUAL java/lang/String.getBytes()[B
ASTORE 2

Voyons maintenant si ce code améliore les performances. Le test de performance est fait sur la [CONFIG_ARM926EJ-S] avec JamVM 1.5.4 / GnuClasspath 0.98 / Java 1.5 :

Nombre d'appelStringBuilderString.valueOf(int i)Integer.toString(int)
1549ms9ms7ms
5594ms71ms15ms
100865ms342ms238ms

En conclusion, le fait d’utiliser String.valueOf(int i) ou mieux, Integer.toString(int i), permet de gagner en performance d’exécution mais aussi en mémoire car cela évite de crée de nouveau objet intermédiaire.

Plus généralement, il est toujours préférable d’utiliser les méthodes statiques des classes de bases tel que String, Integer qui seront plus performantes que les méthodes des instances.

Commentaires
Laisser un commentaire