java - Groovy ASTBuilder 多线程性能不佳
问题描述
我在一个项目中使用 Groovy 的 ASTBuilder(版本 2.5.5)。它用于解析和分析通过 REST API 接收到的 groovy 表达式。此 REST 服务接收数千个请求,并即时完成分析。
我注意到多线程环境中存在一些严重的性能问题。下面是一个模拟,并行运行 100 个线程:
int numthreads = 100;
final Callable<Void> task = () -> {
long initial = System.currentTimeInMillis();
// Simple rule
new AstBuilder().buildFromString("a+b");
System.out.print(String.format("\n\nThread took %s ms.",
System.currentTimeInMillis() - initial));
return null;
};
final ExecutorService executorService = Executors.newFixedThreadPool(numthreads);
final List<Callable<Void>> tasks = new ArrayList<>();
while (numthreads-- > 0) {
tasks.add(task);
}
for (Future<Void> future : executorService.invokeAll(tasks)) {
future.get();
}
我尝试使用不同的线程负载。数字越大,速度越慢。
- 100 个线程 => ~1800 毫秒
- 200 个线程 => ~2500ms
- 300 个线程 => ~4000 毫秒
但是,如果我对线程进行序列化(例如将池大小设置为 1),我会得到更好的结果,每个线程大约 10 毫秒。有人可以帮我理解为什么会这样吗?
解决方案
执行多线程代码,计算机在物理 CPU 内核之间共享线程。这意味着线程数超过内核数越多,您从每个线程中获得的收益就越少。在您的示例中,线程数随着任务数的增加而增加。因此,随着任务数量的增加,每个 CPU 内核都被迫处理越来越多的线程。同时,您可能会注意到numthreads = 1
和之间的差异numthreads = 4
非常小。因为在这种情况下,每个核心只处理少数(甚至只是一个)线程。不要将线程数设置为多于物理 CPU 线程数,因为这没有多大意义。
此外,在您的示例中,您试图比较不同数量的线程如何执行不同数量的任务。但是为了查看多线程代码的效率,您必须比较不同数量的线程在相同数量的任务下的执行情况。我将通过以下方式更改示例:
int threadNumber = 16;
int taskNumber = 200;
//...task method
final ExecutorService executorService = Executors.newFixedThreadPool(threadNumber);
final List<Callable<Void>> tasks = new ArrayList<>();
while (taskNumber-- > 0) {
tasks.add(task);
}
long start = System.currentTimeMillis();
for (Future<Void> future : executorService.invokeAll(tasks)) {
future.get();
}
long end = System.currentTimeMillis() - start;
System.out.println(end);
executorService.shutdown();
试试这个代码threadNumber=1
,让我们说,threadNumber=16
你会看到不同之处。
推荐阅读
- c - 为什么我们需要 int *ptr = NULL;?
- mapbox - 如何在地图框图层中显示堆叠位置?
- python - 无法单击 iframe 中的下拉菜单 - Selenium Python
- projection - 在 EventStore Projection 中没有得到任何结果
- node.js - app.use(express.static("public")) 如何处理嵌套 URL?
- java - 通过以 5 为增量读取来创建一个对象(来自我们的一个类)
- android-studio - 如何在文本上添加笔画
- javascript - 为什么在 5 和 50 之间打印所有可被 3 和 5 整除的数字的这两种解决方案都有效?
- c# - 在 Webview Renderer 中处理自定义事件
- sql - Oracle中缺少右括号问题