【发布时间】: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