简体   繁体   中英

Slow reflection with NHibernate (additional call of CodeAccessSecurityEngine)

I've got serious problem with our application. We are developing GUI application + server which can be used in two different purposes.

  1. GUI application invoking embedded server which runs in the same process as embedded server
  2. GUI application is communicated with separated standalone server application via REST - separated process.

We are using spring.net so there are small differences between both solutions. Server is just one context so the solution #1 instantiates it directly as new spring.net context and solution #2 has two exe files: GUI.exe + standalone server exe. As I already said, both application flows are almost the same.

Whats the issue? Standalone server is three times slower than solution #1. It means separated standalone server application is three times slower than embedded one.

I've used DotTrace and find the find the reason in 10 minutes. Server uses NHibernate which get/set properties via reflection very often.

In the first solution when GUI application hosted in embedded server, reflection is very quick. But when it's on separate standalone server perform, reflections tasks are very slow.

Here are stack traces for slow solution:


- 5,874 ms  System.RuntimeMethodHandle.PerformSecurityCheck(Object, IRuntimeMethodInfo, RuntimeType, UInt32)
  - 4,642 ms  System.Security.CodeAccessSecurityEngine.ReflectionTargetDemandHelper(Int32, PermissionSet)
  - 36ms System.Security.CodeAccessSecurityEngine.CheckSetHelper(CompressedStack, PermissionSet, PermissionSet, PermissionSet, RuntimeMethodHandleInternal, RuntimeAssembly, SecurityAction)
  - 1ms System.Reflection.RuntimeMethodInfo.get_Value

Fast solution:


- 5 ms  •  10,740 calls  •  System.RuntimeMethodHandle.PerformSecurityCheck(Object, IRuntimeMethodInfo, RuntimeType, UInt32)
  -  1 ms  •  10,740 calls  •  System.Reflection.RuntimeMethodInfo.get_Value

As you can see, the slow solution killer is the aditional call to System.Security.CodeAccessSecurityEngine.ReflectionTargetDemandHelper. Standalone server should automatically run as full trusted as well as GUI does.

Do you have any solutions how to switch this check off or how to set up the standalone server application? When I compare both app.configs, i'm not able to find any difference regarding described issue.

EDIT:

We have finally investigated the reason and the solution was the only clear.

Standalone server instantiates spring.net's context with using ContextRegistry.GetContext() but embedded one uses standard new XmlApplicationContext(new[] {"..."}) . This simple difference results into so significant performance hit.

It seems that spring's app.config context handler do "any wrong stuff" but we have not time to investigate the real purpose yet.

How are the embedded and standalone servers being created? Are they generated code or code that you've written? Have you verified that the standalone server is running under full trust? What framework is being used to handle the REST requests? I've used NHibernate in a similar manner before (client talking to web service and web service using NH) and never seen a 5-6 second delay per request because of CAS. Are you sure that you are caching your SessionFactory properly?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM