Avatar billede dsj Nybegynder
02. januar 2004 - 17:09 Der er 6 kommentarer og
1 løsning

Performance: Skrive String til SocketChannel

Hvordan kommer man hurtigst (mindst CPU-tid) fra:

String output = "...";

til

SocketChannel.write(ByteBuffer);

Altså hvordan konverterer man mest effektivt en String til noget en SocketChannel kan skrive; en ByteBuffer...
Avatar billede dsj Nybegynder
02. januar 2004 - 17:47 #1
Scenariet er i øvrigt en server med mange længere levende klienter, der hver har tildelt en direct ByteBuffer, som genbruges til klienten dør.
Avatar billede arne_v Ekspert
03. januar 2004 - 21:36 #2
Et gæt (jeg har ikke arbejdet seriøst med nio):

String s;
ByteBuffer bb = ByteBuffer.wrap(s.getBytes());
Avatar billede dsj Nybegynder
04. januar 2004 - 00:25 #3
Den har jeg også tænkt på, men wrap opretter hver gang en ny ByteBuffer, der ikke er direct, og derfor vil være genstand for garbage collection.
Avatar billede arne_v Ekspert
04. januar 2004 - 00:51 #4
bb.clear();
bb.put(s.getBytes());

så ?
Avatar billede arne_v Ekspert
04. januar 2004 - 01:05 #5
import java.nio.ByteBuffer;

public class ByteBufferTest {
    private final static int N = 10000000;
    private final static String s = "Dette er en test";
    private static void test1() {
        ByteBuffer bb = null;
        long t1 = System.currentTimeMillis();
        for(int i = 0; i < N; i++) {
            bb = ByteBuffer.wrap(s.getBytes());
        }
        long t2 = System.currentTimeMillis();
        bb.rewind();
        if(bb.limit() != s.length()) System.out.println("Oops");
        for(int i = 0; i < bb.limit(); i++) if(bb.get() != s.charAt(i)) System.out.println("oops");
        System.out.println("wrap: " + (t2-t1));
    }
    private static void test2() {
        ByteBuffer bb = ByteBuffer.allocate(s.length());
        long t1 = System.currentTimeMillis();
        for(int i = 0; i < N; i++) {
            bb.clear();
            bb.put(s.getBytes());
        }
        long t2 = System.currentTimeMillis();
        bb.rewind();
        if(bb.limit() != s.length()) System.out.println("Oops");
        for(int i = 0; i < bb.limit(); i++) if(bb.get() != s.charAt(i)) System.out.println("oops");
        System.out.println("clear and put: " + (t2-t1));
    }
    public static void main(String[] args) {
        test1();
        test2();
    }
}

giver:

wrap: 32266
clear and put: 32703

på min PC => ingen forskel.
Avatar billede dsj Nybegynder
04. januar 2004 - 02:17 #6
Pt. gør jeg sådan:

writeBuf = ByteBuffer.allocateDirect(65536);
...
writeBuf.put(out.getBytes());
writeBuf.flip();
while (writeBuf.hasRemaining()) {
  channel.write(writeBuf);
}
writeBuf.clear();

Husk at ByteBufferen skal oprettes som direct for at vinde performance ved genbrug af bufferen. Det jeg allerede gør ser ud til at være en anelse hurtigere end wrap. Det jeg mest tænkte på var, om der var andre måder at gøre det på, f.eks. ved at bruge en direct CharBuffer (ByteBuffer.asCharBuffer). Det dyre i denne operation er helt klar String.getBytes(), da den skal encode en hel masse. Det jeg derfor er ude efter, er om muligt en mere effektiv måde at konvertere en String noget et byte-array.
Avatar billede dsj Nybegynder
07. januar 2004 - 20:51 #7
Lukker.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester