AggressiveInlining работает?
Пишу код, понадобилось поработь с флагами. Захотелось проверки
Код:
(value & flag) == flag
Код:
value.IsSet(flag)
Код:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
(чтобы быстрая работа с битиками не превратилась в махинации со стеком и вызовом методов)
Компилирую в релизной конфигурации, смотрю в IL - шиш. Как был вызов метода, так и остался.
Пошёл гуглить, нашёл такую статейку:
http://blogs.microsoft.co.il/blogs/sasha/archive/2012/01/20/aggressive-inlining-in-the-clr-4-5-jit.aspx
Взял пример из неё, как не имеющий никаких подводных камней и совершенно точно поддающийся инлайнигу. Шиш.
Изменил метод:
Код:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int SmallMethod(int i, int j)
{
return (i + j);
}
public static int SmallMethod(int i, int j)
{
return (i + j);
}
Проверяю - шиш.
И вот вопросы:
1) Работает ли в .NET 4.5 (x64) AggressiveInlining?
2) Работает ли Inlining вообще? Возможно, его нужно как-то дополнительно разрешать?
Код:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace CSharp_test
{
class Program
{
const int _max = 100000000;
static void Main(string[] args)
{
Method1();
Method2();
int sum = 0;
var s1 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
sum += Method1();
}
s1.Stop();
var s2 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
sum += Method2();
}
s2.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 10000000) /
_max).ToString("0.00 ns"));
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 10000000) /
_max).ToString("0.00 ns"));
Console.ReadKey();
}
static int Method1()
{
// ... No inlining suggestion.
return "one".Length + "two".Length + "three".Length +
"four".Length + "five".Length + "six".Length +
"seven".Length + "eight".Length + "nine".Length +
"ten".Length;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static int Method2()
{
// ... Aggressive inlining.
return "one".Length + "two".Length + "three".Length +
"four".Length + "five".Length + "six".Length +
"seven".Length + "eight".Length + "nine".Length +
"ten".Length;
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace CSharp_test
{
class Program
{
const int _max = 100000000;
static void Main(string[] args)
{
Method1();
Method2();
int sum = 0;
var s1 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
sum += Method1();
}
s1.Stop();
var s2 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
sum += Method2();
}
s2.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 10000000) /
_max).ToString("0.00 ns"));
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 10000000) /
_max).ToString("0.00 ns"));
Console.ReadKey();
}
static int Method1()
{
// ... No inlining suggestion.
return "one".Length + "two".Length + "three".Length +
"four".Length + "five".Length + "six".Length +
"seven".Length + "eight".Length + "nine".Length +
"ten".Length;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static int Method2()
{
// ... Aggressive inlining.
return "one".Length + "two".Length + "three".Length +
"four".Length + "five".Length + "six".Length +
"seven".Length + "eight".Length + "nine".Length +
"ten".Length;
}
}
}
УМВР.
TargetedPatchingOptOut — ещё одну плюшку для инлайна, т.к. AggressiveInlining не является 100% гарантией. Ну и:
Кстати, почитай про
However, methods that couldn’t be inlined previously because of other criteria are still not inlined. I checked the following, and neither of these methods was inlined:
Recursive method
Virtual method (even if the static type of the receiver variable is sealed)
Method with exception handling (representing a “complicated flowgraph”)
Recursive method
Virtual method (even if the static type of the receiver variable is sealed)
Method with exception handling (representing a “complicated flowgraph”)