- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试了解如何正确使用 Java 的执行器。我意识到将任务提交给 ExecutorService
有其自身的开销。但是,我很惊讶地看到它竟然这么高。
我的程序需要以尽可能低的延迟处理大量数据(股票市场数据)。大多数计算都是相当简单的算术运算。
我试图测试一些非常简单的东西:“Math.random() * Math.random()
”
最简单的测试在一个简单的循环中运行这个计算。第二个测试在匿名 Runnable 中进行相同的计算(这应该衡量创建新对象的成本)。第三个测试将 Runnable
传递给 ExecutorService
(这衡量了引入执行程序的成本)。
我在我的小笔记本电脑(2 个 cpu,1.5 gig ram)上运行了测试:
(in milliseconds)
simpleCompuation:47
computationWithObjCreation:62
computationWithObjCreationAndExecutors:422
(大约每四次运行一次,前两个数字最终相等)
请注意,执行器比在单个线程上执行花费的时间要多得多。对于 1 到 8 之间的线程池大小,数字大致相同。
问题:我是否漏掉了一些明显的东西,或者这些结果是否符合预期?这些结果告诉我,我传递给执行者的任何任务都必须进行一些重要的计算。如果我正在处理数百万条消息,并且我需要对每条消息执行非常简单(且成本低廉)的转换,我仍然可能无法使用执行器......尝试将计算分散到多个 CPU 上最终可能比仅在一个线程中完成它们。设计决策变得比我原先想象的要复杂得多。有什么想法吗?
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ExecServicePerformance {
private static int count = 100000;
public static void main(String[] args) throws InterruptedException {
//warmup
simpleCompuation();
computationWithObjCreation();
computationWithObjCreationAndExecutors();
long start = System.currentTimeMillis();
simpleCompuation();
long stop = System.currentTimeMillis();
System.out.println("simpleCompuation:"+(stop-start));
start = System.currentTimeMillis();
computationWithObjCreation();
stop = System.currentTimeMillis();
System.out.println("computationWithObjCreation:"+(stop-start));
start = System.currentTimeMillis();
computationWithObjCreationAndExecutors();
stop = System.currentTimeMillis();
System.out.println("computationWithObjCreationAndExecutors:"+(stop-start));
}
private static void computationWithObjCreation() {
for(int i=0;i<count;i++){
new Runnable(){
@Override
public void run() {
double x = Math.random()*Math.random();
}
}.run();
}
}
private static void simpleCompuation() {
for(int i=0;i<count;i++){
double x = Math.random()*Math.random();
}
}
private static void computationWithObjCreationAndExecutors()
throws InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(1);
for(int i=0;i<count;i++){
es.submit(new Runnable() {
@Override
public void run() {
double x = Math.random()*Math.random();
}
});
}
es.shutdown();
es.awaitTermination(10, TimeUnit.SECONDS);
}
}
最佳答案
编辑:我更改了您的示例,让它在我的小型双核 x200 笔记本电脑上运行。
provisioned 2 batches to be executed
simpleCompuation:14
computationWithObjCreation:17
computationWithObjCreationAndExecutors:9
如您在源代码中所见,我也将批处理配置和执行程序生命周期排除在测量之外。与其他两种方法相比,这更公平。
自己看结果...
import java.util.List;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ExecServicePerformance {
private static int count = 100000;
public static void main( String[] args ) throws InterruptedException {
final int cpus = Runtime.getRuntime().availableProcessors();
final ExecutorService es = Executors.newFixedThreadPool( cpus );
final Vector< Batch > batches = new Vector< Batch >( cpus );
final int batchComputations = count / cpus;
for ( int i = 0; i < cpus; i++ ) {
batches.add( new Batch( batchComputations ) );
}
System.out.println( "provisioned " + cpus + " batches to be executed" );
// warmup
simpleCompuation();
computationWithObjCreation();
computationWithObjCreationAndExecutors( es, batches );
long start = System.currentTimeMillis();
simpleCompuation();
long stop = System.currentTimeMillis();
System.out.println( "simpleCompuation:" + ( stop - start ) );
start = System.currentTimeMillis();
computationWithObjCreation();
stop = System.currentTimeMillis();
System.out.println( "computationWithObjCreation:" + ( stop - start ) );
// Executor
start = System.currentTimeMillis();
computationWithObjCreationAndExecutors( es, batches );
es.shutdown();
es.awaitTermination( 10, TimeUnit.SECONDS );
// Note: Executor#shutdown() and Executor#awaitTermination() requires
// some extra time. But the result should still be clear.
stop = System.currentTimeMillis();
System.out.println( "computationWithObjCreationAndExecutors:"
+ ( stop - start ) );
}
private static void computationWithObjCreation() {
for ( int i = 0; i < count; i++ ) {
new Runnable() {
@Override
public void run() {
double x = Math.random() * Math.random();
}
}.run();
}
}
private static void simpleCompuation() {
for ( int i = 0; i < count; i++ ) {
double x = Math.random() * Math.random();
}
}
private static void computationWithObjCreationAndExecutors(
ExecutorService es, List< Batch > batches )
throws InterruptedException {
for ( Batch batch : batches ) {
es.submit( batch );
}
}
private static class Batch implements Runnable {
private final int computations;
public Batch( final int computations ) {
this.computations = computations;
}
@Override
public void run() {
int countdown = computations;
while ( countdown-- > -1 ) {
double x = Math.random() * Math.random();
}
}
}
}
关于java - ExecutorService 令人惊讶的性能盈亏平衡点——经验法则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1647990/
我正在为一个类(class)项目制作一个 C# 应用程序。我想确保一个字符串具有三个值之一。通常,在网络应用程序中,我会在客户端使用 javascript 进行验证。但是,这目前是一个控制台应用程序。
我注意到了 int i=10000000; boolean isPrime= false; while(!isPrime){ i++; Syst
一般来说,类构造函数应该接受的最大参数数量是多少?我正在开发一个需要大量初始化数据(目前有 10 个参数)的类。但是,带有 10 个参数的构造函数感觉不对。这让我相信我应该为每条数据创建一个 gett
改善网页加载时间的一种方法是内联其 css - 因为 css 会阻塞渲染。但是,内联 css 会阻止浏览器缓存它。因此,一般建议仅内联“小”css。 但是什么才算“小”呢?我在网上搜索了一些经验法则,
我正在尝试了解如何正确使用 Java 的执行器。我意识到将任务提交给 ExecutorService 有其自身的开销。但是,我很惊讶地看到它竟然这么高。 我的程序需要以尽可能低的延迟处理大量数据(股票
我读过几篇 GWT 开发人员博客,其中提到了一些“经验法则”,即如果生成的 JavaScript 代码达到 100 行或更多,最好自己编写 JavaScript(而不是通过 GWT 生成它) . 我的
最近我偶然发现了一个非常大的性能改进——我说的是 4 倍的改进——只需更改一行代码。我刚刚将 std::sort 调用更改为 concurrency_parallel 排序 // Get a cont
我在 javascript 中使用 setTimeout() 函数来允许在解析一些 xml 数据时显示一个显示“正在加载”的弹出窗口。我发现,在足够小的延迟值(低于 10 毫秒)下,在浏览器卡住一段时
Leonid 在他的书的第四章中写道:“...Module、Block 和 With。这些结构在 Mathematica Book 和 Mathematica Help 中有详细解释,所以我在这里简单
我是一名优秀的程序员,十分优秀!