Caching a LINQ to SQL DataContext - c#

We're in the process of doing some performance optimization for a multi-tenant Web application. Currently, a LinqToSql Data Context is created at the beginning of each web request. The context has a lifetime for the web request and it's injected into the constructor of any objects that need it using Castle Windsor.
We had the thought of caching the context (and a set of objects attached to it) in the session cache for up to a few minutes to optimize the setup costs for follow-on web requests. Is this a good/bad idea? What issues need to be considered?

A bad idea IMO. The biggest problem would be concurrency. Thanks to connection-pooling, the costs aren't that much as long as you use the data-context as a pipe for data, not the data bucket itself.
Cache the data; throw away the data-context.
Attempting to hold onto the data-context additionally doesn't scale out to multiple servers, or support any cache implementation except in-process.
Have you measured the setup costs so that you know whether this is worth considering? I really don't believe that is your bottleneck.

Related

Are there performance issues with IHttpClientFactory creating a new HttpClient every time?

I am developing a Web Api application with Asp.Net Core 6.
I see that the IHttpClientFactory CreateClient method creates a new instance of HttpClient every time.
According to this article
Each time we ask for a HttpClient, we get a new instance, which may
(or may not) use an existing HttpClientHandler. The HttpClient itself
it not too heavy to construct so this is okay.
Do you share this view? Is HttpClient really that light that it doesn't cause performance problems?
If there are actually performance problems, what is the best way to handle them?
A typical web API app has a lot of scoped dependencies that are constructed for each request. Your DbContext is another of these. It's not too heavy. Allocation and garbage collection are highly optimized for the creation of short-lived objects so that developers don't have to worry about it. The most important optimization of all is minimizing cognitive load.
If there are actually performance problems, the best way to handle them will depend on what caused them, which you'll learn by profiling your running app. But there probably won't be performance problems. And if there are, they probably won't be where you expected. This is true even for experienced developers.
The kind of performance you're worrying about right now is raw CPU and a bit of memory I/O. I'm not sure why new developers fixate on this. The bottleneck for most applications is disk and network I/O.

Limit for HttpRuntime cache storage in mvc mini profiler

I believe that the mvc mini profiler stores all the response times in HttpRuntime cache. Please let me know if I'm wrong but if that's the case then what is the max limit for this cache? How many operations can it profile before the cache is full? We are using the mini profiler for profiling operations of a test suite and the test suite will grow over time so I am concerned about this thing. Should I be concerned?
On a related note. When all the tests have been profiled I simply call the Save method in SqlServerStorage class of the mini profiler. And all the response times are saved to a SQL server database. Is there any way I could call the Save method more frequently without starting and stopping the profiler again and again? We just start it at the start of the test suite and end it when all the tests have been profiled. We consider one entry to the MiniProfilers table as one profiling session. Right now I am not able to call the 'Save' method more than once because it needs a new MiniProfilerId everytime it is called.
Any suggestions?
I'm not directly familiar with the mini profiler but I do have quite a bit of experience with the cache. The HttpRuntime.Cache property provides a reference to the System.Web.Caching.Cache class. Which is an implementation of the object cache. In general use this cache is static, so there is only one instance. You can configure the behavior of this Cache using the Web.Config file. Some things to keep in mind about the windows cache, you will never get an out of memory error using it. The cache has a percentage of memory value that tells it how full it should get. Once it gets near that top memory usage percentage it will start to cull objects out of the cache starting with the oldest touched objects. So the short answer to your first question is no, don't worry about the memory limits, one of the main selling points of a managed language is that you should never have to worry about memory consumption, let the framework handle it.
As for #2 I wouldn't worry about it. The cache may throw away the response object itself but I would venture a guess that it's already been included in the result aggregation from the profilier, so you really shouldn't need the original request object itself unless you want to deep inspect it.
Long story short, I wouldn't worry about this anymore unless you hit an real issue. Let the cache do it's job and trust the engineers who built it knew what they were doing until you have proof otherwise.

asp.net session variables to store all global data

