Windows Vista Sxs Activation Context Cache


Sxs activation model is built on top of Actication Context. To create an activation context, use the API CreateActCtx.

Activation Context is used very frequently in Windows. For example, a simple operation like start notepad, open the common file dialog, select a file, will call CreateActCtx many times (I measured 18 times in Vista). With the adoption of Sxs model in VC++ libraries, the usage of activation context will certainly be much higher.

However, creating an activation context is a very expensive operation. It has to resolve the full assembly binding closure, which includes probing for policies for all the assemblies, probing for each assembly, and parse each manifest. If you have read the output of sxstrace, you will certainly understand there are a lot work during CreateActCtx.

Fortunately, activation context is fairly static. Given a steady state, it is likely the same input to CreateActCtx will always create an activation context with exactly the same content. This makes it an attractively target for caching.

In Windows Vista, Sxs implements an activation context cache. The article discusses some detail of the Vista activation context cache.

1. What to cache

Only applications from local disk are cached. For applications running off network or CD, the cache has no effect.

2. Location of the cache

From this article (http://blogs.msdn.com/junfeng/archive/2007/06/12/activation-context-creation-flow.aspx) , we understand that the real work of CreateActCtx is done in CSRSS.exe. And this is where the cache is. The main reason is so that the activation context can be shared with multiple processes.

Since each session has a copy of CSRSS.exe, the cache is not shared across use login sessions.

3. Life time of the cache

The cache is only stored in memory. The first time CreateActCtx is called, it adds an entry to the cache. Next time when the same CreateActCtx is called, the result is returned from the cache immediately, saving the expensive probing and xml parsing. The cache is lost when the machine reboots.

4. size of the cache

The cache in Vista RTM has a fixed size, with a Least Recently Used (LRU) replacement algorithm. This may change in the future.

5. Cache Key

The activation context stores the parsed content of all manifests in the full assembly binding closure. Ideally, the cache key should be the path of all the manifests, and their last modified time.

However, if Sxs uses that as the key to the cache, it means Sxs will have to do all the expensive probing, parsing, which makes the cache useless.

To make a compromise, Sxs chooses the path of the entry manifest of CreateActCtx and its last modified time as the key. This means, if one of its dependent assemblies has changed, it is necessary to “touch” (i.e. change the last modified time of) the entry manifest for Sxs to see the change.

Here is an example. You may have a manifest myapp.exe.manifest depending on VC80, and you decides to deploy vc80 privately. So you have a private Microsoft.VC80.CRT.manifest. In Vista, when you change Microsoft.VC80.CRT.manifest, in order for Sxs to see the change in this manifest, you need to change the last modified time of myapp.exe.manifest.

5. WinSxs

If the dependent manifests are part of the application, this update requirement is very reasonable. However, if the assembly you depend on is in the global WinSxs store, you may not get a chance to update your manifest when the assembly in Winsxs changes. 

Thus in Vista, Sxs adds a WinSxs store timestamp. Whenever a publisher policy assembly is installed to Winsxs store, Sxs updates the timestamp. The activation context cache saves the Winsxs store timestamp in the cache when the cache is created. When Sxs processes a CreateActCtx request, it checks to see if the cached Winsxs store timestamp matches the real Winsxs store timestamp. If it does not, Sxs throws out the cache, and re-creates it from scratch.

The reason that the timestamp is updated only when a publisher policy assembly is installed, is because Sxs requires a publisher policy when update an assembly in Winsxs store.


6. Disable the SxS Cache


Remember in the post DotLocal (.local) Dll Redirection, we know that for private testing, we can use registry HKLM\Software\Microsoft\WindowsNT\CurrentVersion\Image File Execution Options!DevOverrideEnable:REG_DWORD to enable DotLocal Dll redirection for applications with SxS manifest. Since disabling the SxS cache should be really for testing only, the same registry key is used to disable the SxS cache.

Comments (6)

  1. Koby Kahane says:

    Thank you for another great SxS post.

    Is there any way (e.g., registry setting, etc.) to disable Vista’s SxS cache for debugging purposes?

    Since you mentioned publisher policy, I noticed that under Vista, the WinSxS store no longer has a Policies subdirectory with the various assembly policies. Where do things like policy binding redirects reside now?

  2. Koby,

    That is a great question. I’ll update the article.

    I’ll have another post later to discuss the structure under WinSxS.

  3. Koby Kahane says:

    Thanks for the quick response.

    While on the topic of future posts, I’d love to see something on the topic of references in winsxs store.

    I am attempting to install a shared side-by-side assembly to the winsxs store using the SxS API in sxs.dll with a custom installer (i.e., not MSI) under Vista. I install it using IAssemblyCache::InstallAssembly with a reference of type FUSION_REFCOUNT_UNINSTALL_SUBKEY_GUID. The assembly seems to install fine. In my uninstaller, I call IAssemblyCache::UninstallAssembly, with a FUSION_INSTALL_REFERENCE that has the Uninstall subkey GUID and the same szIdentifier. The call returns with S_OK. However, the ulDisposition parameter is zero instead of one of the documented values and when I look in winsxs I see the shared assembly is still there. If I call IAssemblyCache::UninstallAssembly with a NULL FUSION_INSTALL_REFERENCE (which is documented to force-remove the assembly) it still remains in place.

    A description of the winsxs reference mechanism in this and other cases (e.g., opaque references, etc.) would be most appreciated.

  4. Norman Diamond says:

    I think we need a command to reprocess a set of manifests on demand, instead of just knowing (until forgetting) that touching one of the manifest files can force it.  This would be similar to the way regsvr32 can register or unregister a DLL on demand, and even tell us immediately if there’s a problem.

  5. Marcus Ohlhaut says:

    I have now three reports where rebooting did not result in a newly added manifest to be evaluated. In all three cases, it was necessary to touch the *.exe, after which the *.exe.manifest file was read.

    There is an additional issue: Windows Explorer overlays the application’s icon with the Shield icon. In my eyes, the overlay should be displayed for exactly those exes that specify requestedExecutionLevel highestAvailable or requireAdministrator in their manifest (because UAC will prompt for those exes). However, the state of the overlay icon does not match the system’s behaviour in the scenario discussed above.

    Copying the exe with or without the manifest to a new location and/or a new name, touching it will not force the shell to add/remove the overlay accordingly.

    This is all broken.