共用方式為


ASP.NET application high CPU utilization caused by “System.NotSupportedException”

 

Background:

==========

Customer experienced the high CPU utilization with their ASP.NET application and the CPU will fluctuate.

 

Analysis:

==========

We found a lot of exceptions generated and this could severely impact the application performance. We got the crash dump which signified the “GetManifestResourceNamesForAssembly” throws “System.NotSupportedException”.

 

The following is the call stack:

0:024> !clrstack

OS Thread Id: 0x25dc (24)

ESP EIP

1ca6e990 7c80bee7 [HelperMethodFrame: 1ca6e990]

1ca6ea34 7983a771 System.Reflection.Emit.AssemblyBuilder.GetManifestResourceNames()

1ca6ea40 6ca781b4 System.Data.Metadata.Edm.MetadataArtifactLoaderCompositeResource.GetManifestResourceNamesForAssembly(System.Reflection.Assembly)

1ca6ea6c 6ca785d2 System.Data.Metadata.Edm.MetadataArtifactLoaderCompositeResource.AssemblyContainsResource(System.Reflection.Assembly, System.String ByRef)

1ca6ea84 6ca77cf1 System.Data.Metadata.Edm.MetadataArtifactLoaderCompositeResource.LoadResources(System.String, System.String, System.Collections.Generic.ICollection`1<System.String>, System.Data.Metadata.Edm.MetadataArtifactAssemblyResolver)

1ca6eac0 6ca782ea System.Data.Metadata.Edm.MetadataArtifactLoaderCompositeResource.CreateResourceLoader(System.String, ExtensionCheck, System.String, System.Collections.Generic.ICollection`1<System.String>, System.Data.Metadata.Edm.MetadataArtifactAssemblyResolver)

