[英]Java multi threading performance worst as increasing thread pool size
我在mongoDB中有4000万个数据。 我正在从集合中并行读取该数据,对其进行处理并将其转储到另一个集合中。
作业初始化的示例代码。
ExecutorService executor = Executors.newFixedThreadPool(10);
int count = total_number_of_records in reading collection
int pageSize = 5000;
int counter = (int) ((count%pageSize==0)?(count/pageSize):(count/pageSize+1));
for (int i = 1; i <= counter; i++) {
Runnable worker = new FinalParallelDataProcessingStrategyOperator(mongoDatabase,vendor,version,importDate,vendorId,i,securitiesId);
executor.execute(worker);
}
每个线程都在做以下事情
public void run() {
try {
List<SecurityTemp> temps = loadDataInBatch();
populateToNewCollection(temps);
populateToAnotherCollection(temps);
} catch (IOException e) {
e.printStackTrace();
}
}
使用以下查询对加载数据进行分页
mongoDB.getCollection("reading_collection").find(whereClause).
.skip(pagesize*(n-1)).limit(pagesize).batchSize(1000).iterator();
机器配置:2个CPU,每个CPU 1个内核
并行实现提供的性能几乎与顺序实现相同。 数据子集的统计信息(319568条记录)
No. of Threads Execution Time(minutes)
1 16
3 15
8 17
10 17
15 16
20 12
50 30
如何提高此应用程序的性能?
由于您是从单一来源读取输入数据,因此该部分很可能是IO绑定的(从您的应用程序的角度来看),因此并行执行它不会带来太多好处。 相反-我认为在多个线程上并行执行类似的查询(只是具有不同的分页)会对性能产生负面影响:同一项工作必须在数据库上执行多次,并且并行查询可能会相互影响方式。
另一个问题是,与读取输入内容相比,处理部分是否要占用大量时间。 如果不使用并行处理,将无助于加快处理速度。 如果可以,我建议以下几点:
至于线程数:最短处理时间的“最佳点”取决于处理的类型。 对于没有大量IO处理的CPU密集型任务,很可能大约是可用内核数-在您的情况下为2。
多线程不会随着线程数量的增加而提高性能。
IO绑定的应用程序不会从多线程中获得太多收益。
这取决于很多因素。 请参考以下相关的SE问题:
即使对于较少的IO绑定,CPU密集型应用程序,也不要配置大量的线程来提高性能。
您可以将代码更改为:
ExecutorService executor = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors());
或(如下所示为ForkJoinPool [从jdk 1.8版本开始运行)
ExecutorService executor = Executors.newWorkStealingPool()
执行器 API:
public static ExecutorService newWorkStealingPool()
使用所有可用处理器作为目标并行性来创建工作窃取线程池
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.