是否有任何性能问题将ByteBuffer分配给一个位置?

时间:2013-12-16 12:12:43

标签: java performance nio

我想知道是否存在与从AsynchronousSocketChannel读取一个字节有关的任何性能问题。我正在实现一个简单的HTTP服务器并解析我需要每字节读取字节的请求:

    ByteBuffer dst = ByteBuffer.allocate(1);

    int end = 0;

    int br = 0;
    int bread = 0;

    StringBuilder sb = new StringBuilder();

    while(bread < RCV_BUF){

        br = client.read(dst).get();

        //End of stream and nothing :(
        if(br == 0){
            return null;
        }

        dst.flip();

        bread += br;

        byte b = dst.get();

        dst.clear();

        if((end == 0 && b == '\r') || (end == 1 && b == '\n') || (end == 2 && b == '\r')){
            end++;
        }
        else 
            if(end == 3 && b == '\n'){
                break;
            }
            else
            {
                end = 0;
            }

        sb.append((char)b);

    }

Java专家可以解释一下,如果这种做法在性能方面有差异吗?

2 个答案:

答案 0 :(得分:2)

通常,您会尝试尽可能多地将字节读入缓冲区。这显着提高了效率:ByteBuffers针对大顺序字节块的读写进行了高度优化。

但是,您仍然可以使ByteBuffers的缓冲区大小为1。如果字节读取的数量很小(比如每秒100,000字节或更少),那么我怀疑它会产生明显的差异。您的代码看起来很适合处理那种卷。与往常一样,如果您认为这是一个真正的问题,您应该进行基准测试,但如果代码已经足够快以满足您的需求,那么优化代码就没什么意义了。

但更严重的是,我会质疑为什么你要写这种代码?为什么不使用经过良好测试的库(例如Netty),它应该为你做所有这些事情?

答案 1 :(得分:0)

嘛!我找到了一种更有效的方法来解决这个问题!我分配了最小尺寸的ByteBuffer!糟糕的是我在解析器中引入了一些复杂性。但无论如何......

    int RCV_BUF = client.getOption(StandardSocketOptions.SO_RCVBUF);

    ByteBuffer dst = ByteBuffer.allocate(256);

    int end = 0;

    int br = 0;
    int bread = 0;

    StringBuilder sb = new StringBuilder();

    boolean endr = false;
    boolean cr = false;

    //Try parse headers
    while(!endr && bread < RCV_BUF){

        br = client.read(dst).get();

        //End of stream and nothing :(
        if(br == 0){
            return null;
        }

        dst.flip();

        bread += br;

        while(dst.hasRemaining()){

            byte b = dst.get();

            if(end == 0 && b == '\r'){      
                end++;
                continue;
            }

            // Possible header...
            if(end == 1){

                      // We got a header!
                if(b == '\n'){

                    // Reached the end of headers!
                    if(cr){
                        endr = true;
                        break;
                    }

                    cr = true;

                    end = 0;

                    System.out.println(sb.toString());

                    sb = new StringBuilder();

                    continue;
                }

                //Bad request (send a 400 status code...)!
                return null;
            }

            if(cr){
                cr = false;
            }

            sb.append((char)b);

        }

        dst.clear();

    }