Add-ons and extensions often get accused of slowing down browser performance. The short answer is true, but that discounts a lot of scenarios and value. In many cases, you’ll have a better experience when you have the right extensions installed – and that can speed your personal performance if not the bench speed of the browser.
The browser itself can bring its own nuance to the performance equation. The discussion below relates to developing add-ons for Internet Explorer (IE) and unique properties of that environment. The way IE is built can impact add-on performance. Here are a few things to keep in mind.
IE Process Overview
With Internet Explorer 7, Microsoft made significant changes, primarily around how a browser page is loaded. The key focus was to ensure that a malicious site or code would not have full access to a user’s machine (especially if the user is running with an administrative account).
When Internet Explorer is opened, it starts a new process, shown in the Figure as the Frame Process. It controls the IE Frame, menus and such, and runs at the normal user-level of permissions so that it can interact with configuration files, the registry and similar program level functions.
Next a child process is started, which is shown above as a Browser Process. This process is the container for one or more browser tab windows. Even though as a window it appears within the IE Frame Process, it is actually running in its own process with restricted permissions. This is to prevent any web site from attempting to access the user’s system directly, and has access to only a limited set of resources.
In the Browser process the actual browser window is opened, hosting the target web site. This browser window then loads any add-ons that are enabled.
When Internet Explorer is first installed, it performs a calculation based on the system – its performance, available memory, some other factors and comes up with a number that it stores in the registry. This number determines the maximum number of Browser Processes it will start. As more browser tabs/windows are opened, additional Browser Processes are started until this maximum number is reached. In the above diagram, you can see that Browser Process 1 is started for Browser Tab 1, Browser Process 2 is started for Browser Tab 2, and Browser Process 3 is started for Browser Tab 3. For this example, the maximum number of browser processes is three, and any additional tabs are opened within the existing Browser Processes in a round-robin fashion.
So, how does this affect your add-on?
Typical IE Add-on Development
Add-ons are loaded into each browser tab, so that an add-on can interact with that particular website directly. But because each browser tab starts the process over again, you start to see where the performance burdens begin to accrue.
For example, a typical add-on using .NET Framework causes the following actions occur:
- The Browser Tab initiates the load of the add-on.
- The Windows operating system detects that the add-on uses a managed code DLL running from within the .Net Framework.
- To load the add-on, the Windows OS first starts the .Net Framework Core in the current process (the Browser Process as described above).
- The .Net Framework Core creates an AppDomain, which is where the managed DLLs are loaded into.
- Before anything else, the primary System DLL files are loaded into the AppDomain, which are required by all .Net applications. These are already precompiled into native code, and are loaded directly into the AppDomain.
- Next the add-on DLL is loaded. In order to load, it has to be converted from its format as compiled in the DLL (.Net intermediate code) into the native code of the system. This is done with the Just-In-Time (JIT) compiler and the resulting native code is stored in a temp directory. This native code is then loaded into AppDomain.
- As the add-on starts to run (initialization code), additional assemblies are loaded. Systems that are pre-compiled are loaded directly, other ones are JIT-compiled and then loaded.
The default configuration from the .Net Framework is that this process is repeated in every AppDomain, plus a new AppDomain is created for the add-on in every browser tab, with this process repeated every time. The performance overhead of the add-on starts to become noticeable to the user of the browser.
Delays occur because:
- Each new tab is starting the .Net Framework Core
- Which then creates the new AppDomain and loading all the DLL files into it
- In the case of the managed DLLs, they need to be JIT-compiled first
Alternative IE Add-on Development Approach
Alternatively, you could take an approach of using Unmanaged code to avoid the process overhead of the .NET Framework. This requires you to take on a larger time and resource commitment building process and systems on your own. The memory allocation, type safety, security, and so on, needs to be taken care of by the developer. It’s a lot of work and you regularly see unmanaged code that is prone to memory leaks like buffer overruns, pointer overrides and so forth.
Assuming you navigate those pitfalls, the upside is performance gains. Because your process is not part of the .Net Framework, the system does not need to start the .Net Framework or JIT compile it before it can be loaded. Result? Faster load times.
Exploring this further, you may use unmanaged C++ code (i.e. not based on .Net Framework) for the browser add-on. This is what IE starts when loading the add-on. The unmanaged code would then initiate the .Net Framework core with custom load flags set. In this case, you instruct the .Net Framework core (which runs in the context of the Browser Process) that you want to share the managed code assemblies that are loaded in the primary AppDomain with any child AppDomains. This differs from the standard load behavior described above, where every AppDomain loads its own copies of the assemblies, and requires loading and JIT compiling from the file system every time.
The Primary AppDomain is created once for the Browser Process, and not for every Browser Tab/Window. You load the standard System assemblies, and the managed portion of your add-on. Once these are completed for the Browser Process, the unmanaged code would return. If the .Net Framework core and loaded the primary AppDomain is detected, the unmanaged add-on code can return immediately, greatly reducing the add-on load time.
Hopefully, this gives you some options to explore as you look to improve the performance of your own IE add-ons. If you have your own ideas to share, please add them in the comments below.