【问题标题】:Performance of put() in LinkedBlockingQueueLinkedBlockingQueue 中 put() 的性能
【发布时间】:2012-01-23 15:29:19
【问题描述】:

我正在开发一个股票交易应用程序,它的key 功能是尽可能快地接受来自另一个系统的一些数据(没有阻塞)。然后,我的应用程序将在稍后处理数据。

所以我的想法是让消息在 LinkedBlockingQueue/LinkedTransferQueue 中排队,然后定期排空队列并在后台线程中处理数据。

所以大致如下:

    private final LinkedTransferQueue<Data> queue = new LinkedTransferQueue<Data>();

    public void store( int index, long time, String[] data ) throws InterruptedException{
       Data data = new Data( index, time, data );
       queue.put( data );
    }

    private class BackgroundProcessor implements Runnable{

    private List<Data> entryList = new LinkedList<Data>( );

    @Override
    public void run(){

        try {
            while ( keepProcessing ){

                int count = queue.drainTo( entryList );

                for ( Data data : entryList ){
                //process data
                }
            }
        } catch( Exception e ){
               logger.error("Exception while processing data.", e);
        } 
    }

}

然后我想测试这种方法的性能:

    public void testStore( String[] dataArray ) throws InterruptedException{

        int size = 100 * 1000;

        long iTime = System.nanoTime();
        for ( int i=0; i < size; i++ ){
           store( i, System.nanoTime, dataArray );
        }
        long fTime = System.nanoTime();

        System.err.println("Average Time (nanos): " +   (fTime - iTime)/size;

        float avgTimeInMicros = ((float) (fTime - iTime)/(size * 1000));
        System.err.println("Average Time (micros): " + avgTimeInMicros);
    }

我看到在我的 testStore() 中,如果 size = 100,0000,我可以创建 Data 对象(它是一个不可变对象)并在 0.8 微秒内入队。但是,如果我将尺寸减小到 50,则需要多达 20 微秒。

我假设,一段时间后 jvm 会优化我的代码。 但是,在我的应用程序中,突发获取 50 条数据消息更为现实,有没有办法调整 jvm(或我的代码)以在 1-2 微秒内排队,而不管突发大小如何?

P.S 我在 jdk 1.6 上使用 -mx == -ms 512m 尝试了这个测试。

【问题讨论】:

  • 我不确定您是如何对性能进行计时的,但请确保在开始计时之前您已“启动泵”——这意味着当 JVM 首次加载新类时会浪费时间。与仅测量少量消息相比,此类加载时间很重要。我会让测试运行大约 1,000 次迭代 - 然后模拟你的 50 条消息的爆发。这将确保您的结果不会受到 JVM 启动/类加载的影响。一般来说,确保 Java 中间歇性处理的持续性能时间是一项具有挑战性的任务。
  • 完全同意上述评论。你的是一个天真的微基准。看看 Goetz 的这篇必读文章:ibm.com/developerworks/java/library/j-jtp02225/index.html
  • 谢谢。我现在在插入任何真实数据之前预热队列。因此,随后的 50 条消息会在大约 2 微秒内排队。

标签: java multithreading performance queue put


【解决方案1】:

处理 10,000,然后在 JVM 预热后测试 50 的突发。对于交易系统,您应确保在开始交易之前预热 JVM。

如果您希望您的交易系统始终保持快速,您可以考虑如何在不丢弃任何对象的情况下完成。

您可能会发现 Disruptor 库很有趣。它旨在处理 5 M 消息/秒或更多。 http://code.google.com/p/disruptor/

【讨论】:

  • 嗨,彼得,我已经查看了中断器库及其出色的功能,尽管对于我的特定工作来说这可能是过度杀伤力。你知道它是否有办法不控制生产者吗? (我知道他们有不同的“ClaimStrategy”变体,可以选择等待的方式(锁定、旋转等..)。干杯。
  • 不持有生产者的问题是必须让队列有效增长。通常,大量排队的成本会权衡收益。我解决这个问题的方法是使用可以增长到与磁盘空间一样大的共享内存。如果你有一个快速的磁盘(例如 SSD),你可以在最小的影响下落后数百万条消息。
猜你喜欢
  • 1970-01-01
  • 2013-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-18
  • 2012-08-25
  • 1970-01-01
  • 2021-01-23
相关资源
最近更新 更多