2011-11-29 37 views
2

我正在从事涉及从套接字交易报价读取的任务,并且我需要实现最小延迟和高吞吐量。如何从使用Java的套接字高效地读取NIO

我开始与simpliest可能的Java NIO原型这样

ByteBuffer buf = ByteBuffer.allocateDirect(BUFFER_SIZE); 
try { 
     buf.clear(); 
     int numBytesRead = socketChannel.read(buf); 

     if (numBytesRead == -1) { 
      socketChannel.close(); 
     } else { 
      buf.flip(); 
      byte[] byteArrived = new byte[buf.remaining]; 
      buf.get(byteArrived,0,byteArrived.length); 
      // here we send byteArrived to the parser 
     } 
    } catch (IOException e) {  
} 

我猜它是瘸子每次创建byte []数组,但由于缺乏知识,我不知道如何解析的ByteBuffer (因为我需要将字节协议解组成消息并传递给业务逻辑)。你能推荐如何避免大量垃圾产生?

另外我想问一下最佳实践如何组织套接字读取低延迟和高吞吐量?我阅读了LMAX和破解框架,他们在单线程上实现了6M交易。

回答

4

您可以使用Disruptor和其他方法实现更高的性能。很大程度上取决于消息的大小和复杂性(以及对消息做什么!!)

如果要使用ByteBuffer序列化/反序列化,请使用putXxxx和getXxxx方法。为了使这个过程更容易,我建议先将每条消息的长度放在第一位,以便在尝试解析它之前检查是否有完整的消息。

您可能会发现这个有趣的演示http://vanillajava.blogspot.com/2011/11/low-latency-slides.html

+0

消息非常简单,12个字节或27个字节长。 –

+0

在这种情况下,您可以获得250Kmsg/s至40M msg/s,具体取决于您是想要最低延迟(低至5 us)还是最高吞吐量(但有25 us延迟)。当然,这一切都必须来自某个地方,去某个地方。除非您有需求并且您的消费者可以快速处理消息,否则没有必要担心。 –

+0

建议 - 将长度设置为第一个字段,并记住从套接字读取单个消息可能会传递多个消息以及部分消息。其他要考虑的事情:a)实例化缓冲区一次b)创建包装byte []的对象池并提供bean样式的访问器/其他方法(然后序列化/反序列化就像在IO缓冲区和对象内部数组之间复制字节一样简单) –

1

假设你可以调整你的解析器API接受(byte[] buffer, int offset, int length)作为参数,你可以通过(bb.array(), 0, bb.limit())作为参数,而不必创建new byte[]在所有的每读。然而,这不可能是决定速度的一步。