Waaay more connections than necessary
We had a dump where we got a .NET OutofMemory exception. The ASP.NET folks looked at the dump and saw a large number of rooted TDS objects. I wasn't sure where those were coming from, so pulled up the dump to evaluate this.
0:033> !dumpheap -stat
...
0x65400574 11,959 1,339,408 System.Data.SqlClient.SqlConnectionString
0x654049c0 11,959 1,482,916 System.Data.SqlClient.TdsParser
0x65405fdc 11,958 1,530,624 System.Data.SqlClient._SqlMetaData
0x65404744 11,959 1,674,260 System.Data.SqlClient.SqlInternalConnectionTds
0x79101fe4 36,452 2,041,312 System.Collections.Hashtable
0x65404dec 11,959 2,248,292 System.Data.SqlClient.TdsParserStateObject
0x7910be50 206,356 2,476,272 System.Boolean
0x65400808 233,910 4,678,200 System.Data.Common.NameValuePermission
0x65400b64 221,950 5,326,800 System.Data.Common.NameValuePair
0x7912d8f8 257,690 5,741,720 System.Object[]
0x000df590 175 10,314,064 Free
0x7912d9bc 36,461 13,194,048 System.Collections.Hashtable+bucket[]
0x790fd8c4 493,301 34,033,216 System.String
0x7912dae8 48,478 192,431,300 System.Byte[]
Total 1,994,862 objects, Total size: 290,427,832
Notice any pattern? 11959 seems to be pretty repetitive. I especially don't understand why we have almost 12000 internal connections unless....
Yep - customer is not pooling!!
First, dump out the method table for the System.Data.SqlClient.SqlConnectionString
0:033> !dumpheap -mt 0x65400574
This produces a ridiculously large (11,959 members!) list of SqlConnectionStrings. So, let's dump out one at random:
0:033> !do 0x2e016064
Name: System.Data.SqlClient.SqlConnectionString
MethodTable: 65400574
EEClass: 6544c6c0
Size: 112(0x70) bytes
GC Generation: 2
(C:\WINDOWS\assembly\GAC_32\System.Data\2.0.0.0__b77a5c561934e089\System.Data.dll)
Fields:
MT Field Offset Type VT Attr Value Name
790fd8c4 4000bce 4 System.String 0 instance 2e015e50 _usersConnectionString
And then keep drilling into him...
0:033> !do 2e015e50
Name: System.String
String: Data Source=cpsrv;Initial Catalog=Changepoint;Integrated Security=False;User ID=xxxxx;Password=yyyyy;Enlist=False;Pooling=False;Asynchronous Processing=True;Application Name=SqlQueryNotificationService-ac370dde-d9c4-4cbe-9d82-7d7a8df159c6
Let's do another one, too
0:033> !do 0x2c5b9aa8
Name: System.Data.SqlClient.SqlConnectionString
MethodTable: 65400574
EEClass: 6544c6c0
Size: 112(0x70) bytes
GC Generation: 2
(C:\WINDOWS\assembly\GAC_32\System.Data\2.0.0.0__b77a5c561934e089\System.Data.dll)
Fields:
MT Field Offset Type VT Attr Value Name
790fd8c4 4000bce 4 System.String 0 instance 2c5b9894 _usersConnectionString
0:033> !do 2c5b9894
Name: System.String
MethodTable: 790fd8c4
EEClass: 790fd824
Size: 530(0x212) bytes
GC Generation: 2
(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: Data Source=cpsrv;Initial Catalog=Changepoint;Integrated Security=False;User ID=xxxx;Password=yyyy;Enlist=False;Pooling=False;Asynchronous Processing=True;Application Name=SqlQueryNotificationService-78b81d9b-ecd9-400d-8435-6e745d449c96
Note that in both cases, the connection string has Pooling=False and an application name that has a GUID. Either one of these will prevent good use of connection pooling.
The customer needs to turn pooling on, plus eliminate the GUID from the Application Name.
Comments
- Anonymous
April 05, 2009
PingBack from http://www.anith.com/?p=26520