当消息大小很大时,socketchannel.write()变得非常慢

时间:2011-11-07 20:30:10

标签: java nio socketchannel

在我使用java nio的程序中,socketchannel.write()在尝试连续写入10 KB消息时变得非常慢。写入完整10 KB消息的测量时间介于160 ms和200 ms之间。但是编写完整的5 KB消息的时间只需要0.8毫秒。

在选择器中,我只有Selection.OP_READ并且不处理Selection.OP_WRITE。当收到大的完整消息时,它会被写入另一个接收器4次。

有人遇到同样的问题吗?有关于socketchannel.write()的帖子很慢。我的问题是如何在OP_READ和OP_WRITE之间进行替换?

如果我添加一个例如150毫秒的inerval,则响应时间会减少。有什么方法可以找到缓冲区已满的时间,所以我可以让程序等待。我的操作系统是windows xp。

感谢。

我通过检查写入的字节数来遵循EPJ的建议。但响应时间仍然很长。我在这里发布了部分代码,并想检查我的代码是否有问题。

//这是使用nio的writeData()部分:

      while (buffer.hasRemaining()) {   
        try {           
                buffer.flip();                  
                n = socket.write(buffer);           
                if(n == 0) {                
                    key.interestOps(SelectionKey.OP_WRITE);
                    key.attach(buffer);             
                    break;
                }                               
        } catch (IOException e) {               
            e.printStackTrace();
        } finally {
            buffer.compact();
        }
    }   

    if(buffer.position()==0) {                  
        key.interestOps(SelectionKey.OP_READ);
    }

2 个答案:

答案 0 :(得分:3)

我建议您的阅读过程很慢,这会导致其接收缓冲区备份,这会导致您的发送缓冲区备份,从而导致您的发送停止。

否则您还没有为非阻塞模式正确编写代码。如果从write()方法得到零结果,则必须(a)将interestOps更改为OP_WRITE并(b)返回到select循环。当你得到OP_WRITE时,你必须重复写;如果您编写了所有数据,请将interestOps更改回OP_READ,否则保留所有内容并等待下一个OP_WRITE。如果你在非阻塞模式下写入时尝试循环,即使存在零长度写入,你也会旋转,浪费CPU周期和时间。

Modulo错误:

while (buffer.position() > 0)
{
  try
  {
    buffer.flip();
    int count = ch.write(buffer);
    if (count == 0)
    {
      key.interestOps(SelectionKey.OP_WRITE);
      break;
    }
  }
  finally
  {
    buffer.compact();
  }
}
if (buffer.position() == 0)
{
  key.interestOps(SelectionKey.OP_READ);
}

答案 1 :(得分:2)

如果写入超过20微秒,我建议你有一个缓冲区问题。我假设您正在使用阻止NIO。当发送缓冲区未满时,通常需要5到20微秒。在过去,我已经配置我的服务器来杀死任何需要2毫秒写入的慢速消费者。 (可能有点咄咄逼人。;)

您可以尝试增加发送缓冲区的大小(Socket.setSendBufferSize(int),也可用于SocketChannels),但看起来您尝试发送的数据超出了带宽允许的范围。

10 KB不是一个大消息,典型的发送缓冲区大小是64 KB,因此要使其满,您需要有6-7个消息未发送。这可能解释了5KB相对较快的方式。