在 JRuby 分析中花费大量时间在 Thread#initialize 和 Thread#join 中意味着啥?

Posted

技术标签:

【中文标题】在 JRuby 分析中花费大量时间在 Thread#initialize 和 Thread#join 中意味着啥?【英文标题】:What do large times spent in Thread#initialize and Thread#join mean in JRuby profiling?在 JRuby 分析中花费大量时间在 Thread#initialize 和 Thread#join 中意味着什么? 【发布时间】:2013-02-16 04:07:54 【问题描述】:

我正在尝试使用 JRuby 的内置分析器来分析应用程序。

大部分时间花在ClassIsOfInterest.method_that_is_of_interest,而大部分时间花在Thread#initializeThread#join

     total        self    children       calls  method
----------------------------------------------------------------
     31.36        0.02       31.35        4525  Array#each
     31.06        0.00       31.06           2  Test::Unit::RunCount.run_once
     31.06        0.00       31.06           1  Test::Unit::RunCount.run
     31.06        0.00       31.06           1  MiniTest::Unit#run
     31.06        0.00       31.05           1  MiniTest::Unit#_run
     31.01        0.00       31.01        2219  Kernel.send
     31.00        0.00       31.00           1  MiniTest::Unit#run_tests
     31.00        0.00       31.00           1  MiniTest::Unit#_run_anything
     30.99        0.00       30.99           1  Test::Unit::Runner#_run_suites
     30.99        0.00       30.99           5  MiniTest::Unit#_run_suite
     30.99        0.00       30.98       21629  Array#map
     30.98        0.00       30.98           1  Test::Unit::TestCase#run
     30.98        0.00       30.98           1  MiniTest::Unit::TestCase#run
     30.98        0.00       30.98         659  BasicObject#__send__
     30.98        0.00       30.98           1  MyTestClass#my_test_method
     30.80        0.00       30.80          18  Enumerable.each_with_index
     30.77        0.00       30.77          15  MyTestHelper.generate_call_parser_based_on_barcoded_sequence
     30.26        0.00       30.25        4943  Class#new_proxy
     26.13        0.00       26.13          15  MyProductionClass1#my_production_method1

<snip boring methods with zero self time>

     24.27        0.00       24.27          15  ClassIsOfInterest.method_that_is_of_interest
     13.71        0.01       13.71         541  Enumerable.map
     13.48        0.86       12.63          30  Range#each
     12.62        0.22       12.41         450  Thread.new
     12.41       12.41        0.00         450  Thread#initialize
     10.78       10.78        0.00         450  Thread#join
      4.03        0.12        3.91         539  Kernel.require
      3.34        0.00        3.34         248  Kernel.require
      2.49        0.00        2.49          15  MyTestFixture.create_fixture

<snip boring methods with small total times>

ClassIsOfInterest.method_that_is_of_interest 的每次调用都会创建 30 个线程,这可能有点过头了,但我认为它不会降低性能。当我每次调用只创建三个线程时,我得到了

 23.16        0.00       23.15          15  ClassIsOfInterest.method_that_is_of_interest
 22.73       22.73        0.00          45  Thread#join
  4.18        0.08        4.10         539  Kernel.require
  3.56        0.00        3.56         248  Kernel.require
  2.78        0.00        2.78          15  MyTestFixture.create_fixture

Thread#initialize(在第一个配置文件中)和Thread#join 的大时间值是否表明负责线程化的代码需要一段时间,或者仅仅是线程内执行的代码需要一段时间?

【问题讨论】:

【参考方案1】:

您看到Thread#join 的原因是您的主线程正在花费大量时间等待其他线程完成。在method_that_is_of_interest 上花费的大部分时间都花在阻止Thread#join 上,因为它没有做任何其他工作。我不会太担心——配置文件只是说你的一个线程阻塞了其他线程正在做的事情。在这种情况下,更好的性能测量是总运行时间,使用不同数量的线程运行代码并查看最佳点在哪里。

Thread.new/Thread#initialize 出现的原因是线程是昂贵的创建对象。如果您经常调用此方法并且每次都会创建所有这些线程,我建议您查看 Java 的 Executors API。使用Executors 创建一个线程池一次(当您的应用程序启动时)并将所有任务提交到池中而不是创建新线程(您可以使用ExecutorCompletionService 等待所有任务完成,或者只调用#get在您提交任务时获得的FutureTask 实例上)。

【讨论】:

以上是关于在 JRuby 分析中花费大量时间在 Thread#initialize 和 Thread#join 中意味着啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何分析 JRuby 代码?

在大量查询结果的循环中,更新操作花费了奇怪的时间

在性别字段的 posgresdb 中过滤花费大量时间

在 EF6 中执行 StoredProcedure 需要花费大量时间

在 EF6 中执行 StoredProcedure 需要花费大量时间

dev-server 花费大量时间在 webpack 4 中重建项目