Do IIS Web Applications that use the same App Pool share DLLs in memory? - asp.net-core

I inherited a large web site. To the user, it consists of 20 "modules" with different functionality. Each module can be accessed via a menu from each other module.
Each module has been implemented as a separate Web Application in IIS, all sitting under the Default Web Site. They all use the same App Pool. All implemented in ASP.NET Core (net5).
The modules share about 70% of their code. This library code sits in several projects. The web application projects all have References to the library DLLs. After everything has been built, the bin folder of each web application project has a copy of the library DLLs (so there are then 20 copies of each library DLL on disk).
Assuming that web application 1 is receiving requests and has been loaded into server memory. If web application 2 then gets loaded into server memory, will the library DLLs then be loaded into memory again for web application 2? Or will web application 2 use the library DLLs that have already been loaded into memory for web application 1? As in, after web applications 1 and 2 have been loaded in memory, will there be 1 copy of the library cod in memory or 2 copies?
Reason behind the question is that I need to reduce memory usage on the web server. There are no operational benefits to having separate web applications. They are all deployed together in one go. We never start or stop just one of them, it is always all or nothing. Wondering if I can save memory by having 1 big web application instead of 20 smaller web applications.

Your ASP.NET Core web apps in the same application pool are configured to use out-of-process hosting, so all their assemblies/libraries are loaded into individual .NET Core processes (Kestrel based) (dotnet.exe usually, or your own executable when self contained deployment is used).
Diagrams in that Microsoft article make it super easy to understand the relationship among the runtime processes.
In that mode, IIS worker process(es) w3wp.exe only loads the ASP.NET Core module to work as reverse proxy.
Combining the two above, the answer to your question Do IIS Web Applications that use the same App Pool share DLLs in memory? is rather clear that nothing is shared and you cannot share anything either due to the process boundary.

Related

Understanding ASP.NET Core with Apache

