Question

I was studying for EPiServer exam and have read this article about EPiServer initialization: http://world.episerver.com/Documentation/Items/Tech-Notes/EPiServer-CMS-6/EPiServer-CMS-60/Initialization/

It describes how to configure initialization to limit assemblies to be scanned during startup, but there is mentioned forceBinFolderScan attribute which is not described. Examples has it always set to true.

I also found another article which describes how to improve startup time of EPiServer site: http://world.episerver.com/Blogs/Alexander-Haneng/Dates/2011/12/Starting-CMS-6-R2-sites-faster-after-build/

Author says to change that attribute to false, but doesn't explain what it means. Does setting it to false stops scanning assemblies at all or scans them only at some conditions?

I have quite large site and it takes several minutes to load. I have lot of assemblies in bin folder, so wanted to limit scanning only to those which contains some initialization modules or plugins.

Was it helpful?

Solution

Because of Asp.Net build system and app startup optimization algorithms all assemblies may not be loaded in app domain. This may hide some assemblies from EPiServer initialization system which is executed during app start. To avoid this - EPiServer allows you to set this forceBinFolderScan flag to force bin/ folder (and probing folder for v7) scanning for assemblies. If flag is set to true - EPiServer is not asking AppDomain for loaded assemblies - but instead scans the filesystem and loads dlls that are not yet loaded.

OTHER TIPS

Decompiled EPiServer source code and found that when forceBinFolderScan attribute is set to true makes EPiServer framework to scan each dll in bin folder. It iterates through all dlls and loads them into AppDomain.

If this attribute is set to false, it doesn't scan bin folder, but relies on ASP.NET assembly loading.

After assemblies are loaded in AppDomain from bin (or not loaded if attribute is false) it gets all assemblies from AppDomain and then filters them based on add/remove configuration. So add/remove tags do not affect bin folder scanning.

Actually this behavior and reason for such behavior is described in EPiServer documentation: MEF - The Discovery Mechanism (see note at the bottom of paragraph). Author just didn't mentioned that it is controlled by forceBinFolderScan attribute.

UPDATE

Here is an example which describes that behavior.

Assume that we have two assemblies: MyPlugins.dll - which contains some plugins and NoPlugins.dll. Also assume that those DLLs are not loaded by ASP.NET at application start.

We have this configuration which tells not to force scan bin folder and include all assemblies except NoPlugins.dll:

  <scanAssembly forceBinFolderScan="false">
    <add assembly="*" />
    <remove assembly="NoPlugins.dll" />
  </scanAssembly>

With such configuration MyPlugins.dll and NoPlugins.dll is not loaded in AppDomain and can't be scanned. So no plugins will be available.

If we set forceBinFolderScan="true":

  <scanAssembly forceBinFolderScan="true">
    <add assembly="*" />
    <remove assembly="NoPlugins.dll" />
  </scanAssembly>

With such configuration both DLLs are explicitly loaded from bin folder into AppDomain. Then filtering occurs and NoPlugins.dll is removed from module/plugin scanning collection. As a result plugins from MyPlugins.dll will be loaded.

UPDATE 2

Tested different configurations to see if optimizations help, but seems that filtering assemblies gives even worse results.

My site has quite a lot of assemblies, so it takes a lot of time to start up. I tried 3 different scenarios.

1:

  <scanAssembly forceBinFolderScan="false">
    <add assembly="*" />
    <!-- Remove assemblies generated by EPiOptimizer -->
    <remove assembly="..." />
  </scanAssembly>

2:

  <scanAssembly forceBinFolderScan="false">
    <add assembly="*" />
  </scanAssembly>

3:

  <scanAssembly forceBinFolderScan="true">
    <add assembly="*" />
  </scanAssembly>

I performed simple tests 3 times each - did iisreset and in Chrome refreshed page and checked timeline (I know it is not perfect test) and here are results:

1: 1.3 min, 1 min, 1.3 min

2: 1 min, 57 s, 1 min

3: 57 s, 57 s, 57 s

I tried these tests else several times in different order, but results were same. So it is not reasonable to make optimizations by adding tag. Seems that it is more expensive to filter out assemblies which are loaded in AppDomain then to scan all of them. The strange thing is that forcing bin folder scan gives better results, but probably it is my test issue.

With that flag set to true, EPiServer will scan the bin folder during the site startup for assemblies that have EPiServer plugins. This detection is done by loading the assemblies and checking if they have classes that have the EPiServer plugin attribute or are EPiServer initialization modules.

You can use this tool to check which assemblies can be removed from that section, in order tom improve startup time.

http://www.david-tec.com/2011/11/Optimising-EPiServer-start-up-times-during-build-with-EPiOptimiser/

With forceBinFolderScan set to true, the EPiServer initialization engine will scan through all assemblies in the bin folder. If the assembly contains a reference to MEF (System.ComponentModel.Composition.dll), then that is scanned for classes marked with the IInitializableModule attribute. Any classes found then have its Initialize method called.

If you set forceBinFolderScan to false, then no assemblies are scanned, and you have to explicitly add any assemblies containing plugins by adding an entry in the scanAssembly element. E.g

<scanAssembly forceBinFolderScan="false">
   <add assembly="AssemblyWithPlugins.dll" />
</scanAssembly>

Or the opposite, you can exclude assemblies known not to contain plugins, or those you don't wish to be scanned, and initialized by the initialization engine:

<scanAssembly forceBinFolderScan="true">
   <remove assembly="AssemblyWithOutPlugins.dll" />
</scanAssembly>

Only scanning specific assemblies can improve site startup time, but you have to remember to update the list with any new assemblies added, or any plugins in those assemblies won't be loaded by EPiServer.

You can see this activity in the Log4Net log, by setting the log level to Warn or higher, you'll see messages such as "Not scanning {0} since it lacks any refererences to MEF" etc.

There is a great blog post about leveraging this feature to improve site startup time

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top