在对这个答案的评论中(建议使用位移运算符而不是整数乘法/除法,为了提高性能),我询问这实际上是否会更快.在我的脑海中有一个想法,在某种程度上,某些东西将足够巧妙地解决这个问题>> 1并且/ 2是相同的操作.但是,我现在想知道这是否真的是真的,如果是,它会发生在什么级别.
测试程序optimize为两种方法产生以下比较CIL(带有on),分别对其参数进行划分和移位:
IL_0000: ldarg.0
IL_0001: ldc.i4.2
IL_0002: div
IL_0003: ret
} // end of method Program::Divider
Run Code Online (Sandbox Code Playgroud)
与
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: shr
IL_0003: ret
} // end of method Program::Shifter
Run Code Online (Sandbox Code Playgroud)
所以C#编译器正在发出div或shr指示,而不是聪明.我现在想看看JITter生成的实际x86汇编程序,但我不知道如何执行此操作.它甚至可能吗?
编辑添加
感谢您的回答,已接受来自nobugz的那个,因为它包含有关该调试器选项的关键信息.最终对我有用的是:
Tools | Options | Debugger,关闭'抑制模块负载上的JIT优化'(即我们希望允许 JIT优化)Debugger.Break()某处发表声明至少可以说结果很有启发性 - 事实证明JITter实际上可以做算术!这是来自"反汇编"窗口的已编辑样本.各种-Shifter方法除以2的幂>>; 各种-Divider …
我是一个在开发机器上使用Windows 7的新手,我有一个在启动时崩溃的开发工具,我没有看到它抛出的任何错误消息,或者有机会调试它,因为它显示了崩溃程序的Windows 7对话框,其中显示"Windows正在检查解决方案......"
我想让我的旧学校大屁股断言对话框,带有一个大的"DEBUG"按钮.我在Visual Studio的选项和设置中完全启用了JIT,所以我不确定为什么我没有得到该选项.
我试图重现这里描述的一些处理器缓存效果.我知道Java是一个托管环境,这些例子不会完全翻译,但我遇到了一个奇怪的例子,我试图提炼出一个简单的例子来说明效果:
public static void main(String[] args) {
final int runs = 10;
final int steps = 1024 * 1024 * 1024;
for (int run = 0; run < runs; run++) {
final int[] a = new int[1];
long start = System.nanoTime();
for (int i = 0; i < steps; i++) {
a[0]++;
}
long stop = System.nanoTime();
long time = TimeUnit.MILLISECONDS.convert(stop - start, TimeUnit.NANOSECONDS);
System.out.printf("Time for loop# %2d: %5d ms\n", run, time);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
Time for loop# …Run Code Online (Sandbox Code Playgroud) 虚拟机如何动态生成本机代码并执行它?
假设您可以确定要发出的本机机器操作码是什么,那么您如何实际运行它?
将助记符指令映射到二进制代码,将其填充到char*指针并将其作为函数进行转换并执行是不是很麻烦?
或者你会生成一个临时共享库(.dll或.so或其他)并使用标准函数将其加载到内存中LoadLibrary吗?
如果我们在硬件中实现java解释器那么我们如何实现java字节码的体系结构中立性... java是否使用JIT(只是在时间解释器中)?以及这些与虚拟机概念的操作系统和java虚拟机(JVM)有何关系
我们发现我们的Javascript代码的解释存在严重问题,这些代码仅发生在iOS 5/Safari 6(当时的iPad版本)上,我们认为这是由于Safari中的Just in Time JS编译器中的关键错误.(请参阅下面的更新,了解更多受影响的版本和现在似乎包含修复的版本).
我们最初在我们的库的在线演示中发现了这个问题:演示或多或少地随机崩溃,但这只是第二次(甚至更晚)发生相同代码的执行.即如果你运行一部分代码,一切正常,但后续运行会使应用程序崩溃.
有趣的是,在Chrome for iOS中执行相同的代码问题没有显示,我们认为这是由于Chrome for iOS中使用的Webview缺少JIT功能.
经过大量的摆弄,我们终于认为我们发现了至少一个有问题的代码:
var a = 0; // counter for index
for (var b = this.getStart(); b !== null; b = b.getNext()) // iterate over all cells
b.$f = a++; // assign index to cell and then increment
Run Code Online (Sandbox Code Playgroud)
本质上,这是一个简单的for循环,它将链表中的每个单元格分配给它的索引.这里的问题是循环体中的后增量操作.当前计数被分配给字段并在计算表达式后更新,基本上与首先分配a然后将其递增1相同.
这在我们测试的所有浏览器和Safari中的前几次都可以正常工作,然后突然看起来似乎计数器变量a首先递增,然后分配结果,就像预增量操作一样.
我创建了一个小提琴,显示了这里的问题:http://jsfiddle.net/yGuy/L6t5G/
在带有iOS 6的iPad 2上运行示例并且所有更新结果对于我的情况下的前两次运行是正常的,并且在第三次运行中突然显示列表中的最后一个元素具有指定的值,其中一个是关闭的(输出当你点击"点击我"按钮从"从0到500"变为"从0到501"时
有趣的是,如果你切换标签,或稍等一下,可能会发生突然结果是正确的两次左右的运行!似乎Safari有时重置是JIT缓存.
所以,因为我认为Safari团队可能需要很长时间来修复这个bug(我还没有报告),并且可能还有其他类似的错误,比如潜伏在JIT中同样难以找到的,我想知道是否有办法在Safari中禁用JIT功能.当然这会降低我们的代码(已经非常占用CPU),但速度比崩溃慢.
更新:不出所料,它不仅仅是受影响的后增量运算符,还有后减量运算符.更令人惊讶和更令人担忧的是,如果赋值,则没有区别,因此在现有代码中查找赋值是不够的.例如,下面的代码b.$f = (a++ % 2 == 0) ? 1 : 2;中,变量值未分配,但仅用于三元运算符条件,在某种意义上"失败",有时选择了错误的分支.目前看起来似乎只有在根本不使用邮政运营商时才能避免问题.
更新:同样的问题不仅存在于iOS设备中,而且存在于Safari 6中的 …
我发现我在市场上发布的一个应用程序会在某些手机上产生奇怪的结果.经过调查发现,一个函数存在一个问题,即计算两个GeoPoints之间的距离 - 有时它会返回完全错误的值.此问题仅在使用MediaTek MT6589 SoC(又名MTK6589)的设备上重现.而AFAIK所有此类设备都安装了Android 4.2.
更新我还能够使用联发科MT8125/8389芯片和安装了MT6589并安装了Android 4.1的Fly IQ444 Quattro重现联想S6000平板电脑上的错误.
我创建了一个测试项目,有助于重现错误.它重复运行计算1000次或100次迭代.为了排除线程问题的可能性,在UI线程上执行计算(具有小的暂停以保持UI响应).在测试项目中,我只使用了原始距离公式的一部分:
private double calcX() {
double t = 1.0;
double X = 0.5 + t / 16384;
return X;
}
Run Code Online (Sandbox Code Playgroud)
您可以在web2.0calc.com上自行查看,其值X应约为:0.50006103515625.
然而,在具有MT6589芯片的设备上,通常会计算出错误的值:2.0.
项目可在Google Code上找到(也可以使用APK).测试类的来源如下:
public class MtkTestActivity extends Activity {
static final double A = 0.5;
static final double B = 1;
static final double D = 16384;
static final …Run Code Online (Sandbox Code Playgroud) 我正在开发一个似乎工作正常的JIT编译器,除了一个问题:当代码引发异常并且异常处理程序在JITted例程中时,操作系统会立即终止进程.当我关闭DEP时不会发生这种情况,所以我认为它与DEP有关.
当DEP关闭时,异常处理程序正确运行,我确保调用VirtualProtect保护值为的JITted例程PAGE_EXECUTE_READ,然后验证它VirtualQuery.
在调试器下对此进行测试会报告致命错误发生在引发异常的位置,而不是稍后,我认为这意味着发生了类似的事情:
有没有人知道我可能做错了什么,以及如何让DEP接受我的异常处理程序?执行JITted代码本身没有任何问题.
编辑:这是生成存根的Delphi代码.它分配内存,加载基本代码,修复跳转修复和尝试块,然后将内存标记为可执行文件.这是DWS项目中外部函数JIT正在进行的工作的一部分.
function MakeExecutable(const value: TBytes; const calls: TFunctionCallArray; call: pointer;
const tryFrame: TTryFrame): pointer;
var
oldprotect: cardinal;
lCall, lOffset: nativeInt;
ptr: pointer;
fixup: TFunctionCall;
info: _MEMORY_BASIC_INFORMATION;
begin
result := VirtualAlloc(nil, length(value), MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
system.Move(value[0], result^, length(value));
for fixup in calls do
begin
ptr := @PByte(result)[fixup.offset];
if fixup.call = 0 then
lCall := nativeInt(call)
else lCall := fixup.call;
lOffset := (lCall - …Run Code Online (Sandbox Code Playgroud) 这个问题可能看起来有点愚蠢或奇怪,但我听说过很多关于.NET CLR,JIT编译器以及它是如何工作的等等等等等等......但现在我想知道它的确切位置或托管位置.
是吗 -
要么
我正在寻找关于此的详细答案.有人可能会将这个问题描述为"Windows操作系统如何在.NET运行时内触发/执行.NET可执行文件?
如您所知,Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE为了防止出现负值,该safeAbs方法已在我的项目中实现:
public static int safeAbs(int i) {
i = Math.abs(i);
return i < 0 ? 0 : i;
}
Run Code Online (Sandbox Code Playgroud)
我将性能与以下各项进行了比较:
public static int safeAbs(int i) {
return i == Integer.MIN_VALUE ? 0 : Math.abs(i);
}
Run Code Online (Sandbox Code Playgroud)
并且第一个比第二个慢几乎6倍(第二个性能几乎与“纯” Math.abs(int)相同)。从我的角度来看,字节码没有显着差异,但是我猜想差异存在于JIT“汇编”代码中:
“慢”版本:
0x00007f0149119720: mov %eax,0xfffffffffffec000(%rsp)
0x00007f0149119727: push %rbp
0x00007f0149119728: sub $0x20,%rsp
0x00007f014911972c: test %esi,%esi
0x00007f014911972e: jl 0x7f0149119734
0x00007f0149119730: mov %esi,%eax
0x00007f0149119732: jmp 0x7f014911973c
0x00007f0149119734: neg %esi
0x00007f0149119736: test %esi,%esi
0x00007f0149119738: jl 0x7f0149119748
0x00007f014911973a: mov %esi,%eax
0x00007f014911973c: add $0x20,%rsp …Run Code Online (Sandbox Code Playgroud)