出于这样或那样的原因,我有时会发现查看函数的优化编译器输出很有用或者很有趣.
对于非托管C/C++代码,我最喜欢的方法是在Release模式下编译,在感兴趣的函数中粘贴一个断点,运行,并在它到达断点时查看Visual Studio中的反汇编.
我最近尝试使用C#项目,并发现该技术不起作用.即使在Release模式下,我看到的反汇编显然也没有优化.我发现并禁用了(在Visual Studio 2010中)"调试...选项和设置...调试...常规...抑制模块加载时的JIT优化"选项,这可以让我更接近我想要的,只现在它在我尝试运行它时发出警告,然后我无法让它停在断点上以便我可以看到反汇编.
那么,如果我想看一个函数的CLR(4.0)抖动的反汇编优化输出,那么最好的方法是什么呢?为了清楚起见,我希望看到x86(或最好是x86_64)反汇编,而不仅仅是IL反汇编(你可以在Reflector中看到).
可能重复:
JIT编译器与脱机编译器
我听说在某些情况下,由于JIT优化,Java程序或java程序的某些部分能够比C++(或其他预编译代码)中的"相同"代码执行得更快.这是因为编译器能够确定某些变量的范围,避免一些条件并在运行时拉出类似的技巧.
你能给出一个(或更好 - 一些)例子吗?并且可能概述了编译器能够优化字节码超出预编译代码可能性的确切条件?
注意:这个问题不是将Java与C++进行比较.它关于JIT编译的可能性.请不要燃烧.我也不知道有任何重复.如果你是的话请指出来.
我正在编写相当低级别的代码,必须对速度进行高度优化.每个CPU周期都很重要.因为代码是用Java编写的,所以我不能像C中那样写低级别,但是我希望能够从VM中获取所有内容.
我正在处理一个字节数组.我的代码有两个部分,我现在主要感兴趣.第一个是:
int key = (data[i] & 0xff)
| ((data[i + 1] & 0xff) << 8)
| ((data[i + 2] & 0xff) << 16)
| ((data[i + 3] & 0xff) << 24);
Run Code Online (Sandbox Code Playgroud)
第二个是:
key = (key << 15) | (key >>> 17);
Run Code Online (Sandbox Code Playgroud)
从性能来看,我猜这些陈述没有按照我的预期进行优化.第二个陈述基本上是一个ROTL 15, key.第一个语句将4个字节加载到int中.0xff如果访问的字节恰好为负,则掩码仅用于补偿由隐式转换为int所产生的添加符号位.这应该很容易转换为高效的机器代码,但令我惊讶的是,如果我删除了掩码,性能会上升.(这当然会破坏我的代码,但我很想知道会发生什么.)
这里发生了什么?最常见的Java VM是否会在JIT期间以期望优秀的C++编译器优化等效C++代码的方式优化此代码?我可以影响这个过程吗?设置-XX:+AggressiveOpts似乎没有区别.
(CPU:x64,平台:Linux/HotSpot)
java有一个参数-XX:MaxInlineLevel(默认值为9),它控制嵌入的嵌套调用的最大数量.为什么会有这样的限制?为什么基于频率和代码大小的通常启发式方法不足以让JVM自行决定内联的深度?
(这是由JitWatch提示我显示深度嵌套的Guava checkArgument调用由于深度没有内联)
我清楚MemoryBarrier的用法,但不清楚运行时幕后发生的事情.任何人都可以对发生的事情做出很好的解释吗?
在关于Hotspot中的JIT的讲座中,我想尽可能多地给出JIT执行的特定优化的示例.
我只知道"方法内联",但应该有更多.为每个例子投票.
using System;
namespace ConsoleApplication1
{
class TestMath
{
static void Main()
{
double res = 0.0;
for(int i =0;i<1000000;++i)
res += System.Math.Sqrt(2.0);
Console.WriteLine(res);
Console.ReadKey();
}
}
}
Run Code Online (Sandbox Code Playgroud)
通过将此代码与c ++版本进行基准测试,我发现性能比c ++版本慢10倍.我对此没有任何问题,但这引出了以下问题:
似乎(在几次搜索之后)JIT编译器无法像c ++编译器那样优化此代码,即只调用sqrt一次并在其上应用*1000000.
有没有办法迫使JIT这样做?
我已经为.NET RyuJit安装了新的Jit编译器,并按照安装文档中的描述在regedit中设置了.NetFramework中的AltJit =*键. http://blogs.msdn.com/b/dotnet/archive/2013/09/30/ryujit-the-next-generation-jit-compiler.aspx
那么如何验证RyuJit实际上是否正在使用?
我一直在找你,有些代码无效.除了下面的一行,一切看起来都很好.
Transport = Transport?? MockITransportUtil.GetMock(true);
Run Code Online (Sandbox Code Playgroud)
执行该行之前,Transport为null.我看到GetMock已执行,并且它返回一个非null对象.在该行之后,运输仍为空;
我看了生成的IL,看起来很好.
IL_0002: ldarg.0
IL_0003: ldfld class [Moq]Moq.Mock`1<class [CommLibNet]CommLibNET.ITransport> Curex.Services.Common.UnitTests.Messaging.TestIGuaranteedSubscriptionBase::Transport
IL_0008: dup
IL_0009: brtrue.s IL_0012
IL_000b: pop
IL_000c: ldc.i4.1
IL_000d: call class [Moq]Moq.Mock`1<class [CommLibNet]CommLibNET.ITransport> Curex.Services.Common.UnitTests.Mocking.MockITransportUtil::GetMock(bool)
IL_0012: stfld class [Moq]Moq.Mock`1<class [CommLibNet]CommLibNET.ITransport> Curex.Services.Common.UnitTests.Messaging.TestIGuaranteedSubscriptionBase::Transport
Run Code Online (Sandbox Code Playgroud)
我们看到函数被调用,stfld应该获取返回值并设置字段.
所以我然后查看了程序集,我看到调用已经完成,但看起来RAX中的返回被下一次调用吹走了并且丢失了.
Transport = Transport?? MockITransportUtil.GetMock(true);
000007FE9236F776 mov rax,qword ptr [rbp+0B0h]
000007FE9236F77D mov rax,qword ptr [rax+20h]
000007FE9236F781 mov qword ptr [rbp+20h],rax
000007FE9236F785 mov rcx,qword ptr [rbp+20h]
000007FE9236F789 mov rax,qword ptr [rbp+0B0h]
000007FE9236F790 mov qword ptr [rbp+28h],rax
000007FE9236F794 test rcx,rcx
000007FE9236F797 jne 000007FE9236F7AC
000007FE9236F799 mov …Run Code Online (Sandbox Code Playgroud) 我刚刚发现PyTorch文档暴露了一些名为Torch Scripts的东西.但是,我不知道:
jit ×10
java ×4
c# ×3
.net ×2
optimization ×2
clr ×1
disassembly ×1
jvm ×1
performance ×1
pytorch ×1
ryujit ×1