davidebbo / WebActivator

Apache License 2.0
242 stars 49 forks source link

WebActivator is indirectly causing performance degradation in Visual Studio #8

Closed LordZoltan closed 11 years ago

LordZoltan commented 11 years ago

Rather than give the full rundown I'll link to a StackOverflow Q&A I created a few months back.

The outline is that Visual Studio will execute any WebActivator - controlled Pre-Start code frequently because of the way that it spins up a virtual HostingEnvironment in order to get pages built for intellisense. VS' memory usage (or in VS2012's case the webhost that it uses) can then balloon, as it takes on any overhead that would normally be associated with running the website.

The reason why this came to my attention was - as my SO question says - I was working on a site that opens a UDP listener in such a pre-start method (used for web-farm synchronisation), and then when I went to debug the site locally I found that the port was already in use; with the offending process being VS2010.

As you'll see from my own answer to this question the way I've fixed this is to add a static class called HostInformation to the WebActivator namespace, with a static property called IsDevelopmentEnvironment. At the beginning of all my pre-app start methods I now call this and return before doing anything else:

public static void Start()
{
  if(HostInformation.IsDevelopmentEnvironment)
    return;
  /*carry on... */
}

The implementation is pretty hacky, but as it stands there doesn't appear to be very much else we can do.

I'm pretty certain there are many people out there experiencing VS issues (I experienced not only bad memory usage, but a very slow editor experience in Razor) as a result of this.

I know it's not technically WebActivator's fault, but it would be great if you could push such a fix down into the bowels of the system!

brgrz commented 11 years ago

I can confirm this issue and it has surfaced to my attention when I was spinning up the RavenDB Embedded edition in the PreApplicationStartMethod, resulting in the RavenDB files to get locked by the Microsoft.VisualStudio.Web.Host process and are as such unavailable to other processes such as the IISExpress giving the exception at runtime.

The problem happens when you run Build, it will at this time spin up the Microsoft.VisualStudio.Web.Host process and this process then remains running indefinitely, maintaing a lock on all resources and services that were registered in PreStart. I do most of the IoC registration in PreStart because it is how it's supposed to be done specifically with ServiceStack's Funq, check for more info here https://github.com/ServiceStack/ServiceStack/wiki/The-IoC-container

davidebbo commented 11 years ago

@LordZoltan: one comment about your IsDevelopmentEnvironment: instead of writing your own logic to detect this, you can just use System.Web.Hosting.HostingEnvironment.InClientBuildManager. See this answer for more details on this.

davidebbo commented 11 years ago

But looking at the general issue, I don't think there is a whole lot that WebActivator can do here, since there are cases where we really do want this code to run in VS/aspnet_compiler.

I suppose one thing it could do is add a flag to PreApplicationStartMethodAttribute that we make the code not run in these scenarios. This way, the author of the PreStart method can easily make the decision. Today, you can do this using HostingEnvironment.InClientBuildManager, but that wouldmake it slightly easier.

LordZoltan commented 11 years ago

Hi David, thanks for your response(s).

I understand; in fact I can see how cool it can be to have pre-app-start code being called by the ASP.Net compiler. So yes, perhaps a flag on the attribute is a great idea. I would guess that a large majority of us wouldn't want such code to execute outside a 'proper' Web host, and that potentially lots of people might be experiencing issues as a result. Pure supposition though!

Thanks for the heads up on the InClientBuildManager property, I'll give it a shot and if it has the desired effect will get rid of my hacky code!

davidebbo commented 11 years ago

I just pushed a signed WebActivatorEx package: http://nuget.org/packages/WebActivatorEx/. Can you please give it a try?

Let's call it experimental at this point, as I need more feedback about it being what we really want before starting to advertise it for general use.

LordZoltan commented 11 years ago

Hi David,

Sure will, and totally understand.

If I can get on to it today I will, but if not i'll definitely have a play on Monday.

Thanks,

Andras

davidebbo commented 11 years ago

You know what, I actually meant to put that comment in in https://github.com/davidebbo/WebActivator/pull/3 and not this bug. Though that new package does in fact have this fix as well.

Now you need to specifically add a RunInDesigner flag to get the behavior you don't want (that used to be default). It's a breaking change, but since it's a new package, we can get away with it. :)

LordZoltan commented 11 years ago

An elegant solution - and it all works perfectly, David - including enabling the behaviour I don't want (we do indeed have another project internally in which we precompile and therefore being able to use webactivator hooks to register dynamic modules for precompilation is handy).

I also don't foresee the strong naming being an issue for us either - although I'm not wishing to add to that debate(!). I think you're right in what you've said on that other thread - in the web environment the binding redirect generally works pretty well; indeed it's used habitually now for the MVC upgrade process and I've never had it fail there.

Thanks for your hard work here and in the past - hopefully it won't cause issues for others and you'll be able to make it 'official'.

davidebbo commented 11 years ago

Thanks for the feedback!

The transition to this new package is likely to take a while, and I'm hoping the transition won't be too rocky!

davidebbo commented 11 years ago

This is fixed in WebActivator 2.x