Full Width Azure Portal for Big Monitors!

DISCLAIMER: I work on the Azure team, but not on the portal. I think the portal is great, I just prefer a full-width layout. Use at your own risk.

I use the Azure portal A LOT. Since nuget.org is hosted on Azure, that’s probably not a shock :). One thing I don’t like (personal preference, I know some people like it) is that it’s a fixed-width site. I have all this space on my monitor going unused!

Boo. Fixed Width :(

You know what would look better? A full width layout:

Yay! Full Width :)

Fortunately, it’s easy to make it look like that, at least on Chrome. First, download the Stylish extension.

Download Stylish

Then, click the new Stylish button on your toolbar and choose “Manage installed styles”

Click Dat Button!

Choose “Write new style” to go to the style editor. Enter the following CSS and mark it to run for all URLs on the domain “manage.windowsazure.com”:

#headerbar-wrapper {
	width: 100%;
	margin-left: 0;
	left: 0;
}
#fxshell-navpane {
	left: 0;
	margin-left: 0;
}
#drawer {
	margin-left: 0;
	left: 0;
	width: 100%;
}
#aux-foreground {
	width: 100%;
	left: 0;
	margin-left: 0;
}

I also put it on a Gist here: https://gist.github.com/anurse/5485124

Save the stylesheet, reload the portal and POOF, instant full-width layout! Enjoy!

Posted on 29 Apr 2013

Lambdas vs. Method Groups

Update: Due to a glitch in my code I miscalculated the difference. It has been updated. See full history of the code in the Gist. The outcome is still essentially the same :)

I was talking with David Fowler when he mentioned something I found surprising: “Lambdas are more efficient than Method Groups”. My initial reaction was that he was entirely wrong, but he explained why and then I decided to do some analysis. Here’s what I found.

I wrote a simple program that would pass a method group in to a method in a big loop:

for (int i = 0; i < Iterations; i++)
{
	Call(Dump);
}

And later on, it tried the same with a simple lambda

for (int i = 0; i < Iterations; i++)
{
	Call(s => Dump(s));
}

Where Call takes an Action<string> and Dump takes a single string argument and just does nothing:

private static void Call(Action<string> act)
{
	act("Hi!");
}
private static void Dump(string str)
{
}

See the full code for the program as a Gist.

I put in some simple Stopwatch-based timing and Console.ReadLine calls to allow me to advance the app through the steps slowly. The results from the Stopwatch (which timed the whole process and took an average) were interesting on their own. I pre-JIT the methods by calling them outside the loops first, and with 100,000,000 iterations, I got this output:

Running Method Group Test
Finished Method Group Test
Elapsed: 1.5171E+006ns
Average: 1.5171E-002ns
High-Precision? Yes
Press Enter to Continue
Running Lambda Test
Finished Lambda Test
Elapsed: 9.9125E+005ns
Average: 9.9125E-003ns
High-Precision? Yes
Press Enter to End

The lambda case is noticibly faster! Note the difference in exponent (we’re dealing with tiny numbers). Ok, so not much faster, but still, that’s a significant result.

Now, what about memory. So I pulled up perfmon and added the .NET “Allocated Bytes/sec” counter. I’m not sure if that’s the right one, but it certainly seemed to illustrate the point. This is what I saw:

Perfmon

The big spike at the beginning (highlighted in Orange) is the Method Group round. The flat line (highlighted in Green) is the Lambda round. This must be where the problem lies.

Sure enough, looking at the code, we see something interesting. To simplify, I’ve made simple instance methods that just perform the call with a method group and a lambda (see the Gist). Now to decompile them.

.method private hidebysig instance void MethodGroup() cil managed
{
    .maxstack 8
    L_0000: nop 
    L_0001: ldnull 
    L_0002: ldftn void Curious.Program::Dump(string)
    L_0008: newobj instance void [mscorlib]System.Action`1<string>::.ctor(object, native int)
    L_000d: call void Curious.Program::Call(class [mscorlib]System.Action`1<string>)
    L_0012: nop 
    L_0013: ret 
}

First the one with the Method Group (above). Hmm… at L_0008 we see that we’re creating a new delegate and putting the function pointer to Dump in. Make sense. So why doesn’t the lambda version create the same amount of memory?

