Friday, November 29, 2013

.NET will not inline methods with many parameters (in practice)

By examining disassembly of this method in the debugger, I learned that the .NET inliner (x64) is too dumb to take into account the cost of calling a method in its inlining decision. .NET will not inline the last three methods, even though I only add a single additional instruction for each additional parameter. So it seems the inlining decision is based only on the cost of the method body; .NET ignores the cost *savings* of not having to shuffle registers or stack space around when it inlines a method.
private static long InliningTest(long a, long b, long c, long d, long e, long f, long g, long h)
{
    long total = 0;
    total += Foo(a, b, c);
    total += Foo(c, d, e, f);
    total += Foo(d, e, f, g, h);
    total += Foo(f, g, h, a, b, c);
    total += Foo(h, a, b, c, d, e, f);
    total += Foo(a, b, c, d, e, f, g, h);
    total += Foo(a, c, e, g, b, d, f);
    total += Foo(a, b, c, d, e, f);
    total += Foo(a, b, c, d);
    total += Foo(a, b, c);
    return total;
}
private static long Add(long a, long b)
{
    return a + b;
}
private static long Foo(long a, long b, long c)
{
    return a * b * c + a + b + c;
}
private static long Foo(long a, long b, long c, long d)
{
    return a * b * c * d + a + b + c;
}
private static long Foo(long a, long b, long c, long d, long e)
{
    return a * b * c * d * e + a + b + c + d;
}
private static long Foo(long a, long b, long c, long d, long e, long f)
{
    return a * b * c * d * e * f + a + b + c + d;
}
private static long Foo(long a, long b, long c, long d, long e, long f, long g)
{
    return a * b * c * d * e * f * g + a + b + c + d;
}
private static long Foo(long a, long b, long c, long d, long e, long f, long g, long h)
{
    return a * b * c * d * e * f * g * h + a + b + c + d;
}

Wednesday, November 20, 2013

Re: VSIX with the VS2010 Beta 2 SDK

I found this blog post useful. I tried to leave the following comment, but was told that only "team members" were allowed to leave comments.

Thanks very much! I figured out the MergeWithCTO thing myself by comparison to another project, but then I got this error in ActivityLog:
<description>CreateInstance failed for package [MyExtension.MyPackageClass, MyExtension, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b1460dff8a28f7a7]</description>
...
<errorinfo>Could not load file or assembly 'MyExtension, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b1460dff8a28f7a7' or one of its dependencies. The system cannot find the file specified.</errorinfo>
The error message made no sense at all because (1) the error message knows the name of the Package class, how could it discover the name of the class if it never loaded the DLL? and (2) my extension also contains an implementation of ITaggerProvider that runs properly, so clearly my DLL was being loaded.

Adding those properties to my csproj file fixed the problem.
<PropertyGroup>
 <RegisterOutputPackage>true</RegisterOutputPackage>
 <RegisterWithCodebase>true</RegisterWithCodebase>
</PropertyGroup>