Navigation
About Me

MS certified C#/ASP.NET software developer from Baltimore, MD.

Search
Subscribe
Monday
01Jun

Where has all the content gone?

I feel bad with more and more people following my blog that I'm not able to keep up with my posts but I do have a reason, I promise!

I've been self-employed however due to clients drying up I've been looking for a full time job as a .NET dev and have been extremely busy with writing demo code and trying to find work.  If you know of anyone looking for a .NET dev feel free to forward them to me through my Contact page or e-mail me at chad dot moran at live dot com.

I have some great content writting up including the third part of my ASP.NET MVC URL generation optimization and another great post about how I found a problem with a common workaround for ASP.NET MVC output caching that could cause way more memory usage than required.

I'll try to pump out these posts as soon as possible and my apologies for not getting them out sooner.  Thanks for reading and hope to write again soon.

Saturday
02May

Extension method digest #4 RouteBase.AsRoute

This one is very simple but is extremely helpful when dabbling in the System.Web.Routing namespace.  Using AsRoute extension will allow you to get to the properties and methods on the Route type itself like Constraints, Defaults and Url.

public static class RouteBaseExtensions
{
public static Route AsRoute(this RouteBase routeBase)
{
return routeBase as Route;
}
}

Again, a very simple extension method that can help save some time instead of having to cast the object yourself.  If the RouteBase target isn’t a Route itself it will just return null.

Thursday
23Apr

Optimizing URL generation in ASP.NET MVC – Part 2

Part 1
Part 2

So in continuing with the series of URL generation optimization in ASP.NET MVC we’re going to take a look at the actual optimization part of things.

Before I get started I’d like to start off by saying the results of the first part’s test were a little off due to my mistake.  When I was setting up the routes I didn’t setup defaults for the default route (“/”) so the URLs actually being generated were /name=chad&age=23 instead of /Home/Index/Chad/23 and thus skewing the results so to fix that I’ll be running the first 5 all over again including 3 new ones.  Note that the expression syntax method was not changed from this and the performance still stands.  The only methods that were really affected by this were those that found the route by action and controller names.  I apologize for the mistake and I will update the post accordingly.

In the first part we looked at some methods that are probably most commonly used by ASP.NET MVC devs and this part I’d like to look at some lesser-used methods of getting these URLs generated.  In this part I’m going to go over 2 other methods of getting URLs generated.  Though these methods might not generate all of the HTML they’re just as useful and even faster than previous methods.

Url.Action using action name and anonymous object (Method 6)

Url.Action("Index", new { name = "Chad", age = 23 })

Url.Action using action name, controller name and anonymous object (Method 7)

Url.Action("Index", "Home", new { name = "Chad", age = 23 })

Url.RouteUrl using route name and anonymous object (Method 8)

Url.RouteUrl("HomeIndex", new { name = "Chad", age = 23 })

Same conditions as the the first part.  After thinking about it I should have put these tests into the first part but what can you do so here they are.  Before the results I’d like to point out these methods don’t generate the whole URL rather the part after the TLD.  So in a URL like http://mydomain.com/Home/Index these methods would only generate the /Home/Index parts.  I understand this isn’t the same as the previous methods but they can still be used the same.  Only differences is you would have to wrap them in your own HTML (blasphemy, I know).  It would look something like this.

<a href="<% Url.RouteUrl("HomeIndex", new { name = "Chad", age = 23 }); %>">Link</a>

Now for the results.

URL Generation test

As you can see there was actually a difference between using action name and controller name versus using route names in performance like I originally suspected there should have been.

This is where the second part of this series should have started considering those 3 last tests should have been in the last one.

In the first part I linked to a great presentation that showed off how you can improve URL generation performance by not using the expression syntax and not using anonymous objects.  I’d also like to cover that.

When you use method 1 for URL generation it has to get the parameter values from your expression and put them into a RouteValueDictionary and pass that into another method to get the URL.  The method it uses is a nasty one (not coded badly but, expensive).  This method is in Microsoft.Web.Mvc.Internal.ExpressionHelper class.

private static void AddParameterValuesFromExpressionToDictionary(RouteValueDictionary rvd, MethodCallExpression call)
{
ParameterInfo[] parameters = call.Method.GetParameters();
if (parameters.Length > 0)
{
for (int i = 0; i < parameters.Length; i++)
{
Expression expression = call.Arguments[i];
object obj2 = null;
ConstantExpression expression2 = expression as ConstantExpression;
if (expression2 != null)
{
obj2 = expression2.Value;
}
else
{
Expression<Func<object>> expression3 = Expression.Lambda<Func<object>>(Expression.Convert(expression, typeof(object)), new ParameterExpression[0]);
obj2 = expression3.Compile()();
}
rvd.Add(parameters[i].Name, obj2);
}
}
}