.method private hidebysig instance void Lambda() cil managed
{
    .maxstack 8
    L_0000: nop 
    L_0001: ldsfld class [mscorlib]System.Action`1<string> Curious.Program::CS$<>9__CachedAnonymousMethodDelegate5
    L_0006: brtrue.s L_001b
    L_0008: ldnull 
    L_0009: ldftn void Curious.Program::<Lambda>b__4(string)
    L_000f: newobj instance void [mscorlib]System.Action`1<string>::.ctor(object, native int)
    L_0014: stsfld class [mscorlib]System.Action`1<string> Curious.Program::CS$<>9__CachedAnonymousMethodDelegate5
    L_0019: br.s L_001b
    L_001b: ldsfld class [mscorlib]System.Action`1<string> Curious.Program::CS$<>9__CachedAnonymousMethodDelegate5
    L_0020: call void Curious.Program::Call(class [mscorlib]System.Action`1<string>)
    L_0025: nop 
    L_0026: ret 
}

Well, it certainly does more. But the key parts start at L_0001. The first thing this code does is check if the “CS$<>9__CachedAnonymousMethodDelegate5” member has a value. If not, it fills it in, at L_0014. But if it DOES have a value, the code just invokes that cached value! BINGO! The Method Group version allocates a new object every single time it is run whereas the lambda version uses an instance (or static, as necessary) field to cache the delegate.

So, what does this mean for you? Well, probably not much. Notice that all these numbers were tiny, so we’re talking about micro-optimizations. In fact, the most important take-away here is to remember that just because something seems faster, doesn’t mean it is faster. In David’s case, he discovered this in SignalR because they have a non-trivial number of lambdas allocated per connection, and there can be a LOT of connections. I know that I’ll probably switch to using Lambdas, just because it doesn’t seem to have any ill effects and if it saves us a few bytes, why not.

Please do note that I’m no performance expert. If you see a problem in this post, please tell me! It’s possible I’ve gotten this completely wrong somehow, so if this kind of performance is crucial to your app, you should definitely do your own profiling! And remember, the only way to make performance gains is to measure measure measure. You can’t just eyeball perf ;).

Posted on 19 Feb 2013

Look Ma! No GAC! Razor IntelliSense without GACing

If you’ve done any work with the open-source ASP.Net Web Stack (on Codeplex!) then you may have encountered one annoying issue: If you install an MVC 4 release, your source code version of MVC stops working. This is because our releases put the assemblies in the Global Assembly Cache, which is basically a special folder which overrides the Bin folder of your application. There are many reasons we do this, for example it is required if you are going to NGen an assembly. But specific reasons aside, the fact is that we install our assemblies in the GAC and that isn’t likely to change in “v2” (MVC4/WebPages2/Razor2). So, how can we start working around this problem?

WARNING: This is totally unsupported. I’m happy to help in the comments but if you call Product Support they won’t help you with this!

Step 0: Capture Binaries

Before you go uninstalling stuff, you should do one of these two things:

  1. Grab the assemblies necessary for VS BEFORE uninstalling OR
  2. Be prepared to build new ones from source

If you aren’t prepared to do #2, make sure you do #1! The Assemblies are in C:\Program Files (x86)\Microsoft ASP.Net. Here’s the full list of the ones you need, collect them and copy them into a separate folder (because Step 1 will delete them):

  • System.Web.Razor.dll
  • System.Web.WebPages.Razor.dll
  • System.Web.WebPages.Deployment.dll
  • System.Web.WebPages.dll
  • System.Web.Mvc.dll

Step 1: UnGACing

The first step is simply to remove the assemblies from the GAC. We only need to remove the “V2” Assemblies (“V4” for MVC related assemblies) because the GAC’d copy of v1 (v3 for MVC) won’t interfere with a version you build from source. NOTE: This will put Razor IntelliSense and other Visual Studio features relating to MVC in a somewhat broken state, but we’ll fix that in Step 2.

The first thing you might notice if you try to remove our assemblies from the GAC in the “usual” way is that they are locked by Windows Installer:

Razor assemblies are locked by Windows Installer

Ok, that kinda sucks. But fortunately this actually works to our benefit because we can use Windows Installer to remove the assemblies for us! If you installed MVC4/WebPages2 for Visual Studio 2010, this is easy, just go to Add/Remove Programs and uninstall the following two entries: “Microsoft ASP.Net MVC 4 Runtime” and “Microsoft ASP.Net WebPages 2 Runtime”. DO NOT remove the matching Visual Studio tools entries!

If you installed Visual Studio 2012, we don’t actually add our individual components to the Add/Remove Programs list in order to give you just one thing to uninstall (Visual Studio 2012). But, you can still uninstall our components! It just takes a little PowerShell Magic. So, open up an Admin PowerShell prompt (don’t worry, these are all built-in commands so copy-paste away)

First, run this command to uninstall ASP.Net MVC 4:

gwmi Win32_Product | where { $_.Name -eq "Microsoft ASP.Net MVC 4 Runtime" } | ForEach { $msi = Convert-Path "$($_.InstallSource)\*.msi"; msiexec /x $msi }

Click through the prompts and click “Yes” when you are asked to confirm even though 1 or more products will stop working (that’s VS ;)). Then, run a slightly different script to remove ASP.Net Web Pages 2 (which includes Razor):

gwmi Win32_Product | where { $_.Name -eq "Microsoft ASP.Net Web Pages 2 Runtime" } | ForEach { $msi = Convert-Path "$($_.InstallSource)\*.msi"; msiexec /x $msi }

Step 2: Fixing VS.

Now, some of the VS tooling will be broken :(. Pretty much just Razor IntelliSense but that’s one of the best features! (Though I may be biased ;)). VS tries to load System.Web.Razor (and some other friends) in order to parse Razor documents, but in Step 1, we removed it from the GAC and VS doesn’t have a local copy, so it doesn’t know where to find them!

The fix for this is simple: Give VS a local copy! So, first grab the binaries from Step 0 (if you collected them), or build new binaries from our source code (just follow the steps on our CodePlex site and then grab the binaries from the bin folder). Then, copy them to the following folder:

C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\PrivateAssemblies

Of course, replace “Program Files (x86)” with “Program Files” if you’re on a 32-bit OS. And replace “Microsoft Visual Studio 11.0” with “Microsoft Visual Studio 2010” if you’re using VS 2010. Restart VS and you should have IntelliSense! If you run in to issues, try building your project and restarting VS.

Wrapping up

That should be it! Now, please note that this is very unsupported. It works, but if you bork your VS installation, you’re on your own. Ok, not totally on your own, I’m happy to try helping in the comments, but don’t call support because they won’t help you with this!

If you get totally screwed, then you can either: repair VS if you’re using VS 2012, or reinstall MVC 4 if you’re using VS 2010. That should put you back in a known state.

Posted on 06 Jun 2012

BadImageFormatException - The signature is incorrect

Have you ever gotten this exception when running Unit Tests which use Moq?

System.BadImageFormatException : [D:\Path\To\A.dll] The signature is incorrect.

It’s a little strange but it turns out the issue is caused by a missing assembly reference in your Unit Test project. Let’s say you have three projects: Core, Types and Test. In Types, we define a helper interface for writing to the console:

public interface IConsole {
    void WriteLine(string line);
}

In Core, we have code to create and return one:

public class Thingy {
    public virtual IConsole MakeConsole() { ... }
}

And in Test, you have a unit test to test that something in Core never even constructs a console. Tests ONLY references Core, not Types (for whatever reason).

[Fact]
public void DoodadWritesToConsole() {
    // Arrange
    var thingyMock = new Mock<Thingy>();
    var doodad = new Doodad(thingyMock.Object);
    // Act
    doodad.DoAThing(writeToConsole: false);
    // Assert
    thingyMock.Verify(t => t.MakeConsole(), Times.Never());
}

If you have this set up, you’ll get the BadImageFormatException when running the test (or should, I haven’t verified this particular set of classes but I mocked it up from the code I actually found this in). The problem is that Test doesn’t reference Types, and Types is what provides the interface used as the return value for MakeConsole. All you need to do is add a reference from Test to Types and you’re done!

I basically just wanted to throw up a quick blog post so that I could find it if I encountered this again, but hopefully this also helps a few other folks :)

Posted on 18 May 2012

Yet another blog update!

Well, I went and updated my blog again. I got tired of paying for SquareSpace when I was only barely using it. Also, I’m a nerd and nerdy things make me happy. So, I’m trying out GitHub Pages and Jekyll. That means that this entire site is up on GitHub and can be viewed by anyone at any time! The repo is here. It’s all static html that gets run through Jekyll on GitHub’s servers. I have a local copy of Jekyll I use to test things out too. The comments are mostly ported across except for one page (which I’ve contacted Disqus support for). The RSS feed has also moved, but the old one should continue to work. Please resubscribe to the new one though at: http://feeds.feedburner.com/Vibrantcode.

As you can see, I’ve also updated the site layout. It’s a Responsive design as well, which means that the layout adjusts as the browser window size shrinks. It also means it should look pretty good on mobile devices like phones and tablets!

I’ll have more posts later on the details behind the new “engine” but it’s bedtime now ;). Enjoy! Let me know what you think of it!

Posted on 06 May 2012