OVH Cloud OVH Cloud

lenteur de conversion byte[] vers String

5 réponses
Avatar
Eric Razny
Bonjour.

Un code comme :

byte buf[]=new byte[L_LENGTH];
//[snap] ... buf is filled with raw datas, some parts are UTF-16BE strings
String S=new String(buf, 20, 54, "UTF-16BE");

fonctionne mais est horriblement lent. Le web n'a rien donné, pas plus
qu'une recherche sur usenet (ou alors j'ai tapé avec des mouffles :) )

Quelqu'un aurait une idée pour accélérer le bidule?

Merci d'avance.

Eric

5 réponses

Avatar
Chr
Bonjour.

Un code comme :

byte buf[]=new byte[L_LENGTH];
//[snap] ... buf is filled with raw datas, some parts are UTF-16BE strings
String S=new String(buf, 20, 54, "UTF-16BE");

fonctionne mais est horriblement lent. Le web n'a rien donné, pas plus
qu'une recherche sur usenet (ou alors j'ai tapé avec des mouffles :) )

Quelqu'un aurait une idée pour accélérer le bidule?

Merci d'avance.

Eric


StringBuffer sb=new StringBuffer();
sb.append("UTF-16BE");
String s = sb.toSting();

Avatar
TestMan
Bonjour.

Un code comme :

byte buf[]=new byte[L_LENGTH];
//[snap] ... buf is filled with raw datas, some parts are UTF-16BE strings
String S=new String(buf, 20, 54, "UTF-16BE");

fonctionne mais est horriblement lent. Le web n'a rien donné, pas plus
qu'une recherche sur usenet (ou alors j'ai tapé avec des mouffles :) )

Quelqu'un aurait une idée pour accélérer le bidule?

Merci d'avance.

Eric


Bonjour,

"horriblement lent", tu peux étayer ton propos ?

Si tu travailles avec de grosse quantité de chaines à transformer, mieux
vaut simplement utiliser les flux (Stream / Reader), c'est plus simple
et tu peux optimiser à tout les niveaux (buffer, nio, ...).

Si maintenant tu récupéres un truc style "structure", et que tu veux le
"parser" pour remplir un bean par exemple alors regarde DataInputStream
et ByteArrayInputStream.

Et enfin, si tu as besoin de performance de haut niveau, je te conseille
l'utilisation d'un outil d'analyse de performance qui te permetra de
voir ou tu dois gagner du temps en priorité dans ton algo ...

A+

TM

Avatar
Eric Razny
Le Tue, 24 Jan 2006 16:15:17 +0100, Chr a écrit :

byte buf[]=new byte[L_LENGTH];
//[snap] ... buf is filled with raw datas, some parts are UTF-16BE
strings String S=new String(buf, 20, 54, "UTF-16BE");

fonctionne mais est horriblement lent. Le web n'a rien donné, pas plus
qu'une recherche sur usenet (ou alors j'ai tapé avec des mouffles :) )

Quelqu'un aurait une idée pour accélérer le bidule?


StringBuffer sb=new StringBuffer();
sb.append("UTF-16BE");
String s = sb.toSting();


Ok mais je part d'un buffer de byte et dans StringBuffer il n'y a rien
pour ajouter des byte[], sachant qu'on ne peut faire un cast de byte[]
vers char[].
Et si je dois repartir sur un sb.append(new String(...)) je tourne en rond.

Par contre s'il y a moyen d'ajouter ce satané buffer je peux probablement
réutiliser le StringBuffer une fois crée, ce qui gagnera du temps.

Merci.

Eric.


Avatar
Eric Razny
Le Tue, 24 Jan 2006 16:53:44 +0100, TestMan a écrit :

"horriblement lent", tu peux étayer ton propos ?


Oops, au temps pour moi. Voici la partie épurée du reste :

/////// CODE //////

import java.io.FileInputStream;
import java.nio.MappedByteBuffer;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; import java.util.GregorianCalendar;

public class Test{
public static void main(String args[]){

int sum = 0;
String fileName="/tmp/test.bin"; //file size is 22MB :
22645840 GregorianCalendar start=new GregorianCalendar();
try {


FileInputStream fs = new FileInputStream(fileName); FileChannel fchan null;
fchan = fs.getChannel();
int sz = (int)fchan.size();
MappedByteBuffer mbuf = null;
mbuf fchan.map(FileChannel.MapMode.READ_ONLY, 0, sz);

byte tpb = 0;
ByteBuffer ibuf = mbuf.asReadOnlyBuffer();
byte tmpBuf[]=new byte[212];
while (ibuf.hasRemaining()) {
ibuf.get(tmpBuf);
String Part1=new String(tmpBuf, 20, 54,
"UTF-16BE"); // à commenter
String Part2=new String(tmpBuf,
74, 132, "UTF-16BE"); // à commenter
}
}
}catch(Exception e){e.printStackTrace();}
System.out.println("Duration in ms : "+(new
GregorianCalendar().getTimeInMillis()-start.getTimeInMillis()));
}
}
/////// END OF CODE //////

Qui donne sur une plateforme particuliere :
ava version "1.5.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08) Java
HotSpot(TM) Client VM (build 1.5.0_01-b08, mixed mode, sharing) Linux 2.6,
debian sarge, via processor & chipset.

4616 alors qu'en commentant les deux lignes 383.


Si tu travailles avec de grosse quantité de chaines à transformer, mieux
vaut simplement utiliser les flux (Stream / Reader), c'est plus simple et
tu peux optimiser à tout les niveaux (buffer, nio, ...).


J'ai a un moment un buffer de byte, c'est mon prérequis :(
De toutes les manière le point qui me pénalise ici n'est pas les accès
disques.

Si maintenant tu récupéres un truc style "structure", et que tu veux le
"parser" pour remplir un bean par exemple alors regarde DataInputStream
et ByteArrayInputStream.


DataInputStream est un codage particulier qui passe par de l'UTF-8. Ici
dans mon buffer j'ai dans une partie des chaines unicode en UTF-16 big
endian.

ByteArrayInputStream me remet dans la même position : je n'ai rien
trouvé dans les API qui me permettent d'initialiser un String UTF-16BE
plus rapidement.

Et enfin, si tu as besoin de performance de haut niveau, je te conseille
l'utilisation d'un outil d'analyse de performance qui te permetra de voir
ou tu dois gagner du temps en priorité dans ton algo ...


La c'est tout vu, c'est ici :)

Eric.

Avatar
Eric Razny
Le Tue, 24 Jan 2006 03:36:11 +0100, Eric Razny a écrit :

Bonjour.

Un code comme :

byte buf[]=new byte[L_LENGTH];
//[snap] ... buf is filled with raw datas, some parts are UTF-16BE strings
String S=new String(buf, 20, 54, "UTF-16BE");

fonctionne mais est horriblement lent. Le web n'a rien donné, pas plus
qu'une recherche sur usenet (ou alors j'ai tapé avec des mouffles :) )

Quelqu'un aurait une idée pour accélérer le bidule?


Ok j'ai eu une réponse sur le forum anglais alors je la copie ici :

Tout le crédit est à apporter à Chris Uppal.
Accessoirement la solution par StringBuilder ne fonctionne pas car je doit
rester compatible avec la 1.4.2 JVM

...
int charCount = byteCount / 2;
char[] buffer = new char[charCount];
for (int i = 0; i < charCount; i++)
{
byte low = bytes[startByte++];
byte high = bytes[startByte++];
int ch = ((low & 0xFF) << 8 ) | (high & 0xFF); buffer[i] = (char)ch;
}
return new String(buffer);