How to improve ASP. net website performance

improve performance in asp net application and how to improve asp.net page performance
JohenCorner Profile Pic
JohenCorner,France,Professional
Published Date:02-08-2017
Your Website URL(Optional)
Comment
SECRETS FASTER ASP.NET 1JEFFREY RICHTER JOHN ROBBINS DAVID CONLIN SHMUEL ENGLARD RYAN RILEY CHRIS ALLEN ROBERT HAKEN MITCHEL SELLERS NIALL MERRIGAN CHRIS HURLEY RAGHAVENDRA MATT LEE JP TOTO MICHAEL WILLIAMSON TIAGO PASCOAL 2Foreword When we launched the predecessor to this book, 50 Ways to Avoid, Find and Fix ASP.NET Performance Issues, we had no idea what a hit it would be. More than 15,000 of you have got a copy, it’s been featured on www.asp.net, and it took Twitter by storm. Rising adoption of MVC 4 and Web API means more new chances for performance improvements than you can shake a stick at, so this book adds DPRQJRWKHUWKLQJV DðVWIXORIQHZWLSVIRUWKRVH technologies, all from members of the ASP.NET community. I’d like to thank them all for their excellent contributions. Last time, I said that between us we could make ASP.NET applications run faster than Usain Bolt with cheetahs for shoes. We’re not quite there yet, HWRSXWHKHUEXW,KRSHDOORI\RXðQGDIHZWLSVPRU a gazelle-like spring in your applications’ step. Michaela Murray dotnetteamred-gate.com redgateContents Foreword 3 Want to build scalable websites and services? Work asynchronously 6 Where are your custom performance counters? 7 RavenDB 8 Don’t call AsEnumerable on a collection before using LINQ 9 Never call .Wait() or .Result on a Task 10 Throwing HttpResponseExceptions 11 Web API tracing 12 Message Handlers 13 Database access 14 `VKLHPSWYLMLYHJJ\YHJOLU`V\»YLWYVÄSPUN Make the most of connection pooling by closing SQLConnection as soon as possible 16 OutputCache 17 ZLVUÄN\YL(HPVHVPKOYLHKOVWWPUN especially in library code 18 Be careful of variable allocations 20 4 4 PBHow to stress test your public facing web application using the cloud (or without it) 22 Using the keyword await doesn’t make the work asynchronous 24 +VU»\ZLHZ`UJHHPMVYZOVYTLOVKZ Turn off Change Tracking in Entity Framework 26 Always use compiled queries in Entity Framework 27 Diagnosing JavaScript memory leaks with Chrome Dev tools 28 Monitoring memory consumption over time 30 Use JValue in JSON.Net to parse complex JSON objects that you don’t have POCO types for 32 Cache JavaScript and CSS permanently 34 3VHKL_LYUHS1HH:JYPWJVULUHZ`UJOYVUV\ZS` KVU»ZWLJ\SHL7YVÄSL More free eBooks from Red Gate 37 Tools from Red Gate 38 1 Want to build scalable websites and services? Work asynchronously Jeffrey Richter www.wintellect.com One of the secrets to producing scalable websites and services is to perform all your I/O operations asynchronously to avoid blocking threads. When your thread issues a synchronous I/O request, the Windows kernel blocks the thread. This causes the thread pool to create a new thread, which allocates a lot of memory and wastes precious CPU time. Calling xxxAsync method and using C’s async/await keywords allows your thread to return to the thread pool so it can be used for other things. This reduces the resource consumption of your app, allowing it to use more memory and improving response time to your clients. 6 PB2 Where are your custom performance counters? John Robbins PULSSLJJVT'1VOUPULSSLJ Performance counters are a great way to watch how you are using .NET, IIS, the database, and much more on the operating system. However, the real benefits of performance counters come when you start using them to record data that’s unique to you, such as how many logins you’ve had, what’s the average time for your web service to process a specific request, and anything else you can imagine. With .NET’s excellent PerformanceCounter class doing the work for you, creating performance counters is so simple a manager could do it. By spending no more than an hour on planning and implementation, you can get a ton of actionable information out of your application in production. Performance counters are cheap, easy, and you can never have enough. 7 PB3 RavenDB David Conlin HNPSLSPRLHJHJVT9LK.HL RavenDB has built in protection against the select n+1 problem and also forces you to think about paging early on. It’s really good at making you build database performance in from the ground level. 8 PB4 Don’t call AsEnumerable on a collection before using LINQ Shmuel Englard ISVNLUNSHYKUL'ZOT\LSPL When you’re using an ORM that has LINQ to SQL, such as Entity Framework, do not call AsEnumerable on the collection before using LINQ, even if that gives you options that are easier to work with. If you do, it means your LINQ query is run client- side, rather than converted to SQL and performed on the database server. 9 PBA selection of tips from Ryan Riley panesofglass 5 Never call .Wait() or .Result on a Task Never call .Wait() or .Result on a Task within your application; it can bring your server crashing down. It shouldn’t be necessary to mention this, but so many examples do this that it’s worth reiterating. 10 PB6 Throwing HttpResponseExceptions This is a very handy way to skip to the end of a processing chain when something goes wrong. Sure, you can return an HttpResponseMessage, but it will pass through the filters and handlers on its way out. Throwing an HttpResponseException skips all that and goes right to the end. Use it with the same care you would use in throwing any exception. 11 PB7 Web API tracing Web API integrates tracing, so as to make it very easy to know what’s going on throughout the lifetime of your services. Microsoft has released an add- on package to enable tracing of Web API using System.Diagnostics. You can also find adapters for NLog and log4net on NuGet. This is really helpful for tracking down unexpected responses or unhandled exceptions, especially in production applications. For the best performance, of course, you should use Event Tracing for Windows (ETW). You can find a sample project showing how this can work with Web API in the samples here. 12 PB8 Message Handlers If you only have to handle simple cases and don’t need complex routing, you can handle a given route directly by inheriting from DelegatingHandler and setting this custom handler as the last parameter of config.Routes. MapHttpRoute. This completely bypasses the filter pipeline and requires a lot more manual work, but it also bypasses all the Reflection-based controller and action lookups. Here’s an example: https://gist.github.com/panesofglass/5831674. You can also share common logic between some of the controllers by using this approach and manually hooking up the controller dispatcher, as in https://gist.github.com/panesofglass/5831674. This is slightly better than the filter approach because you can return a response before all the Reflection-based lookups occur, although even the default Reflection- based lookups are fast, because they’re cached. 13 PB9 Database access Most examples of Web API use either Entity Framework directly or show some abstractions such as Repository and/or UnitOf Work, which introduce a number of classes, as well as strong typing. That’s all good. However, in many Web API cases you’re simply exposing, and possibly transforming, data from a data store. You are probably reading in values from a query string, JSON, or XML, and manipulating SQL. All of these are strings. While you can certainly use a serializer to work with inputs and use casting to correctly validate data types, in many cases you can forego the cost of boxing/unboxing or serializing/ deserializing by using dynamics. I have a gist that shows how to do this using Dapper (with Async support): https://gist.github.com/panesofglass/5212462. Use it as a way of eking out extra performance, rather than a standard approach. 14 PB10 WYLMLYOLU`V\»YLWYVÄSPUN accuracy to detail Chris Allen MHSSLUMHJLIVVRJVTJOYPZZ`9LK.HL There is always a trade-off between accuracy and detail, and before you start optimizing you want to be very sure of your data. Sampling techniques tend to be more accurate than instrumentation techniques. If you feel you really must get line-level detail, do it as a second pass after you’ve narrowed down your most expensive call stacks.  PB11 Make the most of connection pooling by closing SQLConnection as soon as possible Robert Haken RUVSLKNLIHZLOHPJa'9VILY/HRLU Close or Dispose your SqlConnection as quickly as possible to take advantage of connection pooling in ADO.NET. Closed connections return to the connection pool, where they remain cached, so you won’t need to create a new connection. Take advantage of the using statement to restrict the scope of your SqlConnections for the short time you need them. 16 PB12 OutputCache Robert Haken RUVSLKNLIHZLOHPJa'9VILY/HRLU Use output caching whenever your rendered HTML does not vary between requests, or if you have only a few variants. If you need isolated updates, consider using the Substitution control, or apply selective output caching by breaking your page into several UserControls, each with its own OutputCache. 17 PB13  Mitchel Sellers mitchelsellers One of the most amazing thing about using async/await keywords for async and background processes is that you don’t have to do anything special to be able to interact with the UI thread. For example, if you trigger an async operation on the UI thread, then interact with a TextBox after the code returns, the .NET framework will automatically marshal the continuation back to the UI thread for you behind the scenes. This is often very helpful, because you need to interact with the UI thread, but there are other times where you really are thread agnostic. In those cases it is important to use ConfigureAwait to set ContinueOnCapturedContext to false. This ensures that the .NET runtime doesn’t have to go through the effort of resuming your method on the thread that called it. In general, this prevents a lot of back-and-forth thread hopping, but in some cases it can be even more helpful. 18 PB OVWWPUN LZWLJPHSS`PUSPIYHY`JVKL ZLVUÄN\YL(HPVHVPKOYLHKConsider this example using ConfigureAwait: byte buffer = new byte0x1000; int numRead; while((numRead = await source.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) 0) await source.WriteAsync(buffer, 0, numRead).ConfigureAwait(false); This code reads an input source in small blocks. If we were working with a large input stream, we could easily have 10, 20, or even more different await cycles. Each cycle through is at least two async calls, with two sets of callbacks to the calling thread. By using ConfigureAwait(false), the total time to execution is much lower and we truly get the best performance out of async. 19 PB14 Be careful of variable allocations Mitchel Sellers mitchelsellers Inside async methods, .NET will create a state machine behind the scenes to lift out local variables for you. That way, when the method resumes, all the values are still there. It’s a fantastic feature, but at it’s not yet smart enough to tell if you still need a particular variable. Consider this code example: var today = DateTime.Now; var tomorrow = today.AddDays(1); await MyTaskHere(); Console.WriteLine(tomorrow); In this example we have two DateTime variables declared - yes, it’s a trivial example, but it proves the point. After the await, we only need to use the “tomorrow” value. However, the state machine will lift out both the today and tomorrow variables. In this example, the object that is used to retain state for the async operation is larger than necessary. This means more variable declarations, and eventually this can lead to additional GC cycles, and so on. 20 PB