As you can see on lines 17 and 18 this is getting called for every parameter coming into your method.  If you have a method with more parameters performance would be affected.  I decided to run a test on this too and see how performance would be changed as you add parameters onto your actions.  Again, same conditions used as the all other tests.

Expression syntax test

As you can see performance gets thrown out the door as you add more and more parameters to the action method.

So that’s what is killing performance in the expression syntax of URL generation.  What about the other methods, what could be hurting their performance?  The main performance loss in all other methods is using anonymous objects.  When you use an anonymous object for your route parameter values it has to use reflection to put them into a RouteValueDictionary and this is how it’s done.

private void AddValues(object values)
{
if (values != null)
{
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(values))
{
object obj2 = descriptor.GetValue(values);
this.Add(descriptor.Name, obj2);
}
}
}

So again, reflection is happening for each parameter passed in so the same performance decrease would happen with all other methods when adding more parameters.

To get around this we can just pass in our own RouteValueDictionary to avoid having to any reflection and it’s pretty easy to do.  So we’ll run the same 9 tests as before but without using anonymous objects and see what kind of difference we see.

Html.ActionLink<> expression (Method 1)

Html.ActionLink<HomeController>(c => c.Index("Chad", 23), "Link")

 

Html.ActionLink using action name and RouteValueDictionary (Method 2)

Html.ActionLink("Link", "Index", new RouteValueDictionary { { "name", "Chad" }, { "age", 23 } })

Html.ActionLink using action name, controller name and RouteValueDictionary (Method 3)

Html.ActionLink("Link", "Index", "Home", new RouteValueDictionary { { "name", "Chad" }, { "age", 23 } }, null)

Html.RouteLink using RouteValueDictionary (Method 4)

Html.RouteLink("Link", new RouteValueDictionary { { "name", "Chad" }, { "age", 23 } })

Html.RouteLink using named route and RouteValueDictionary (Method 5)

Html.RouteLink("Link", "HomeIndex", new RouteValueDictionary { { "name", "Chad" }, { "age", 23 } })

Url.Action using action name and RouteValueDictionary (Method 6)

Url.Action("Index", new RouteValueDictionary { { "name", "Chad" }, { "age", 23 } })

Url.Action using action name, controller name and RouteValueDIctionary (Method 7)

Url.Action("Index", "Home", new RouteValueDictionary { { "name", "Chad" }, { "age", 23 } })

Url.RouteUrl using route name and RouteValueDictionary (Method 8)

Url.RouteUrl("HomeIndex", new RouteValueDictionary { { "name", "Chad" }, { "age", 23 } })

TIme to run the tests…

URL Generation test

I put method 1 there for consistency.  The rest saw a pretty substantial boost in performance.  The most was Method 5 going from 282 to 120 ms, that’s more than double boost in performance.

As you can see the difference was going from this…

new { name = "Chad", age = 23 }

To this…

new RouteValueDictionary { { "name", "Chad" }, { "age", 23 } }

Again, I’m sure there are those out there that will point out this looks like a pain to write these types of links with this code and I agree.  That’s why in the next part I’m going to go over how we can get intellisense and maintainability over our code when generating URLs.  I am fully aware that this is only a difference of 100ms~ over 10,000 links but this can be very helpful with high-volume sites and sites that generate a large amount of URLs per page.

So now we’ve seen which methods are fastest and how we can make them twice as fast.  In the next part of the series I’ll go over how we can utilize this faster code and still keep it maintainable and easy to use.

Wednesday
22Apr

Synthetic followers, sign of something deeper?

Lately I’ve noticed an abnormal amount of people following me and shortly after I decided to follow them back unfollow me.  I mean, really?

I don’t know this just angers me and makes me feel bad for that person at the same time.  If you really want people to follow you write interesting information don’t trick people into following you.  I get about 2-5 spam followers a day if you want I can forward them and you can have your own little following.

Maybe I’m seeing twitter from a different light but for some people followers are like WoW achivements or StackOverflow reputation points – they’re just addicting.  Seriously though, I think this shows a lot about a person that they feel the need to get synthetic followers.  What I mean by that is, non-organic followers.  People that were tricked into following someone by some sort of mechanism.

Now I’m sure there are people out there who go follow happy and change their mind.  I guess excuses are like belly buttons… everyone has one.

</rant>

Tuesday
21Apr

Optimizing URL generation in ASP.NET MVC – Part 1

Part 1
Part 2