I have inherited a project from a developer who was rather fond of session variables. He has used them to store all sorts of global stuff - datatables, datasets, locations of files, connection strings etc. I am a little worried that this may not be very scalable and we do have the possibility of a lot more users in the immediate future.
Am I right to be concerned, and if so why?
Is there an easy way to see how much memory this is all using on the live server at the moment?
What would be the best approach for re-factoring this to use a better solution?
Yes, I would say that you do have some cause for concern. Overuse of session can cause a lot of performance issues. Ideally, session should only be used for information that is specific to the user. Obviously there are exceptions to this rule, but keep that in mind when you're refactoring.
As for the refactoring itself, I would look into caching any large objects that are not user-specific, and removing anything that doesn't need to be in session. Don't be afraid to make a few trips to the database to retrieve information when you need it. Go with the option that puts the least overall strain on the server. The trick is keeping it balanced and distributing the weight as evenly as possible across the various layers of the application.
It was probably due to poor design, and yes you should be concerned if you plan on getting heavier traffic or scaling the site.
Connection strings should be stored in web.config. Seems like you would have to do some redesigning of the data-layer and how the pages pass data to each other to steer away from storing datatables and datasets in Session. For example, instead of storing a whole dataset in Session, store, or pass by url, something small (like an ID) that can be used to re-query the database.
Sessions always hurt scalability. However, once sessions are being used, the impact of a little bit more data in a session isn't that bad.
Still, it has to be stored somewhere, has to be retrieved from somewhere, so it's going to have an impact. It's going to really hurt if you have to move to a web-farm to deal with being very successful, since that's harder to do well in a scalable manner. I'd start by taking anything that should be global in the true sense (shared between all sessions) and move it into a truly globally-accessible location.
Then anything that depended upon the previous request, I'd have be sent by that request.
Doing both of those would reduce the amount they were used for immensely (perhaps enough to turn off sessions and get the massive scalability boost that gives).
Depending on the IIS version, using Session to store state can have an impact on scaling. The later versions of IIS are better.
However, the main problem I have run into is that sessions expire and then your data is lost; you may provide your own Session_OnEnd handler where it is possible to regenerate your session.
Overall yes, you should be concerned about this.
Session is a "per user" type of storage that is in memory. Looking at the memory usage of the ASP.NET Worker Process will give you an idea of memory usage, but you might need to use third-party tools if you want to dig in deeper to what is in. In addition session gets really "fun" when you start load balancing etc.
ConnectionStrings and other information that is not "per user" should really not be handled in a "per user" storage location.
As for creating a solution for this though, a lot is going to depend on the data itself, as you might need to find multiple other opportunities/locations to get/store the info.
You are right in feeling concerned about this.
Connection strings should be stored in Web.config and always read from there. The Web.config file is cached, so storing things in there and then on Session is redundant and unnecessary. The same can be said for locations of files: you can probably create key,value pairs in the appSettings section of your web.config to store this information.
As far as storing datasets, datatables, etc; I would only store this information on Session if getting them from the database is really expensive and provided the data is not too big. A lot of people tend to do this kind of thing w/o realizing that their queries are very fast and that database connections are pooled.
If getting the data from the database does take long, the first thing I would try to remedy would be the speed of my queries. Am I missing indexes? What does the execution plan of my queries show? Am I doing table scans, etc., etc.
One scenario where I currently store information on Session (or Cache) is when I do have to call an external web service that takes more than 2 secs on average to retrieve what I need. Once I get this data I don't need to getting again on every page hit, so I cache it.
Obviously an application that stores pretty much everything it can on Session is going to have scalability issues because memory is a limited resource.
if memory is the issue, why not change session mode to sql server so you can store session data in sql server which requires little code changes.
how to store session data in sql server:
http://msdn.microsoft.com/en-us/library/ms178586.aspx
the catch is that the classes stored in sql server must be serializable and you can use json.net to do just that.

Caching Entity Framework DbContexts per request