In IIS we had an aspnet_isapi extension that handles the request, it then spawns a process w3wp.exe, w3wp.exe then loads and starts the CLR and then CLR does its job.
Now, Kestrel is configured inside the Main() method, so first the Main() should execute, so who starts the Core CLR ? is it IIS for windows and Apache for Linux? Do IIS and Apache know how to search and start Core CLR?
What I know is, when a .NET application is executed at that time the control will go to the operating system, the OS creates a process to load CLR.
The program used by the operating system for loading CLR is called runtime host, which are different depending upon the type of application that is desktop or web-based application i.e.
The runtime host for desktop applications is an API function called CorbinToRuntime.
The runtime host for web-based applications is the ASP.NET worker process (aspnet-wp.exe).
So, how is it possible that first the Main() method will execute and then the CLR, i am not able to digest it, please help.
Forget about everything you know about IIS.
For Apache or nginx, just run your ASP.NET Core console application (who initializes Core CLR) at a local port (http://localhost:5000 for example), and then set up reverse proxy rules to forward external traffic to that port.
That's roughly what Microsoft documented in this article
Such reverse proxy setup is common, as other web stacks (Node.js, Python, Go) are using the same approach.
Because of this specific setup, Linux launches your .NET Core console app by analyzing the COFF envelope (of dotnet executable, or your own executable for self contained deployment) to locate the native entry (not your managed Main).
Apache/nginx is not involved in anyway.
Calling into this entry triggers CoreCLR initialization, and in turn your managed assemblies are loaded and managed Main is called.
You might find articles like this helpful.

Why does .NET Core build generate an EXE file but not generate a dll file?

I have .net core project, When i build that project it generates .exe file but not .dll, My requirement is to create .dll of project and host it in IIS server. how to generate .dll file,what settings need to be done.
An ASP.Net Core binary is meant to be a self-hosted application, so the .exe embed a web server (the default one being Kestrel) that can accept HTTP requests. One of the challenges behind ASP.Net Core was to make it self-contained and decoupled from IIS. So having an .exe is perfectly expected, you can double click on it and you'll get a web server running.
That being said, in a standard production environment, you are supposed to have a webserver like IIS sitting in front of your ASP.Net Core app and acting as a reverse proxy, forwarding the requests to the app. So having an .exe file will not prevent you from hosting behind IIS.
I learned a lot from this article: https://weblog.west-wind.com/posts/2016/Jun/06/Publishing-and-Running-ASPNET-Core-Applications-with-IIS
If there is a way to create a DLL with ASP.Net Core, I don't know it, but what would be the point?
Switching the output type in your project properties to Class Library from Console Application will generate a DLL instead of an EXE.

profiling wcf and mvc 4 with miniprofiler

I am working with miniprofiler and find it very helpful.
I have an mvc4 application that gets its data from a set of wcf services over named pipes. I am in control of both the mvc4 app and the wcf services.
I was reading this post on how to profile the lower layers of the architecture, but maybe I missing something but could not find MvcMiniProfiler.WCF package or part of the MvcMiniProfiler package. Is this still available?
Another question I have is it possible to set up miniprofiler to log to file? I have automated performance tests that are ran against my application that I would like to record the profiling for to understand how the application behaves under load.

How to Debug multiple Sharepoint services on the same machine?

I need to debug a Sharepoint WCF service that is deployed for Sharepoint 2010. However, a colleague needs to debug another Sharepoint service deployed on the same phyical machine. If we debug at the same time strange things occur with the Visual Studio debugger. For example, his debugger would break at breakpoints I have set, or I am seeing exceptions raised by his code. Mind you, we are debugging different services in different solutions. From the information I have gathered so far, this behaviour is like this because there is only one w3wp process per application pool that both the Visual Studio Debugger instances attach to.
So I figured I should try running my service in another applicaion pool to get a different w3wp.exe to attach to. Here is what I tried, but I am not sure, if what I attempted makes any sense, please clarify:
IIS Manager shows that there are two different Sharepoint application pools (excluding the one for Central Adminisitration) and a Site for each. So I tried deploying my service using the other application pool by setting the deployment location to the URL of the other site. However the virtual _vti_bin directory of the service still maps to the same physical directory ...\Web Server Extensions\14\ISAPI\. Deploying from Visual Studio works, but getting a ServiceReference does not. Trying to open <url>/_vti_bin/MyService.svc/MEX shows an error page telling me that therer is already a binding instance associated to the URL. So, I guess this is either not the way to do this, or it is simply not possible to "isolate" services in this way. I am very hesitant to just trial-and-error with IIS Manager or Sharepoint Central Administration settings, because I feel I don't know enough to avoid screwing things up.
Could someone tell me how I can solve this?
The URL you specify when deploying in Visual Studio can be misleading. If you have a sandboxed solution, it gets deployed to this location. If you have a farm solution, it gets deployed centrally and it uses the URL to figure out what application pool to recycle. If you have web application specific settings in the solution i.e. safecontrols), these will be applied to the web application hosting the URL.
The _vti_bin is available to every site in the whole farm; as is _layouts. Since a service will be exposed through multiple URL's (one for each site) the SharePoint team has created custom factory classes to make this possible. Check out one of the built in svc files, and you will see that it uses a special factory class. Use this in your svc file to expose your service in all sites.
As for the debugging, it's never a good idea to have multiple developers using the same machine. If you really want to do it, I suggest using two web applications with different application pools. That way each developer has their own process to attach to. If you use different accounts for the application pool, it makes it easier to find the correct one in the 'attach process' dialog.

How do I start an out of process instance of a WCF service?

I would like to start a new instance of a wcf service host from another (UI) application. I need the service to be out of process because I want to make use of the entire 1.4GB memory limit for a 32bit .NET process.
The obvious method is to use System.Diagnostics.Process.Start(processStartInfo) but I would like to find out whether it is a good way or not. I am planning on bundling the service host exe with the UI application. When I start the process, I will pass in key parameters for the WCF service (like ports and addresses etc). The UI application (or other applications) will then connect to this new process to interact with the service. Once the service has no activity for a while, it will shut itself down or the UI can explicitly make a call to shut the service down.
You can definitely do this:
create a console app which hosts your ServiceHost
make that console app aware of a bunch of command line parameters (or configure them in the console app's app.config)
launch the console app using Process.Start() from your UI app
That should be fairly easy to do, I'd say.
Perhaps I'm completely offbase here, but I don't think there is a 1.4 GB memory limit for .NET processes. The memory allocated for each process is managed by the OS. For 32-bit opeating systems, there is a 4 GB memory space available, but that is shared among all of the processes. So while it may appear that there is only 1.4 GB available, it's not technically true.
The only reason I bring that up is to say that the other way to approach this would be to load your WCF service inside a separate AppDomain within your UI application. The System.AppDomain class can be thought of as a lightweight process within a process. AppDomains can also be unloaded when you are finished with them. And since WCF can cross AppDomain boundaries as well as process boundaries, it's simply another consideration.
If you are not familiar with AppDomains, the approach that #marc_s recommended is the most straightforward. However, if you are looking for an excuse to learn about AppDomains, this would be a great opportunity to do so.