So, I missed last Friday’s Fun Friday post. Technically I missed this week as well since it is now Sunday, and I’m pretending it’s still Friday. I’m also not really doing a full “Fun Friday” post, just a bit of a status update because I know how you worry.
My apologies, but my family and I spent a week in the mountains of North Carolina.
The mountains around Sylva and Cullowhee hold a special place in my heart since it is where I grew up.
This was the first time we’ve spent more than a weekend there in nearly a decade.
It was quite nice to visit family including my neice and her daughter who were visiting from Dubai.
New Project Alert
I’ve been using Docpad for a few months now, and for the most part I love it.
The one and only complaint I have is that when I’m writing and letting docpad “re-compile” the site, it can be a bit slow.
That’s not enough of a problem for me to decide to write a replacement, but writing a replacement would be fun. As in Fun Friday, no?
I’ve used the name Quirkety in the past for blog related work. I don’t plan to make a general usage app that is all things to all people.
Instead I’m going to write an engine that meets my own personal quirky needs. Hence “Quirkety”.
My goals for this project are:
Easier to set up than Docpad
Written in C#
Use ASP MVC Razor engine for dynamic bits
Run from commandline
Gain experience with OWIN/Katana
Move to ASP vNext when it matures a bit
To be clear I have nothing against Docpad. I love it.
My goal is to simplify. Where Docpad is almost 100% flexible in what it can do, Quirkety will be spectacularly inflexible.
Docpad has an amazing plug-in ecosystem that allows you to chain together transforms from darn near any format to darn near any other format.
Quirkety will be more opinionated. It will allow you to write in Markdown files then render them through the MVC Razor view engine out to static files.
Not sure how long it will take to reach the stage of replacing Docpad for my personal usage since I’ll have to coordinate it with other things going on in my life.
For my non-US readers, that’s just the fourth day of July.
In both cases, I hope you have a great day.
4th Of July For Non US Readers
If you aren’t from the US, here’s a quick primer of why the day is significant for those of us in the US.
This is the day we celebrate the greatest break-up letter in history.
On this date our Declaration Of Independence was signed and sent on its way to King George of England.
Here’s my quick paraphrase:
This is hard to say, but we’ve grown apart. It’s like we don’t even know each other anymore.
Sometimes it’s best to just go our separate ways.
We just feel like we owe you an explanation.
We have tried to get you to work things out. Every step of the way, we’ve asked you to make some changes, but Noooo.
It’s no use trying to talk us out of leaving.
We’d really like to be friends, but if you insist we can be enemies.
(Other, smaller signatures)
History is why we celebrate, but how do we celebrate?
Many of us build a fire of one sort or another and grill an animal of one sort or another.
For me it’s hamburgers and hot dogs over charcoal. I like grilling lots of things, but on the 4th I want a burger and/or hot dog, because ‘Merica.
Grilling Is Not Optional
This was last year. Rain tried to dampen (ha! see what I did there?) our spirits, but I said, “No! We must grill!”
No tradition is more American than blowing stuff up.
These days we mostly go for fireworks either lame or spectacular.
Many states have laws regulating the sale of fireworks. This is an attempt to prevent:
High Speed Digit Deletion (the explosive removal of fingers)
In these states it is a tradition for a fair percentage of the population to travel to the nearest state with a more liberal view towards the desires of its citizenry to burn down their neighborhoods and remove unwanted fingers.
In my state (Georgia) we allow only lame fireworks. Here is a chart to help determine if fireworks are lame or awesome.
Potential Damage: Small, localized fire. Easily extinguished by stomping on it.
Potential Damage: Large, neighborhood engulfing conflagration. Extinguished only by concerted effort of two or more governmental agencies.
In bygone days when fireworks were hard to come by, it was a tradition to do the next best thing.
Explosive Launching Of Anvils Into The Air
Anvils are heavy. That’s kind of their thing. You can’t really pound heated metal over a lightweight object.
I find it sad that the practice of launching of 2-300 pound metal objects has largely fallen out of favor. The closest many of us have come to the experience is Lawn Darts.
Here’s a great video to showcase the concept:
Indeed most of us only know of anvils thanks to the tireless work of Wile E. Coyote, Super Genius.
I say Wile E. is the embodiement of America. He never quits. No amount of personal injury or failure has ever stopped him from his pursuit of life, liberty and fast, flightless birds.
So here’s to you, Mr. Coyote, and here’s to you Mr. Wilkinson. May your anvil adventures never end, and may your freedom to pursue failure, folly, and awesomeness ever endure!
Jeff is one of those “Card-Carrying Genius” types. He has written probably more books than I’ve read and was one of the founders of Wintellect. I’ve known several folks who worked for Wintellect, and they have all been damned sharp.
Here’s the opening of his article:
Do you want to know a secret? A deep, dark, dirty secret? One that, if revealed, would cause great angst in the ASP.NET community and prompt shouts of “Aha!” from the anti-Microsoft crowd?
Most Web sites I’ve seen built with ASP.NET aren’t very scalable, not because of a flaw in ASP.NET, but because of how the technology is used. They suffer a self-imposed glass ceiling that limits the number of requests they can process per second. These sites scale just fine until traffic rises to the level of this invisible ceiling. Then throughput begins to degrade. Soon after, requests start to fail, usually returning “Server unavailable” errors.
– Jeff Prosise
In a word: Threads. In two words: Thread Pool. Three words? Thread Pool Saturation.
Each person who connects to your app gets a thread from the .Net CLR Thread Pool.
As long as you don’t have more people than threads, everything’s great!
Unfortunately once you get more people than threads, new users go into a queue to wait for the next available thread.
Browsers waiting for connections lead to frustrated users leaving the page.
The real fun happens when they leave, and then a thread is assigned to them and waits for them to respond.
The thread doesn’t know they left, so it waits until it reaches its timeout period. That means even though they left, they still ate up a thread.
Going back to my story of the two identical apps, the reason the one not being load tested kept working was because it had its own thread pool. The thread pool is at the CLR instance level. In ASP terms that means Application or App Pool level.
How Bad Is It Really?
Bad. Really bad.
I’ve created a super simple MVC app to illustrate.
To keep it simple I just did ye olde File: New Project and accepted the default MVC app.
The Home controller has three actions:
These do nothing but return their view.
In the real world, they would probably look something up in the database, so I put in a random delay to simulate that.
So if you hit one of the pages, the app waits between .5 and 1.5 second before responding.
Here’s a bit of the code:
Random randy = new Random();
public ActionResult Contact()
ViewBag.Message = "Your contact page.";
return randy.Next(500, 1500);
Next I used the Load Testing built into Visual Studio Ultimate to see how it performed.
I started with 200 users and added 200 every 10 seconds until I reached 2,000.
I held at 2,000 and ran for a total of five minutes.
Here is a chart of the results:
Avg. Page Time
The average page load time was 20.7 seconds.
That’s FIVE TIMES longer than the average person will wait!
How Can I Fix This?
If you’ll remember from Jeff Prosise’s article, the answer comes down to asynchronous programming.
If you read his whole article, you probably came away with the impression that Jeff is very smart and asynchronous programming is very hard.
In 2007 that was true (the hard part is less true now, the “he’s smart’ part is still true).
Fortunately .Net 4.5 gave us async and await.
Async Made Easy (ier)
Don’t let anyone kid you, asynchronous coding will make your head hurt.
You really don’t know the order in which things will happen and have to take great care with variables.
I’ve worked a bit with Node.js, and it starts with the idea that everything should be asynchronous.
One of the big differences between Node and ASP is that Node makes you declare synchronous code whereas .Net makes you declare asynchronous code.
Having said that I find the nesting of callbacks in Node to border on spaghettification at times.
Until .Net 4.5 using asynchronous code in .Net was even more cumbersome.
Now with async and await you can write code that looks like synchronous code, but behind the scenes compiles to an asynchronous construct.
Let’s take a look at what changes need to be made to make the controller code I showed before asynchronous, then see the results of running the same load test.
Random randy = new Random();
publicasync Task<ActionResult> Contact()
ViewBag.Message = "Your contact page.";
return randy.Next(500, 1500);
As you can see I added the async keyword on the method and the await keyword inside the method. I also made the method’s return type a Task of type ActionResult instead of an ActionResult.
Also, I obviously couldn’t tell the Thread to sleep, so I swapped out Task.Delay.
The result is that behind the scenes a callback will be added.
Before I was explicitly saying “Wait here and let this thread spin for n-milliseconds, then continue.”
Now I am saying, “Set a callback here, release the thread back into the thread pool, and when n-milliseconds have passed, give me a thread and continue.”
How Much Does It Help?
Here is a chart of the results of running the asynchronous version:
Avg. Page Time
I think you’ll agree that’s quite an improvement.
Yes we had a few that took too long, but the average time to load dropped by an order of magnitude.
Our proverbial average user wouldn’t abandon our site just because of the time to load a page.
As you can see there are a couple of gaps in the chart.
Unfortunately my notebook tends to have I/O log jams and the test was a bit too much for it.
I could move the test up to Visual Studio Online, but it would exceed my monthly allotment of testing “virtual user minutes.” Since these results demonstrate the point I’m making, I don’t think I’ll buy extra minutes to perfect the test.
My first test was with 10,000 users and my notebook shut itself down because the CPU was overheating!
Fortunately 2,000 users sufficiently demonstrates the point.
You knew there had to be a catch, right? It couldn’t be this easy.
No, it’s not quite this easy.
In the real world you will be getting stuff from databases, file systems, and web APIs.
If any of those do something synchronously, you will lose the ability to relinquish the thread back to the pool.
Entity Framework has been an offender in this area, but from EF6 onwards there are asynchronous methods you can use instead of synchronous ones.
I haven’t worked with asynchronous EF yet, so I can’t say much about it.
If you are creating anything other than a departmental app, you should be coding asynchronously.
Sure you can throw more hardware at the problem, but what a waste!
You could spin up the biggest, baddest, fire-breathing monster of a server and you would still be limited by the number of threads in the thread pool.
You can increase the number of connections in the thread pool (and you very well might anyway), or spread the load across multiple web servers (again, you will probably do so), but the biggest bang for the buck comes with asynchronous code.
Hopefully I’ve piqued your interest in asynchronous ASP. Hopefully you’ll starting doing it ASAP.
Nodejs.org It wouldn’t hurt to spend some time with Node to see how an asynchronous or die philosophy works. If nothing else it will make you appreciate how much less complicated .Net now makes asynchronous code.
Tasks, IDisposables and async/await Great post from Mark Rendle about not botching your code by trying to pass along an already disposed task. He makes a great point about the incremental time added by async/await and when it is worth the wait. Or await.
Big software push at work that was very stressful, so Friday looks mighty good.
Also planning to have lunch with a friend so that’s always a bonus.
I’m going with a new format for the links.
Up until now I’ve been using an ordered list so that the links were numbered. That made formatting a royal pain in markdown, so I wound up hand writing HTML. The point of markdown is to not write HTML.
This time there will be no numbers, just headings and paragraphs.
Now that I’ve said that I can’t see why I bothered with the ordered list in the first place.
I’m not a fan of some things Microsoft has done in recent years, but I am a fan of C# and ASP MVC.
Windows 8 COUGH! It’s a floor cleaner AND a dessert topping! COUGH!
Windows Phone COUGH! OK, I really like the Lumia phones, but missing too many apps and users. COUGH!
Windows Surface COUGH!!! Grossly overpriced $$$$$ COUGH!!!!!!
COUGH! CHOKE! GAG! GASP!!!
The word “cough” sure looks weird and incorrectly spelled when you make it all caps.
Don’t you love pull boxes and side notes? I sure do!
A Totally Different Note:
My comments above on Windows Phone and Surface reflect some sour grapes because I really like them and want them, but can’t justify them.
The Surface because of price and Lumia for lack of users and apps I need.
In this video Scott Hunter talks about what’s coming in ASP MVC 6 and then in what they are calling vNext.
Some of my favorites:
Lots of open source: both from Microsoft and used by Microsoft
Modular: Stop being one giant, bloated monolith
Cross platform: Run ASP on Mac or Linux. No, I’m not kidding.
Improved runtime performance
No need to compile web app; compiles on server (wait, isn’t that how it used to work?)
Use whatever tool you like. Vim me, baby!
Less stupid configuration files. Also fewer stupid config files.
Easier to deploy to and configure for cloud
Easier to debug in the cloud
Favorite Quote: We know our configuration system is too complicated, in my opinion, when we have this feature called XML Transformations where we can take your Web.config file and merge it and change it before we copy it up to the cloud. – Scott Hunter
Scott goes on to explain that your configuration should be defined in the cloud not in a config file that has to be transmogrified.
Sounds Good To Me
As I said I’m skeptical of some of Microsoft’s moves, but the Azure and ASP teams have really been doing outstanding work. I am truly looking forward to what’s coming.
Case in point: project files that don’t try to list all the darned files. Why, oh why not just look at the directories? Awesome change there.
Why Is This Important?
Wednesday night I went to a social meetup of the Atlanta Web Design Group.
I am not a designer, but as a web developer I wind up doing design whether I’m good at it or not. I want to learn more about design and meet designers.
As we were talking one of the fellows mentioned that he’s working towards becoming a developer as well as designer. He is looking at Ruby on Rails.
I asked if he had considered the Microsoft stack and his response spoke directly to the points Scott made about tools.
His response? “I can’t really use the Microsoft stack because I use a Mac.”
THAT is why it is important for Microsoft to support Linux and Mac and Sublime Text.
YES This is FUN!!
In case you wonder, yes, I do consider these topics fun!
Microsoft’s Build Conference is their annual developer extravaganza.
The best thing about Build is that most of the sessions are published on Channel 9, so you can learn the new technologies even if you couldn’t attend.
I am in the list of people who could not attend, but who are eager to learn.
If you are reading this, then I assume that you are also in that category.
As I watch these videos I tend to take notes.
As I watched this video and took notes in Vim with Markdown, it dawned on me that it would be a very short path to turning my notes into summary info that other folks might benefit from.
This also serves as my brain-dump/memory jogger for later.
I don’t know how many I’ll do, but if I get feedback that this is valuable, I’ll likely do more.
Do remember that these are just my notes. You will definitely still need to watch the videos to make heads or tails of the notes. I don’t plan to write full summaries or in many cases use full sentences.
Deep Dive: Improving Performance in Your ASP.NET App
Sucks. Don’t use it. Not what Levi said. It still sucks. That’s what jeffa says.
Use ViewStateMode for granular control. Only add what you really need.
Turn off for page, on for specific controls.
Limit what you store in the Page.ViewState property.
Do not set EnableViewStateMac=false Never, ever under any circumstances
Will break in the future if you use it.
Basically if you do this you are not encrypting the viewstate and someone will take advantage of that at some point and you will get what you deserve.
This topic is talking about web forms data source.
Reduce number and size of queries.
EF code first and asp.net 4.5 model binding.
Prefer QueryableDataSource or ObjectDataSource over SqlDataSource.
Glimpse: shows you what’s going on in your web app. Great diagnostic tool.
Get glimpse from nuget.
SqlDataSource does Select * EVERY time. Even during paging.
Damn. That sucks.
install-package ef…. 6.0 not 6.1. May be fixed by now.
Places where throttling can occur:
Max concurrent requests per application
Max concurrent requests per CPU
ASP.NET request queue limit
Is debug=true still present in web.config?
Avoid one .aspx file per folder - try to cluster. Calls compilation system per folder so clustering helps
Consider precompilation to reduce startup time Avoids the above
Avoid writes to files under c:\inetpub\wwwroot Asp and iis monitor changes there (and children) looking for web.config etc changes. Causes recyle of app. Make sister folder to inetpub/wwwroot, not child.
Remove empty methods in Global.asax IIS will call methods even if they are empty.
Use tracing, Glimpse, Intellitrace to find bottlenecks. Also AppInsights
Use perf counters for diagnostics
Consider enabling CDNs on ScriptManager
Weigh 32 vs 64-bit processes 64 uses twice as much memory for some things.
Don’t be afraid to scale out Basically an 80/20 thing. You reach a point of deminishing returns on your optimization efforts that means you are wasting your time.