I have several classes based on System.Entity.Data.DbContext. They get used several times a request in disparate ends of the web application - is it expensive to instantiate them?
I was caching a copy of them in HttpContext.Current.Items because it didn't feel right to have several copies of them per request, but I have now found out that it doesn't get automatically disposed from the HttpContext at the end of the request. Before I set out writing the code to dispose it (in Application_EndRequest), I thought I'd readdress the situation as there really is no point caching them if I should just instantiate them where I need them and dispose them there and then.
Questions similar to this have been asked around the internet, but I can't seem to find one that answers my question exactly. Sorry if I'm repeating someone though.
Update
I've found out that disposing of the contexts probably doesn't matter in this blog post, but I'm still interested to hear whether they are expensive to instantiate in the first place. Basically, is there lots of EF magic going on there behind the scenes that I want to avoid doing too often?
Best bet would be to use an IoC container to manage lifecycles here -- they are very, very good at it and this is quite a common scenario. Has the added advantage of making dynamic invocation easy -- meaning requests for your stylesheet won't create a DB context because it is hardcoded in BeginRequest().
I'm answering my own question for completeness.
This answer provides more information about this issue.
In summary, it isn't that expensive to instantiate the DbContext, so don't worry.
Furthermore, you don't really need to worry about disposing the data contexts either. You might notice ScottGu doesn't in his samples (he usually has the context as a private field on the controller). This answer has some good information from the Linq to SQL team about disposing data contexts, and this blog post also expands on the subject.
Use HttpContext.Items and dispose your context manually in EndRequest - you can even create custom HTTP module for that. That is a correct handling. Context disposal will also release references to all tracked entities and allow GC collecting them.
You can use multiple context per request if you really need them but in most scenarios one is enough. If your server processing is one logical operation you should use one context for whole unit of work. It is especially important if you do more changes in transaction because with multiple context your transaction will be promoted to distributed and it has negative performance impact.
We have a web project using a similar pattern to the one you've described (albeit with multiple and independant L2S Contexts instead of EF). Although the context is not disposed at the end of the request, we have found that because the HttpContext.Current becomes unreferenced, the GC collects the context in due course, causing the dispose under the scenes. We confirmed this using a memory analyser. Although the context was persisting a bit longer than it should, it was acceptable for us.
Since noticing the behaviour we have tried a couple alternatives, including disposing the contexts on EndRequest, and forcing a GC Collect on EndRequest (that one wasn't my idea and was quickly receded).
We're now investigating the possibility of implementing a Unit of Work pattern that encompasses our collection of Contexts during a request. There are some great articles about if you google it, but for us, alas, the time it would take to implement outweighs the potential benefit.
On the side, I'm now investigating the complexity of moving to a combined SOA/Unit of Work approach, but again, it's one of those things hindsight slaps you with after having built up an enterprise sized application without the knowledge.
I'm keen to hear other peoples views on the subject.

Web application design

I have a project that I have recently started working on seriously but had a bit of a design discussion with a friend and I think he raised some interesting points.
The project is designed to be highly scalable and easy to maintain the business objects completely independently. Ease of scalability has forced some of the design decisions that impede the project's initial efficiency.
The basic design is as follows.
There is a "core" that is written in ASP.NET MVC and manages all interactions JSON API and HTML web. It however doesn't create or manage "business objects" like Posts, Contributors etc. Those are all handled in their own separate WCF web services.
The idea of the core is to be really simple leveraging individual controls that use management objects to retrieve the business data/objects from the web services. This in turn means that the core could be multithreaded and could call the controls on the page simultaneously.
Each web service will manage the relevant business object and their data in the DB. Any business specific processing will also be in here such as mapping data in the tables to useful data structures for use in the controls. The whole object will be passed to the core, and the core should only be either retrieving or setting a business object once per transaction. If multi-affecting operations are necessary in the future then I will need to make that functionality available.
Also the web services can perform their own independent caching and depending on the request and their own knowledge of their specific area (e.g. Users) could return a newly created object or a pre-created one.
After the talk with my friend I have the following questions.
I appreciate that WCF isn't as fast as DLL calls or something similar. But how much overhead will there be given that the whole system is based on them?
Creating a thread can be expensive. Will it cost more to do this than just calling all the controls one after another?
Are there any other inherent pit falls that you can see with this design?
Do you have any other clients for the web service beyond your web site? If so, then I think that the web service isn't really needed. A service interface is reasonable, but that doesn't mean that it needs to be a web service. Using a web service you'll incur the extra overhead of serialization and one more network transfer of the data. You gain, perhaps, some automatic caching capabilities for your service, but it sounds like you are planning to implement this on your own in any case. It's hard to quantify the amount of overhead because we don't know how complex your objects are nor how much data you intend to transfer, but I would wager that it's not insignificant.
It it were me, I would simplify the design: go single-threaded, use an embedded service interface. Then, if performance were an issue I'd look to see where I could address the existing performance problems via caching, multiprocessing, etc. This lets the actual application drive the design, though you'd still apply good patterns and practices when the performance issue crops up. In the event that performance doesn't become an issue, then you haven't built a lot of complicated infrastructure -- YAGNI! You are not gonna need it!
It depends on the granularity of your service calls. One principle in SOA is to make your interfaces less chatty, i.e. have one call perform a whole bunch of actions. If you designed your service Interface as if it was a reguler Business object, then it is very likely it will be too chatty.
It depends on your usage pattern. Also regarding threads, granularity is a key factor.
It looks very much like you're overdesigning the system. Changing a service interface is much more cumbersome than changing a simple method signature. If all your business objects are exposed as services, you are up for a debugging nightmare.
1.
Web Service oriented design is reasonable if you have one or more non-native clients (that cannot access to you logic directly). For example AJAX, Flash, another web application from different domain, etc. But using WCF for you application when you can make calls to you logic directly is very bad idea.
If later you will need Web Services you can easily wrap you domain model with Service Layer.
2.
Use thread pool to minimize thread creation calls when necessary. And answer on this question depends on what you need to achieve, it is not clear from you explanation.
3.
Main pit fall is that you are trying to use to many things. Overdesigning probably a good term.
If you are worried about the overhead in calling a WCF service then you can use the null transport. This avoids all the necessary serialization and deserialization that would happen if the client and server were on separate machines.
It doesn't sound like something that'll be highly scalable; at least, not to lots of users per second. Slapping in WCF all over the place will slow things down, by creating far more threads than you need. If the WCF calls don't do much work, then the thread overhead will hurt you hard. Although it'll be multithreaded, multiple calls to ASPX pages are already multithreaded. You might speed up your system when just one person is running, but hit performance hard if lots of users are running. Eg, if one user requests the page, then ten sepearate WCF calls may gain from multithreading. However, if you have 100 page reqests per second, that's 1000 WCF calls per second. That's a lot of overhead.

Categories