是否有人使用JIT技巧来提高静态编译的语言(例如C ++)的运行时性能?似乎基于运行时的观察结果的热点分析和分支预测可以提高任何代码的性能,但是也许只有在虚拟机中才有可能在运行时进行此类观察和实施变化的基本战略原因。我清楚地记得偷听C ++编译器作家喃喃自语“您可以为C ++编写的程序做到这一点”,同时听取动态语言爱好者谈论收集统计数据和重新安排代码,但我的网络搜索以支持这种记忆的证据已经变得枯竭。

有帮助吗?

解决方案

配置文件指导优化与运行时优化不同。基于分析信息,仍在离线进行优化,但是一旦二进制运输,就不会进行持续的优化,因此,如果配置文件引导的优化阶段的使用模式不能准确反映现实世界的使用情况不完美,该程序也不会适应不同的使用模式。

您可能很有趣 惠普的发电机, ,尽管该系统集中在本地二进制 - >本地二进制翻译上,尽管由于C ++几乎完全编译为本机代码,但我想这正是您要寻找的。

您可能还想看看 LLVM, ,这是一个支持JIT编译和运行时优化的编译器框架和中间表示,尽管我不确定实际上是否有任何基于LLVM的运行时间可以编译C ++并执行+运行时优化它。

其他提示

在过去的几年中,我做了很多优化。它是我实施的图形渲染API。由于API将几千种不同的图形模式定义为通用函数,因此可以放慢速度。

我最终为特定于域的语言写了自己的小型JIT编译器(非常接近ASM,但带有一些高级控制结构和局部变量)。

我得到的性能提高在第10到60元之间(取决于编译代码的复杂性),因此额外的工作充分回报了。

在PC上,我不会开始编写自己的JIT编译器,而是使用libjit或llvm进行JIT编译。在我的情况下,由于我正在使用Libjit/llvm不支持的非主流嵌入式处理器的事实,因此不可能,因此我不得不发明自己的。

答案更有可能:没有人对C ++做更多的事情,因为好处可能不明显。

让我详细说明: 吉特 发动机/运行时既有开发人员的观点的祝福和弊端:他们在运行时有更多信息,但很少有时间进行分析。一些优化确实很昂贵,您不太可能看到没有对开始时间产生巨大影响的那些优化,例如:循环展开,自动矢量化(在大多数情况下,这也基于循环展开),指令选择(使用SSE4.1使用SSE4.1,以适合使用SSE4.1)与指令计划和重新排序(使用更好的超级CPU)结合使用的CPU。这种优化结合了诸如代码之类的C(可以从C ++访问)。

单个成熟的编译器架构进行高级编译(据我所知)是Java 热点 使用分层汇编(Java)具有相似原理的汇编和架构 阿祖尔的系统,这一天很受欢迎 Jaegermonkey JS引擎)。

但是,运行时最大的优化之一是以下内容:

多态性内联缓存 (这意味着,如果您使用某些类型运行第一个循环,第二次,循环的代码将是以前的循环的专业类型,则 吉特 将放置一个警卫,并将其作为默认分支作为内衬类型,并基于它,从这种专业形式使用 SSA- 基于形式的发动机将应用恒定的折叠/繁殖,插入,死亡代码淘汰的优化,并取决于如何“高级” 吉特 IS,将进行改进或改进的CPU注册分配。)您可能会注意到 吉特 (热点)将主要改进分支代码,并且使用运行时信息将比C ++代码更好,但是静态编译器(在其方面都有时间进行分析)进行分析,指令重新排序,对于简单循环,可能会变得更好一些表现。另外,通常情况下,C ++代码,需要快速的区域往往不op,因此 吉特 优化不会带来如此惊人的改进。

另一个优势 jit 就是它 吉特 作品交叉集会,因此如果要进行内部插入,它将具有更多信息。

让我详细说明:假设您有A级A,并且您有 只有一个 在另一个软件包/汇编/gem/等中实现它B。并动态加载。

吉特 看到B是A的唯一实现,它可以在其内部表示中替换为A内部表示的a呼叫中的a呼叫,并且方法调用将不会进行调度(请查看VTable),但将是直接调用。这些直接呼叫也可以被嵌入。例如,该B有一种方法: getLength() 返回2,所有电话 getLength() 可以将整个恒定降低到常数2。最后,C ++代码将无法从另一个DLL跳过B的虚拟调用。

C ++的某些实现不支持优化更多.cpp文件(即使今天,最近版本中也有-lto标志 海湾合作委员会 这使得这是可能的)。但是,如果您是C ++开发人员,担心速度,您可能会将所有敏感类都放在同一静态库甚至同一文件中,因此编译器可以很好地嵌入它,从而使JIT通过Design提供了额外的信息,由开发人员本身提供,因此没有绩效损失。

Visual Studio可以选择进行运行时分析,然后可用于优化代码。

“概况指导优化”

Microsoft Visual Studio称此为“配置文件指导优化“;您可以在 MSDN. 。基本上,您可以将程序运行一堆时间,并附有一个探查器,以记录其热点和其他性能特征,然后您可以将profiller的输出馈送到编译器中以获得适当的优化。

我相信 LLVM 尝试做一些。它试图在程序的整个生命周期(编译时,链接时间和运行时)进行优化。

合理的问题 - 但有一个令人怀疑的前提。

就像尼尔斯的回答一样,有时“优化”表示“低级优化”,这本身就是一个不错的主题。

但是,它是基于“热点”的概念,该概念远不及通常给出的相关性。

定义:热点是一小部分代码区域,其中一个程序的程序计数器花费了很大一部分时间。

如果有一个热点,例如占用大量时间的紧密内部循环,则值得在低级别优化(如果您控制的代码中)进行优化(即不在第三方库中)。

现在假设内部循环包含对函数,任何函数的调用。现在,该程序计数器不太可能在那里找到,因为它更有可能在功能中。因此,尽管代码可能浪费,但它不再是热点。

有许多通用方法可以使软件慢,哪些热点是一个。但是,以我的经验,这是大多数程序员都知道的唯一一个,也是低级优化的唯一一个。

看到这个。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top