【问题标题】:Increase CPU utilization using parallel stream for DB intensive task为 DB 密集型任务使用并行流提高 CPU 利用率
【发布时间】:2017-07-19 06:26:27
【问题描述】:

我正在使用 java 8 并行流将数据插入数据库。 以下是代码

customers.parallelStream().forEach(t->{

        UserTransaction userTransaction = new UserTransactionImp();
        try {
            userTransaction.begin();
            userTransaction.setTransactionTimeout(300);
            //CODE to write data to DB for each customer in a global transaction using atomikos and hibernate
            userTransaction.commit();
        }catch(Exception e){
            userTransaction.rollback();
        }
    });

完成任务需要2个多小时。我在两个不同的实例(两个java主要方法)中运行了相同的测试。完成所需的时间降至1小时。有没有其他方法可以扩大规模在一个 java 实例中。我正在使用 Atomikos,Hibernate 进行持久性。我已经配置了批处理,插入排序和更新排序。Evrything 已正确批处理并且工作正常。 但我观察到在此期间 CPU 的使用率没有超过 30%。有什么办法可以利用更多的处理器并扩大规模。

【问题讨论】:

  • 您是否使用了连接池,以便它们在与数据库通信时不会相互阻塞?您在填充数据库时使用的任何其他可能导致线程相互阻塞的共享资源?
  • 您还应该知道,使用并行流有一些注意事项,尤其是在它们上运行 I/O 代码时。 dzone.com/articles/think-twice-using-java-8
  • 尝试使用自定义 ForkJoinPool 来运行并行流并调整线程数。
  • 我使用了自定义 ForkJoinPool 。结果还是一样
  • 是的,我正在使用连接池。

标签: java database oracle java-stream atomikos


【解决方案1】:

parallelStream() 基本上为您提供了“默认”实现。我曾经听一个人说:“每当你使用这个构造时,都要测量它的效果”。

换句话说:当您对默认实现不满意时,您可能需要查看您的自己的实现。关注的不是单一的操作,而是“全貌”。

示例:如果每个“镜头”将 5、10、50 个“用户”“标记”在一起会怎样 - 意思是:您减少了交易数量,但允许更多内容进入每个“镜头”。

是的,这是一个非常笼统的答案 - 但这是一个非常笼统的问题。我们完全不知道您的代码在那里做什么 - 所以这里没有人能说出什么是减少整体运行时间的“完美”方式。

除此之外:您想要配置您的整个设置。也许你的问题不是“java”部分——而是你的数据库。内存不够,工作量太大……或者网络,或者,或者,或者。换句话说:首先专注于了解您的性能瓶颈真正存在的地方。

(关于“性能”和瓶颈的好读物:Michael Nygard 的经典“Release it”)

【讨论】:

  • 问题似乎是atomikos。它占用了超过 80% 的执行时间
猜你喜欢
  • 1970-01-01
  • 2015-10-22
  • 2013-08-26
  • 2014-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多