[java] InputStream, altijd byte-voor-byte volgens spec?

Pagina: 1
Acties:

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Ik zit net de specs van de verschillende java.io.* classes eens in detail te bekijken, en zie dat java.io.InputStream altijd byte-voor-byte leest, zelfs als je read(byte[]) aanroept:

The read(b) method for class InputStream has the same effect as:
read(b, 0, b.length)

en

The read(b, off, len) method for class InputStream simply calls the method read() repeatedly. If the first such call results in an IOException, that exception is returned from the call to the read(b, off, len) method. If any subsequent call to read() results in a IOException, the exception is caught and treated as if it were end of file; the bytes read up to that point are stored into b and the number of bytes read before the exception occurred is returned. Subclasses are encouraged to provide a more efficient implementation of this method.

Ik zit met een paar apps met aardig wat socket overhead (na profilen), en vraag me na het lezen van dit statement af hoe sockets dan ooit snel kunnen werken onder Java? Ik was in de veronderstelling dat Java's InputStream.read(byte[]) ook daadwerkelijk meerdere bytes tegelijk (native) kon lezen.

Verwijderd

nou, ik weet niet of je al meteen kunt roepen dat byte voor byte van native naar Java verplaatsen voor langzamer communicatie zorgt dan het verplaatsen van een stream in één keer.

Maar ik heb even in de source code van Java (Sun J2SE 1.4.2) gekeken en daar bleek dat de InputStream van sockets (SocketInputStream.class) juist wel data in blokken aan de native side vraagt.

Er wordt gebruik gemaakt van de method SocketInputStream.socketRead0(...) en dit is de commentaar die erbij staat:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    /** 
     * Reads into an array of bytes at the specified offset using
     * the received socket primitive. 
     * @param fd the FileDescriptor
     * @param b the buffer into which the data is read
     * @param off the start offset of the data
     * @param len the maximum number of bytes read
     * @param timeout the read timeout in ms
     * @return the actual number of bytes read, -1 is
     *          returned when the end of the stream is reached. 
     * @exception IOException If an I/O error has occurred.
     */
    private native int socketRead0(FileDescriptor fd, 
                       byte b[], int off, int len,
                   int timeout)
    throws IOException;


En ook de InputStream voor files (FileInputStream.class) bezit een native method voor het inlezen van een byte array:

code:
1
2
3
4
5
6
7
8
    /**
     * Reads a subarray as a sequence of bytes.
     * @param b the data to be written
     * @param off the start offset in the data
     * @param len the number of bytes that are written
     * @exception IOException If an I/O error has occurred.
     */
    private native int readBytes(byte b[], int off, int len) throws IOException;

[ Voor 21% gewijzigd door Verwijderd op 03-07-2003 03:35 ]


  • B-Man
  • Registratie: Februari 2000
  • Niet online
Hmmm, dat zou dan betekenen dat er standaard al wel buffering in de Java classes zit (native), aangezien InputStream toch echt enkel byte-voor-byte leest. Als de native functies die erachter zitten wel blokken bytes kunnen lezen, moet er dus een buffer tussenin zitten.

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
Yep. Ik heb hier een NIO server en die native calls zijn echt direct naar API spul. Op m'n Celeron 400 kan ik 900 clients aan die elk gemiddeld 1 message opsturen en aan elke andere doorsturen. Zeker voor socket spul NIO gebruiken dus (ook maar 1 / 2 threads nodig). Met de gewone oude API plafonneerd ie al met 120 clients (en dat is met 100% cpu usage terwijl de andere max 40% - hij 'crasht' in het eerste geval in de Windowz API (gewoon teveel data - dus de sockets worden gekillt))...

  • Swinnio
  • Registratie: Maart 2001
  • Laatst online: 18-08 09:00
Het is zeker wel mogelijk meerdere bytes tegelijk in te lezen, weet alleen niet waar en hoe de buffering dan precies werkt. Deze code gebruik ik momenteel bijv. om een byte array in te lezen:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
try {
                in = socket.getInputStream();
                out = socket.getOutputStream();
                
                byte[] data = new byte[150];
                int num = 0;                
                              
                while ((num = in.read(data)) != -1) {
                    readPckt(data, num);
                }                
                
                System.out.println("Connection " + name + " will be terminated");
                
                if (debug) System.out.println("Closing socket...");
                socket.close();
                
            }

If the world wouldn't suck, we'd all fall off


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
als je met NIO / channels werkt lees je bijna altijd meer dan per byte in - meestal gewoon de hele message in 1 go. Nog een reden om de oude sockets niet meer te gebruiken.
Pagina: 1