首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JIT去优化,reason=“约束”。为什么JIT去优化方法?

JIT去优化,reason=“约束”。为什么JIT去优化方法?
EN

Stack Overflow用户
提问于 2021-02-01 23:54:48
回答 2查看 464关注 0票数 5

有人能指点我的方向吗?这可能会让我明白为什么JIT去优化我的循环?(OSR)。看起来它是由C1编译一次,然后再经过多次去优化(我可以看到几十个或上百个以开头的日志)。

这是包含重要循环的类:

代码语言:javascript
复制
@SynchronizationRequired
public class Worker implements Runnable
{
    private static final byte NOT_RUNNING = 0, RUNNING = 1, SHUTDOWN = 2, FORCE_SHUTDOWN = 3;
    private static final AtomicIntegerFieldUpdater<Worker> isRunningFieldUpdater =
            AtomicIntegerFieldUpdater.newUpdater(Worker.class, "isRunning");

    private volatile int isRunning = NOT_RUNNING;

    private final Queue<FunkovConnection> tasks = new SpscUnboundedArrayQueue<>(512);

    /**
     * Executing tasks from queue until closed.
     */
    @Override
    public void run()
    {
        if (isRunning())
        {
            return;
        }

        while (notClosed())
        {
            FunkovConnection connection = tasks.poll();
            if (null != connection)
            {
                connection.run();
            }
        }

        if (forceShutdown())
        {
            setNonRunning();
            return;
        }

        FunkovConnection connection;
        while ((connection = tasks.poll()) != null)
        {
            connection.run();
        }

        setNonRunning();
    }

    public void submit(FunkovConnection connection)
    {
        tasks.add(connection);
    }


    /**
     * Shutdowns worker after it finish processing all pending tasks on its queue
     */
    public void shutdown()
    {
        isRunningFieldUpdater.compareAndSet(this, RUNNING, SHUTDOWN);
    }

    /**
     * Shutdowns worker after it finish currently processing task. Pending tasks on queue are not handled
     */
    public void shutdownForce()
    {
        isRunningFieldUpdater.compareAndSet(this, RUNNING, FORCE_SHUTDOWN);
    }

    private void setNonRunning()
    {
        isRunningFieldUpdater.set(this, NOT_RUNNING);
    }

    private boolean forceShutdown()
    {
        return isRunningFieldUpdater.get(this) == FORCE_SHUTDOWN;
    }

    private boolean isRunning()
    {
        return isRunningFieldUpdater.getAndSet(this, RUNNING) == RUNNING;
    }

    public boolean notClosed()
    {
        return isRunningFieldUpdater.get(this) == RUNNING;
    }
}

JIT日志:

代码语言:javascript
复制
 1. <task_queued compile_id='535' compile_kind='osr' method='Worker run ()V' bytes='81' count='1' backedge_count='60416' iicount='1' osr_bci='8' level='3' stamp='0,145' comment='tiered' hot_count='60416'/>
 2. <nmethod compile_id='535' compile_kind='osr' compiler='c1' level='3' entry='0x00007fabf5514ee0' size='5592' address='0x00007fabf5514c10' relocation_offset='344' insts_offset='720' stub_offset='4432' scopes_data_offset='4704' scopes_pcs_offset='5040' dependencies_offset='5552' nul_chk_table_offset='5560' oops_offset='4624' metadata_offset='4640' method='Worker run ()V' bytes='81' count='1' backedge_count='65742' iicount='1' stamp='0,146'/>
 3. <deoptimized thread='132773' reason='constraint' pc='0x00007fabf5515c24' compile_id='535' compile_kind='osr' compiler='c1' level='3'>
<jvms bci='37' method='Worker run ()V' bytes='81' count='1' backedge_count='68801' iicount='1'/>
</deoptimized>
4. <deoptimized thread='132773' reason='constraint' pc='0x00007fabf5515c24' compile_id='535' compile_kind='osr' compiler='c1' level='3'>
<jvms bci='37' method='Worker run ()V' bytes='81' count='1' backedge_count='76993' iicount='1'/>
</deoptimized>
5.<deoptimized thread='132773' reason='constraint' pc='0x00007fabf5515c24' compile_id='535' compile_kind='osr' compiler='c1' level='3'>
<jvms bci='37' method='Worker run ()V' bytes='81' count='1' backedge_count='85185' iicount='1'/>
</deoptimized>
6. <deoptimized thread='132773' reason='constraint' pc='0x00007fabf5515c24' compile_id='535' compile_kind='osr' compiler='c1' level='3'>
<jvms bci='37' method='Worker run ()V' bytes='81' count='1' backedge_count='93377' iicount='1'/>
</deoptimized>

这里有两个问题:

  1. 去优化的原因是什么?“约束”对我来说似乎没什么意义。
  2. 为什么有这么多关于去优化的日志,而不仅仅是一个日志?它看起来像是编译了一次,但是反编译了多次
EN

回答 2

Stack Overflow用户

发布于 2021-02-02 00:26:15

剧透

这是一张幸运的照片,就像@apangin评论的那样。如果你想知道到底发生了什么,不要浪费时间阅读这个答案。

-回答时我的照片

尽管JIT编译器在某些情况下可能会积极地内联,但它仍然有自己的时间限制,如果这需要大量时间来完成,则不会内联。因此,方法只有在字节码大小小于35字节(默认情况下)时才有资格内联。

在您的示例中,您的方法是大小为81字节的,因此不合格:

<jvms bci='37' method='Worker run ()V' bytes='81' ...

Java性能: Scott的最终指南 是否内联一个方法的基本决定取决于它有多热以及它的大小。JVM根据内部计算确定方法是否热(即频繁调用);它不受任何可调参数的直接影响。如果一个方法因为经常被调用而有资格内联,那么只有当它的字节码大小小于325个字节(或任何被指定为-XX:MaxFreqInlineSize=N标志的方法)时,它才会内联。否则,只有当很小时,它才有资格进行内联:小于35个字节的(或任何被指定为-XX:MaxInlineSize=N标志的东西)。

为了使您的方法成为内联的-XX:MaxInlineSize=N.,可以通过命令行更改内联大小限制,指定

作为一种测试,您可以尝试指定类似-XX:MaxInlineSize=90的内容,以检查这些方法现在是否内联。

给读者--上面的建议“解决了”问题(不是真的固定的)。多么?不知道。我甚至得到了正确的答案,滴答,

附录

(我会让这个看起来很酷)

-- JVM语言的工作负载特性

Aibek S. Lukas S. Lubomír B. Andreas S. Andrej P. Yudi Z. Walter B.

票数 2
EN

Stack Overflow用户

发布于 2021-04-19 15:11:03

最近我在一个aarch64平台上也遇到了同样的问题。一些有趣的发现:

  1. 过度的选择并不总是发生在aarch64上,但是从来没有发生在我测试过的x86机器上;
  2. 这个问题造成了一个巨大的运行到运行的差异(>30%,在我的情况下)之间的过度选择发生和没有发生;
  3. 应用@apagin所述的修补程序后,过度的停用问题就消失了,性能也就稳定了。但是,它低于应用修补程序之前的最高性能。您以前是否检查过修补程序是否会导致性能损失?@apagin。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66001797

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档