Inspired by a great presentation by Rudi Benkovic I thought I would make a series of blog posts about improving ASP.NET MVC performance through URL generation.

While developing an application for a project of mine I went gung-ho with expressions wherever I could.  Whether it was methods in my controllers or URL generation they were everywhere.  While stress-testing my app I ramped up the items on a page and noticed performance dipped significantly.  At the time I thought it may have been the data access since I’ve had troubles before with LINQ to SQL performance.  Though I found out it was actually the URL generation.  I was using the expression syntax from MvcFutures that looked like this.

Html.ActionLink<HomeController>(c => c.Index())

This is great if you want compile-time checking by compiling your views.  Problem is, this is horribly inefficient.  Let’s compare it against some other methods of linking.  I’m going to be creating a brand new ASP.NET MVC Project for those that want to follow along.  I’ll be modifying the Index action of the Home controller for the sake of testing.

public ActionResult Index(string name, int age)
{
ViewData["Message"] = string.Format("Hello {0}. I see you're {1} year(s) old.");

return View();
}

I added to parameters to the Index controller so we can test passing arguments into the method as part of the performance testing.  I added the following to web.config

<add namespace="Microsoft.Web.Mvc"/>
<add namespace="URLGeneration"/>
<add namespace="System.Diagnostics"/>

I also added the following routes to the list.  The reason I added them individually is to simulate a site having a few routes.  Putting the one we want to use at the bottom.

routes.MapRoute(
"Default",
"",
new { controller = "Home", action = "Index" }
);

routes.MapRoute(
"AccountChangePassword",
"Account/ChangePassword",
new { controller = "Account", action = "ChangePassword" }
);

routes.MapRoute(
"AccountChangePasswordSuccess",
"Account/ChangePasswordSuccess",
new { controller = "Account", action = "ChangePasswordSuccess" }
);

routes.MapRoute(
"AccountLogOn",
"Account/LogOn",
new { controller = "Account", action = "LogOn" }
);

routes.MapRoute(
"AccountRegister",
"Account/Register",
new { controller = "Account", action = "Register" }
);

routes.MapRoute(
"HomeAbout",
"Home/About",
new { controller = "Home", action = "About" }
);

routes.MapRoute(
"HomeIndex",
"Home/Index/{name}/{age}",
new { controller = "Home", action = "Index" }
);

The name of the project I created was URLGeneration thus the namespace.  Now the code for testing URL generation performance.

<%
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 10000; i++)
{
%><%= // URL generation %><%
}
sw.Stop();
%><%= sw.ElapsedMilliseconds %><%
%>

This code is pretty straight forward and should allow for accurate testing.  I’ll be running this code on a dedicated server with nothing else running and to help accuracy I’ll run the test 5 times and average out the time.  This will ensure we’re testing JUST the URL generation time and not the rest of the page or transfer time.  Some of you might be thinking 10,000 seems like a high number and you’ll never have that many links on your site.  Well, you’re right but if you have a lot of requests coming in at a given time then you may be generating that many overall.  This will help spread out the difference between the tests.

The methods of URL generation will be the following, probably most used methods first.

Html.ActionLink<> expression (Method 1)

Html.ActionLink<HomeController>(c => c.Index("Chad", 23), "Link")

Html.ActionLink using action name and anonymous object (Method 2)

Html.ActionLink("Link", "Index", new { name = "Chad", age = 23 })

Html.ActionLink using action name, controller name and anonymous object (Method 3)

Html.ActionLink("Link", "Index", "Home", new { name = "Chad", age = 23 }, null)

Html.RouteLink using anonymous object for guessing route (Method 4)

Html.RouteLink("Link", new { name = "Chad", age = 23 })

Html.RouteLink using named route (Method 5)

Html.RouteLink("Link", "HomeIndex", new { name = "Chad", age = 23 })

I ran all tests after a couple of warm-up loads.  None of the runs were on a cold start.

test1

UPDATE These results were actually skewed due to a mistake I made in the the default route.  To see updated, correct results please check out the second part of this series.

As you can see the method in MvcFutures is 10x as slow as the others.  I was actually surprised about Method 5 I thought that it would have been the fastest.

Now you may be thinking, well you tested 10,000 links and you’re right.  Let’s say you have 10 links and 1,000 requests coming in (which isn’t a lot for high-volume sites) then you’re adding 2 seconds in processing time just to generate links.  This was not the time it took to generate the whole page just the links.  That’s a lot of time to be adding meaning your requests/sec is going to dip.

In the next installment I’ll go over how we can go about optimizing this performance and how much of an impact it can have with some load testing.