【问题标题】:Disable Java JIT for a specific method of code segment为代码段的特定方法禁用 Java JIT
【发布时间】:2015-01-24 10:55:57
【问题描述】:

我遇到以下问题。以最简单的方式,我的 Web 应用程序中有一个 servlet 和一个 java 类。现在 java 类遍历列表,对每个元素应用一些逻辑。我还保留一个计数器来跟踪处理的元素。我将计数器值传播到 servlet 可以通过 setter 访问的另一个类。从我的 servlet 中,我执行 AJAX 调用以检索已处理元素的数量并显示进度条。

int counter = 0;
...
for(SecurityForWorkflow securityForWorkflow : newSecuritiesForWorkflow) {
    ...
    WorkflowManager.getInstance().setProcessedSecurities(counter);
    counter++;
    ...
}

问题是进度条不流畅,可能从1到56到100。 我的猜测是,JIT 通过看到没有人访问(获取)计数器并将增量移出循环来以某种方式优化流程。我得出了这个结论,因为调试循环时一切都很顺利(我假设调试时 JIT 无法更改流程)但是当我运行它并将值输出到带有时间戳的日志文件中时,计数器会立即从 0 增加到总值/同时即使你循环运行 20 秒(170 次迭代的情况)。

我的问题是是否可以禁用代码段的 JIT 优化(例如通过注释,但谷歌搜索表明它不是)或者可能通过语言构造/技巧强制非优化(我尝试将变量声明为静态,易失性,将循环放在同步块中,每次在新生成的线程中调用设置器,将设置器放在 try-catch 的 finally 块中,还有一些我现在不记得了,如果我放一个 Thread.sleep 就可以工作(1000)在循环中)。

更新:这是循环的代码

我还用WorkflowManager.getInstance().incProcessedSecurities(); 位更新了WorkflowManager.getInstance().setProcessedSecurities(counter); 结果是一样的

for(SecurityForWorkflow securityForWorkflow : newSecuritiesForWorkflow) {
        ManualInteractionEntity manualInteractionEntity = null;
        BondEntityStatus createdBond = null;
        LegEntity createdLeg = null;
        isin = securityForWorkflow.getIsin();
        try {
          automatedSecurityBuildingStatus = securityBuilder.createBondEntity(
              isin, businessDay);
          if(automatedSecurityBuildingStatus.getBondEntityStatus()
              .getAssetType() != null
              && automatedSecurityBuildingStatus.getBondEntityStatus()
              .getEcbStatus() != null) {
            createdBond = automatedSecurityBuildingStatus.getBondEntityStatus();
          }
          else {
            removeFromSecuritiesForWorkflow.add(securityForWorkflow);
          }
        } catch(Exception e) {
          NabsLogger.getInstance().log(Level.WARNING, String.format("Exception"
              + " when creating security with isin: %s", isin), e);
          continue;
        }finally{
          WorkflowManager.getInstance().incProcessedSecurities();
        }
        try {
          createdLeg = createdBond.getLegEntities().get(0);
        } catch (Exception e) {
          createdLeg = createdBond.getLegEntityStatus();
        }

        if (createdBond.getSetupStatus().equals(
            Constants.MANUAL_INTERACTION_NEEDED)) {
          manualInteractionEntity = new ManualInteractionEntity();
          securityForWorkflow.addStatus(
              SecurityForWorkflow.STATUS_MANUAL_INTERACTION_NEEDED);
          manualInteractionEntity.setId(createdBond.getId());
          manualInteractionEntity.setCreation(true);
          Set<String> manualInteractionFields = automatedSecurityBuildingStatus
              .getManualInteractionRuleResults().keySet();
          manualInteractionEntity.setManualInteractionFields(
              new ArrayList<String>(manualInteractionFields));
          manualInteractionEntities.add(manualInteractionEntity);
        } else if (createdBond.getSetupStatus().equals(
            Constants.CREATED_AUTOMATICALLY)) {
          securityForWorkflow.addStatus(
              SecurityForWorkflow.STATUS_AUTOMATICALLY_BUILT);
        }
        PaymentDateCalculatorModel paymentDateCalculatorModel = 
            new PaymentDateCalculatorModel();
        paymentDateCalculatorModel.setAllDates(createdBond);
        PaymentProfileCalculatorModel paymentProfileCalculatorModel = 
            new PaymentProfileCalculatorModel();
        paymentProfileCalculatorModel.setAllPayments(createdBond);
        entities.add(createdBond);
        legs.add(createdLeg);
       }

谢谢。

【问题讨论】:

  • counter 作为参数传递给setProcessedSecurities 是一种访问,并且不会被优化掉。我不会立即怀疑这里有任何与 JIT 优化相关的东西。这里发生了其他一些事情,涉及到您的 sn-p 中没有的代码。例如。如果有某种线程、事件缓存、高 CPU 负载、其他事情发生,比如说,调试模式下的日志记录为其他事情的发生提供了足够的延迟,这使得问题“似乎”消失了。我 99.999% 确定问题不是你想的那样。您可能需要自己进行一些认真的调试。
  • 如果在 JITtted 时它没有按预期工作,你要么在你正在使用的 VM 中发现了一个错误,要么你的代码有一些线程问题——我强烈怀疑是后者。但是没有足够的代码来清楚地了解哪里出了问题。
  • 也就是说,请参阅stackoverflow.com/questions/4004340/…oracle.com/technetwork/java/javase/tech/…(该页面上也有指向 Java 8 选项的链接)。如果您使用不同的 JVM,请参阅其相关文档以获取相关选项。 stackoverflow.com/questions/7738794/add-jvm-options-in-tomcat 描述了如何通过 Tomcat 设置 JVM 选项。
  • 感谢您的回复。我尝试了link 中提到的选项,但没有帮助,所以我决定重新发布以获取更多信息。 @JasonC 然后我将深入研究代码。这是遗留代码,我绑定到 java6。我的一个猜测是,在它与 Thread.sleep(1000) 一起使用后,它是某种竞争条件。这肯定不是高 CPU 负载,我会检查事件缓存,但相同的代码在放入测试文件(不使用 servlet/进度条)并使用 JUnit 测试时会给出相同的结果。
  • 您可以尝试在循环中打印计数器的值以及时间戳,并将这些值与您从 AJAX 获得的值进行比较。 AJAX 调用可能不像您想象的那样经常实现。另一个需要检查的想法是天气使计数器波动产生影响。

标签: java jit


【解决方案1】:

尝试将计数器设置为volatile 或更好的AtomicInteger

【讨论】:

  • 谢谢,但我都试过了,但都没有解决问题。
猜你喜欢
  • 2011-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多