Нет *.Когда F # выдает IL для программы, все обращения к condition
осуществляются через средство доступа к свойству.Из-за этого дополнительного уровня косвенности движок JIT не может оптимизировать все тело reliesOnCondition
.
Позвольте мне показать, как я это выяснил.(Также перечислено в старом блоге пост.)
Создание нового проекта F # 'SOQ'
Создайте наше приложение F #.Я просто жестко запрограммировал условие: false
.
module Program
let condition = false
let inline reliesOnCondition (x:int) =
if condition then
printfn "%i" x
[<EntryPoint>]
let main args =
printfn "(attach a debugger and press any key)"
System.Console.ReadKey(true) |> ignore
reliesOnCondition System.DateTime.Now.Second
0
Разберите его и соберите его с кодами IL в PDB
Далее используйте ildasm
дляразберите бинарный файл IL с помощью параметра /SOURCE
.Это не только даст вам IL-дамп исходного кода, но также включает исходный исходный код, оставленный в качестве комментариев.
ildasm SOQ.exe /OUT=SOQ-annotated.exe.il /SOURCE
Соберите наш двоичный файл из IL
Затем используйте ilasm
для повторной сборки двоичного файла IL, но передайте флаг /DEBUG
, чтобы получить PDB.Полученное приложение будет иметь два уровня кода.Во-первых, исходный F # будет оставлен в виде комментариев, а фактическим кодом будут инструкции IL.
ilasm SOQ-annotated.exe.il /DEBUG
Запустите процесс и подключите отладчик Visual Studio
Запустите недавно аннотированную программу.Это приведет к тому, что приложение получит JIT-тед, как обычно.Затем присоедините отладчик Visual Studio к активному процессу.
Пошаговый код
Просмотр дампа IL в отладчике VS недостаточен.Щелкните правой кнопкой мыши в окне «Stack Traces» и выберите Перейти к разборке .Это даст вам отображение актуальных x86-инструкций.
Вот дамп кода операции x86.Обратите внимание на исходную строку исходного кода F # вверху (ildasm /SOURCE
), инструкции IL под ним (ilasm /DEBUG
) и инструкции x86 ниже (любезно предоставлены Visual Studio).
//000014: reliesOnCondition System.DateTime.Now.Second
IL_0026: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now()
000000db lea ecx,[ebp-58h]
000000de call 595E8C00
IL_002b: stloc.3
000000e3 lea edi,[ebp-30h]
000000e6 lea esi,[ebp-58h]
000000e9 movq xmm0,mmword ptr [esi]
000000ed movq mmword ptr [edi],xmm0
IL_002c: ldloca.s V_3
000000f1 lea eax,[ebp-30h]
000000f4 mov dword ptr [ebp-74h],eax
IL_002e: call instance int32 [mscorlib]System.DateTime::get_Second()
000000f7 mov ecx,dword ptr [ebp-74h]
000000fa call 5960A670
000000ff mov dword ptr [ebp-5Ch],eax
IL_0033: stloc.2
00000102 mov eax,dword ptr [ebp-5Ch]
00000105 mov dword ptr [ebp-28h],eax
IL_0034: call bool Program::get_condition()
00000108 call dword ptr ds:[004232D8h]
0000010e mov dword ptr [ebp-60h],eax
IL_0039: brfalse.s IL_003d
00000111 cmp dword ptr [ebp-60h],0
00000115 je 0000011A
... snip ...
Как вы можетеПосмотрите, инструкция IL 34 вызывает Program::get_condition()
, поэтому JIT не имеет достаточно информации для правильного устранения вызова функции no-op.(Обратите внимание, что только функции могут быть помечены как встроенные, поэтому вы не можете идти дальше, чем это.)
* На моей машине (x64 Win7).Существует разница между механизмами JIT x86 и x64, а также тем, использовали ли вы NGEN для создания своего исполняемого файла.Ваш пробег может отличаться.