1ca6eae8 6ca59488 System.Data.Metadata.Edm.MetadataArtifactLoader.Create(System.String, ExtensionCheck, System.String, System.Collections.Generic.ICollection`1<System.String>, System.Data.Metadata.Edm.MetadataArtifactAssemblyResolver)

1ca6eb04 6cb06474 System.Data.EntityClient.EntityConnection.SplitPaths(System.String)

1ca6eb44 6cb077c1 System.Data.EntityClient.EntityConnection.GetMetadataWorkspace(Boolean)

1ca6eb78 6caa339b System.Data.Objects.ObjectContext.RetrieveMetadataWorkspaceFromConnection()

1ca6eb80 6caa45bd System.Data.Objects.ObjectContext..ctor(System.Data.EntityClient.EntityConnection, Boolean)

1ca6ebb0 6caa46b0 System.Data.Objects.ObjectContext..ctor(System.String, System.String)

1ca6ebc4 1f6e2739 JGB.Qy.EntityModel.JGBQyDBEntities..ctor()

1ca6edf0 79e71b4c [GCFrame: 1ca6edf0]

 

 

0:024> kb 10

ChildEBP RetAddr Args to Child

1ca6e908 79eda99c e0434f4d 00000001 00000001 kernel32!RaiseException+0x53 [d:\nt\base\win32\client\thread.c @ 1540]

1ca6e968 79fb48f8 0b1fa198 00000000 00000000 mscorwks!RaiseTheExceptionInternalOnly+0x2a8 [f:\dd\ndp\clr\src\vm\excep.cpp @ 2735]

1ca6ea2c 7983a771 0b1fa198 1ca6ea64 6ca781b4 mscorwks!JIT_Throw+0xfc [f:\dd\ndp\clr\src\vm\jithelpers.cpp @ 4777]

1ca6ea38 6ca781b4 0b1f9e60 00000000 00000000 mscorlib_ni+0x77a771 --- PARAMETERS DUMPED BELOW.

WARNING: Stack unwind information not available. Following frames may be wrong.

1ca6ea64 6ca785d2 1ca6ea8c 0b1ea300 06a5fc8c System_Data_Entity_ni+0x4d81b4

1ca6ea7c 6ca77cf1 0b1ec7ec 0b1ea4d8 0b1f075c System_Data_Entity_ni+0x4d85d2

1ca6eab0 6ca782ea 0b1ea300 0b1e9e9c 0b1ea46c System_Data_Entity_ni+0x4d7cf1

1ca6ead4 6ca59488 0b1ea300 0b1e9e9c 00000000 System_Data_Entity_ni+0x4d82ea

1ca6eaf0 6cb06474 0b1ea300 0b1e9e9c 00000000 System_Data_Entity_ni+0x4b9488

1ca6eb3c 6cb077c1 0b1e919c 00000000 0b1e9148 System_Data_Entity_ni+0x566474

 

Connection String: Data Source=xxxx;Initial Catalog=xxxxx;Persist Security Info=True;User ID=xxxxx;Password=xxxxxxx;MultipleActiveResultSets=True

 

Related CODE

=============

We check the top call stack functions with reflector:

 

Private Shared Function AssemblyContainsResource(ByVal [assembly] As Assembly, ByRef resourceName As String) As Boolean

    If (resourceName Is Nothing) Then

        Return True

    End If

    Dim str As String

    For Each str In MetadataArtifactLoaderCompositeResource.GetManifestResourceNamesForAssembly([assembly])

        If String.Equals(resourceName, str, StringComparison.OrdinalIgnoreCase) Then

            resourceName = str

            Return True

        End If

    Next

    Return False

End Function

 

 

Friend Shared Function GetManifestResourceNamesForAssembly(ByVal [assembly] As Assembly) As String()

    Try

        Return [assembly].GetManifestResourceNames

    Catch exception1 As NotSupportedException

        Return New String(0 - 1) {}

    End Try

End Function

 

Explaination on NotSupportedException:

 

The exception that is thrown when an invoked method is not supported, or when there is an attempt to read, seek, or write to a stream that does not support the invoked functionality.

 

Since the “NotSupportedException” will be thrown frequently, it imposed heavy load to system resources and CPU utilization is pretty high.

 

Solution:

======

Based on our discussion with product team of Entity Framework, the issue can be identified to be a bug which will be fixed in the next version of .NET framework (4.0). I searched through internet and found several issues rose without a solution/workaround. I hence would like to share with you guys our outputs which have been proved to be helpful:

· By default, the EF designer creates a connection string that looks like below :

o connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl; provider=System.Data.SqlClient;provider connection string=&quot;Data Source=.\sqlexpress;Initial Catalog=PeopleBlogs;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />

o The “res://*” in the metadata keyword means that the Entity framework will go through the calling assembly, all the referenced assemblies of the calling assembly and the loaded assemblies in the current app domain to find the specified metadata resource( in the above case, Model1.csdl, Mode11.ssdl and Model1.msl).

· The problem that you are hitting is that we use GetmanifestResourceNames method to see what resources are present in an Assembly but this method will throw a Not Supported exception in case of dynamic assemblies. In .Net 3.5, CLR did not provide any way to check if an assembly was dynamic, so we caught the exception and continued. In .Net 4.0, CLR added a Assembly.IsDynamic property which we now use so that the exception is not thrown.

· There are a couple of ways to work around the problem in .Net 3.5 SP1:

o If you know the full name of the assembly, you can provide a connection string as follows( the text in red is full name of assembly that contains the metadata resources):

§ connectionString="metadata=res://EFResAPP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null/ ;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=.\sqlexpress;Initial Catalog=PeopleBlogs;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />

o You can also specify the path to the metadata folder( or all the files) on the disk:

§ connectionString="metadata= c:\metadatafolderpath\ ;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=.\sqlexpress;Initial Catalog=PeopleBlogs;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />

§ connectionString="metadata= c:\metadatapath\Model1.csdl|c:\metadatapath\Model1.ssdl|c:\metadatapath\model1.msl; provider=System.Data.SqlClient;provider connection string=&quot;Data Source=.\sqlexpress;Initial Catalog=PeopleBlogs;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />

 

Regards,

 

Yawei Wang