这篇文章是前篇文章《Gettng started with windbg-part I》的继续,假设你已经看过那篇文章,如果没有请先阅读。我们继续在同一个转储文件上进行试验,并在上篇终止的地方继续我们的讲解。
更多命令
上次我们使用许多 sos中扩展命令查看运行中的堆栈,客户请求,线程的CPU使用率等等。
深入到调用堆查看客户请求的唯一名称,本次课程中,继续使用这些命令,并学习一些新的命令。
!dumpstackobjects (!dso)
现在,假设你想查看当前特定线程的堆栈中所有托管对象,我们有办法办到吗?答案是肯定的,使用 !dumpstackobjects (或 简称!dso )就可以办到。假设我们在当前线程中运行了该命令,将会看到当前堆栈中所有引用对象列表。整个输出内容就像下面这样(删除了大小):
0:010> !dumpstackobjects Thread 10 ESP/REG Object Name 0xd0fef88 0xf38edc System.Security.PermissionSet 0xd0ff184 0x1d298ad8 System.Data.DataRow 0xd0ff18c 0x1cfff794 System.Data.Index 0xd0ff190 0x1cfff794 System.Data.Index 0xd0ff1a8 0x1d5a9dd8 System.Byte[] 0xd0ff5e8 0x1d00808c System.Data.OracleClient.OciStatementHandle 0xd0ff5ec 0xf59b34 System.Data.OracleClient.OciErrorHandle 0xd0ff60c 0xf59b34 System.Data.OracleClient.OciErrorHandle 0xd0ff614 0x1d00808c System.Data.OracleClient.OciStatementHandle 0xd0ff61c 0x1d0080a4 System.Data.OracleClient.OracleDataReader 0xd0ff620 0x1d00808c System.Data.OracleClient.OciStatementHandle 0xd0ff628 0xf59b34 System.Data.OracleClient.OciErrorHandle 0xd0ff64c 0x1d0080a4 System.Data.OracleClient.OracleDataReader 0xd0ff664 0x1d0093d4 System.Data.Common.SchemaMapping 0xd0ff678 0x1d0080a4 System.Data.OracleClient.OracleDataReader 0xd0ff6b0 0x1d0093d4 System.Data.Common.SchemaMapping 0xd0ff6b4 0x1d007ef0 System.Data.DataSet 0xd0ff6b8 0x1d008054 System.Data.OracleClient.OracleDataAdapter 0xd0ff6c4 0x3b959a50 System.Data.OracleClient.OracleCommand 0xd0ff6d8 0xf5a49c System.String Table 0xd0ff6f0 0x1d0080a4 System.Data.OracleClient.OracleDataReader 0xd0ff6f4 0xf5a49c System.String Table 0xd0ff6fc 0xf5a49c System.String Table 0xd0ff718 0xf5a49c System.String Table 0xd0ff71c 0xf5a49c System.String Table 0xd0ff728 0x1d0080a4 System.Data.OracleClient.OracleDataReader 0xd0ff72c 0x3b9599fc System.Data.OracleClient.OracleConnection 0xd0ff73c 0x3b9599e8 Dba.Wrapper.OracleWrapper 0xd0ff74c 0x3b9599e8 Dba.Wrapper.OracleWrapper 0xd0ff750 0x3b959a50 System.Data.OracleClient.OracleCommand 0xd0ff75c 0x3b959a50 System.Data.OracleClient.OracleCommand 0xd0ff760 0xf5a49c System.String Table 0xd0ff784 0x3b959a50 System.Data.OracleClient.OracleCommand 0xd0ff788 0xf5a49c System.String Table 0xd0ff794 0x3b9599e8 Dba.Wrapper.OracleWrapper 0xd0ff798 0x1d007ef0 System.Data.DataSet 0xd0ff7b0 0x1d007ee0 System.Object[] 0xd0ff7b4 0x1d004690 System.String SELECT b4.contract_config_id,
0xd0ff7bc 0x1d004660 System.Object[] 0xd0ff7e0 0x1d004690 System.String SELECT b4.contract_config_id,
0xd0ff7e4 0x3b9599e8 Dba.Wrapper.OracleWrapper 0xd0ff7ec 0xf311f4 System.String 0xd0ff804 0x3b9599e8 Dba.Wrapper.OracleWrapper 0xd0ff808 0x1cfff894 Sample.Business.Contract.Template.EvaluatorParameter 0xd0ff814 0xf36558 System.Globalization.NumberFormatInfo 0xd0ff828 0xf311f4 System.String 0xd0ff830 0xf68e8c System.String case b3.materiel_flag when 'N' then b4.t 0xd0ff838 0xf67850 System.String zh-CN 0xd0ff83c 0x3b9599e8 Dba.Wrapper.OracleWrapper 0xd0ff858 0xf6710c System.String Successful update! 0xd0ff85c 0x3b95be28 System.String 3052226 0xd0ff870 0xf67850 System.String zh-CN 0xd0ff874 0xf67070 System.Globalization.CultureInfo 0xd0ff878 0xf67014 Sample.Access.Base.Component.UserInfo 0xd0ff884 0x1cfff894 Sample.Business.Contract.Template.EvaluatorParameter 0xd0ff888 0xf6710c System.String Successful update! 0xd0ff88c 0x3b95be28 System.String 3052226 0xd0ff8a4 0xf6710c System.String Successful update! 0xd0ff8ac 0xf38900 System.String {0} [{1}] 0xd0ff8c8 0xf311f4 System.String 0xd0ff8cc 0x3b95be70 Sample.Common.ClientComponent.ProcessBarFrm 0xd0ff8d0 0x1cfff848 Sample.Business.Contract.Template.TemplateEvaluator 0xd0ff8e4 0x3b95a7cc System.String S3NJ20071030-01DSL 0xd0ff8f8 0xf311f4 System.String 0xd0ff908 0x1cfff7d0 System.String 3052226 [Successful update!] 0xd0ff90c 0x3b9599e8 Dba.Wrapper.OracleWrapper 0xd0ff910 0x3b959a8c Sample.Business.Contract.MaterialConf.GenerateMaterialMng 0xd0ff918 0xf5b3ac System.String False 0xd0ff934 0xf311f4 System.String 0xd0ff938 0x3b95a7cc System.String S3NJ20071030-01DSL 0xd0ff940 0x3b95be28 System.String 3052226 0xd0ff948 0xf569f8 Sample.UI.Win.Service.MaterialManager 0xd0ff960 0x18467a6c System.String 623b3280-0a02-4b0e-ac58-f44e6d0308e0 0xd0ff978 0x3b95be10 System.Collections.ArrayList/ArrayListEnumeratorSimple 0xd0ff994 0x3b95bb08 System.Data.DataRow 0xd0ff998 0x3b959cdc System.Data.DataTable 0xd0ff99c 0x3b959a8c Sample.Business.Contract.MaterialConf.GenerateMaterialMng 0xd0ff9a0 0x3b95998c System.String f873f332-2be7-4544-8bf4-867174e611b3 0xd0ff9a4 0x3b9599e8 Dba.Wrapper.OracleWrapper 0xd0ff9a8 0xf569f8 Sample.UI.Win.Service.MaterialManager 0xd0ff9d0 0xf56b8c System.Timers.Timer 0xd0ff9d4 0xf56b8c System.Timers.Timer 0xd0ff9e4 0x3b95997c System.Timers.ElapsedEventArgs 0xd0ffa40 0xf56bfc System.Object 0xd0ffa44 0xf56bc4 System.Threading.TimerCallback 0xd0ffc08 0xf56bfc System.Object 0xd0ffc28 0xf56bc4 System.Threading.TimerCallback 0xd0ffc30 0xf56bfc System.Object 0xd0ffc40 0xf56bc4 System.Threading.TimerCallback 0xd0ffc48 0xf56bfc System.Object |
当你想查看当前线程中所有引用对象时,这个命令就显得极为有用了。如果你先分析其中的一个对象,只需要简单的拷贝Object列的对象地址,并使用 !dumpobj 命令即可:
0:010> !dumpobj 0x1d298ad8 Name: System.Data.DataRow MethodTable 0x007b9ba4 EEClass 0x00c34ea8 Size 40(0x28) bytes GC Generation: 2 mdToken: 0x02000030 (c:/windows/assembly/gac/system.data/1.0.5000.0__b77a5c561934e089/system.data.dll) FieldDesc*: 0x007b95f0 MT Field Offset Type Attr Value Name 0x007b9ba4 0x40003a8 0x10 System.Int32 instance 0 oldRecord 0x007b9ba4 0x40003a9 0x14 System.Int32 instance 0 newRecord 0x007b9ba4 0x40003aa 0x18 System.Int32 instance -1 tempRecord 0x007b9ba4 0x40003ab 0x1c System.Int32 instance 1 rowID 0x007b9ba4 0x40003ac 0x20 System.Boolean instance 0 inChangingEvent 0x007b9ba4 0x40003ad 0x21 System.Boolean instance 0 inDeletingEvent 0x007b9ba4 0x40003ae 0x22 System.Boolean instance 0 inCascade 0x007b9ba4 0x40003af 0x4 CLASS instance 0x00000000 error 0x007b9ba4 0x40003b0 0x8 CLASS instance 0x00000000 _element 0x007b9ba4 0x40003b1 0xc CLASS instance 0x1d00942c _Table 0x007b9ba4 0x40003b2 0x154 CLASS static 0x00f5b680 zeroColumns |
!dumparray (!da)【标记1】
也许你已经注意到了,在堆栈中有一些数组对象。找找上面列表中System.Object[]类型,并在其上执行 !dumpobj [arrayAddress],仅仅能得到关于数组的基础信息,而没有详细的内容。给了得到更多关于数组的信息,就可以使用 !dumparray ,简称 !da
0:050> !do 27239b98 |
如你所见,!dumparray 命令显示了更多的对象信息。可以看到该对象包含System.String 数据,并有两个元素的数组。既然是System.String 对象,那么我们就可以使用 !dumpobj 查看其内容了。
!objsize
就像你在上面所见到的,对象的大小都是24字节,套用 Obi Wan Kenobi 的话语:“从某种角度来看,这个是真实的”。24字节只是 System.Object[] 自己的大小,并不是它所包含的内容的大小。当你执行 !dumparray 后,就可以看到数组仅仅包含两个字符串的引用对象。这些对象都是独立的对象,能扩展到32M的大小,所以 24字节并不是整个数组的大小。但是还是需要强调的是: System.Object[] 只有24字节大小。
为了得到对象的整个大小,就需要使用 !objsize 命令:
0:010> !objsize 0x1d298ad8 sizeof(0x1d298ad8) = 5,988,380 (0x5b601c) bytes () |
!objsize 通过反复的调用子节点的引用对象,包括重子节点等等来获得对象的大小,很清楚的看到上面 0x1d298ad8 对象的大小是5,988,380字节。
如果拥有较多的子级对象,!objsize 将要花费较长的时间来计算对象的总大小,因此你已经意识到该命令像你想的那样完美。例如:有一个用户自定义按钮控件,并引用它所在的aspx页面,为了获得该控件的大小,不得不获得这整个aspx页面的大小,还得获取所有子级控件的大小。换句话说:如果你要检查的对象出奇的大,就应该手动检测对象的引用情况。
!dumpheap
这个命令也是我经常使用的命令之一,但是使用该命令时最好要带一个参数,如果不带参数该命令将dump出所有的托管堆上的对象,因此经常使用 –stat 参数来得到托管堆上的摘要信息,以下就是使用 !dumpheap –stat 的信息:
0:000> !dumpheap -stat total 1003 objects Statistics: MT Count TotalSize Class Name 7a5e61c8 1 12 System.Diagnostics.OrdinalCaseInsensitiveComparer 79333dc0 1 12 System.Text.DecoderExceptionFallback 79333d7c 1 12 System.Text.EncoderExceptionFallback 79331d90 1 12 System.RuntimeTypeHandle 7932fa14 1 12 System.__Filters 7932f9c4 1 12 System.Reflection.Missing 7932f8cc 1 12 System.RuntimeType+TypeCacheQueue 793233bc 1 12 System.Security.Cryptography.RNGCryptoServiceProvider 7931c13c 1 12 System.Security.Permissions.FileDialogPermission 7931c100 1 12 System.Security.PolicyManager 79307e08 1 12 System.DBNull 793068f4 1 12 System.Collections.Hashtable+KeyCollection 7930416c 1 12 System.DefaultBinder 00ab715c 1 12 MyNamespace.MyNewClass 7aa3ea1c 1 16 System.Timers.ElapsedEventArgs 7995b150 1 16 System.IO.TextReader+SyncTextReader 79331f90 1 16 System.Globalization.GlobalizationAssembly 7932ad1c 1 16 System.Security.Permissions.UIPermission 79329e14 1 16 System.Runtime.InteropServices.HandleRef 79316f28 1 16 System.Threading.Timer 79334808 1 20 Microsoft.Win32.SafeHandles.SafeFileMappingHandle 793347b0 1 20 Microsoft.Win32.SafeHandles.SafeViewOfFileHandle 79334724 1 20 System.Text.InternalEncoderBestFitFallback 79327c7c 1 20 System.Security.Permissions.EnvironmentPermission 7932335c 1 20 System.Security.Cryptography.SafeProvHandle 79317008 1 20 System.Threading._TimerCallback 7a5e3b74 1 24 System.CodeDom.Compiler.TempFileCollection 79334770 1 24 System.Text.InternalDecoderBestFitFallback 793343c0 1 24 System.IO.TextWriter+SyncTextWriter 79332510 1 24 System.OperatingSystem 793181b0 1 24 System.Globalization.GregorianCalendar 79316fb0 1 24 System.Threading.TimerBase 79306b94 2 24 System.Collections.Comparer 79306ad0 2 24 System.OrdinalComparer 7930539c 2 24 System.Security.Permissions.ReflectionPermission 7930508c 1 24 System.RuntimeType+ActivatorCache 799584e8 1 28 System.Text.DBCSCodePageEncoding+DBCSDecoder 79334290 1 28 Microsoft.Win32.Win32Native+InputRecord 79333f24 1 28 System.Text.EncoderNLS 79333c34 1 28 System.IO.Stream+NullStream 79330fb8 1 28 System.SharedStatics 79328ad8 1 28 System.CurrentSystemTimeZone 7aa25a48 1 32 System.Timers.ElapsedEventHandler 7a5e7720 1 32 Microsoft.CSharp.CSharpCodeGenerator 79333ea4 1 32 System.Text.UTF8Encoding+UTF8Encoder 79333e18 1 32 System.Threading.IOCompletionCallback 79333ae4 2 32 System.Text.DecoderReplacementFallback 79333a94 2 32 System.Text.EncoderReplacementFallback 79332efc 1 32 System.Security.PermissionTokenFactory 7932aa38 1 32 System.Text.UnicodeEncoding 7932a834 1 32 System.Threading.ContextCallback 7932a5c0 1 32 System.Runtime.CompilerServices.RuntimeHelpers+CleanupCode 7932a534 1 32 System.Runtime.CompilerServices.RuntimeHelpers+TryCode 79328b30 1 32 System.Globalization.DaylightTime 79327d2c 1 32 System.Text.UnicodeEncoding+Decoder 7931c56c 1 32 System.Security.Util.Tokenizer+StringMaker 79316e9c 1 32 System.Threading.TimerCallback 79307f4c 2 32 System.DateTime 79306a5c 2 32 System.CultureAwareComparer 00ab3cb0 1 32 SOSBasics.Formula 7a5e7e00 3 36 System.Collections.Specialized.StringCollection 79332eb0 1 36 System.Security.Util.TokenBasedSet 79332d18 1 36 System.Security.Permissions.FileIOPermission 793320c8 1 36 System.Int64[] 7932d5e0 1 36 System.Threading.ExecutionContext 79332e50 2 40 System.Security.PermissionToken 7932e8b8 2 40 Microsoft.Win32.SafeHandles.SafeFileHandle 7931e784 1 40 System.Int32[][] 79957cf8 1 44 System.Text.InternalEncoderBestFitFallbackBuffer 793313d8 1 44 System.AppDomainSetup 7933169c 1 48 System.Globalization.TextInfo 7932ef64 1 48 System.Reflection.Module 7aa3ea88 1 56 System.Timers.Timer 7a5e6970 1 56 System.CodeDom.Compiler.CompilerParameters 79333990 2 56 System.Text.UTF8Encoding 793279e4 1 56 System.String[][] 793327cc 5 60 System.Security.Permissions.SecurityPermission 7932c94c 1 60 System.Collections.Hashtable+SyncHashtable 79318958 1 60 System.IO.StreamReader+NullStreamReader 7931886c 1 60 System.IO.StreamReader 7932a644 2 64 System.Globalization.CompareInfo 79307eb0 4 64 System.TimeSpan 79333714 1 68 System.Globalization.CultureTable 793342e4 2 72 System.IO.__ConsoleStream 79330c30 1 72 System.ExecutionEngineException 79330ba0 1 72 System.StackOverflowException 79330b10 1 72 System.OutOfMemoryException 799583bc 1 76 System.Text.DBCSCodePageEncoding 79330a28 4 80 System.Text.StringBuilder 7932fa70 3 96 System.Reflection.MemberFilter 793337a8 5 100 System.Globalization.CultureTableItem 793310cc 1 100 System.AppDomain 7932f98c 1 100 System.Reflection.MetadataArgs+SkipAddresses 79332b38 9 108 System.Int32 793340d4 2 112 System.IO.StreamWriter 79330ec0 2 112 System.Threading.Thread 793325b0 4 144 System.Security.PermissionSet 79330cc0 2 144 System.Threading.ThreadAbortException 7931e9d4 3 156 System.Security.Policy.PolicyLevel 7931cc34 13 156 System.Security.Permissions.StrongNamePublicKeyBlob 7931c2b0 13 156 System.Security.Policy.GacInstalled 7931bfa8 13 156 System.Security.Policy.Url 793338b8 1 188 System.Globalization.DateTimeFormatInfo 7931c01c 13 208 System.Security.Policy.Zone 793336c4 5 240 System.Globalization.CultureTableRecord 793210a8 13 260 Microsoft.Win32.SafeHandles.SafePEFileHandle 7931bd14 13 260 System.Security.Policy.Evidence 79321040 13 312 System.Security.Policy.Hash 793050d4 13 312 System.RuntimeType+ActivatorCacheEntry 793334e8 5 340 System.Globalization.CultureInfo 79332494 15 360 System.Version 7931c898 13 364 System.Security.Policy.StrongName 79330508 31 372 System.Object 79333850 3 384 System.Globalization.NumberFormatInfo 79331e38 16 384 System.Reflection.Assembly 7933291c 17 408 System.Collections.ArrayList 793175fc 13 416 System.Collections.ArrayList+SyncArrayList 793304b4 13 676 System.Security.Util.URLString 79332a88 16 756 System.Int32[] 79332f40 14 784 System.Collections.Hashtable 00163860 16 884 Free 79331a6c 52 1040 System.RuntimeType 7933335c 20 1996 System.Byte[] 7933303c 14 2016 System.Collections.Hashtable+bucket[] 7933151c 21 4964 System.Char[] 793040bc 55 23244 System.Object[] 793308ec 414 27288 System.String Total 1003 objects |
如你所见,我们得到一个托管堆上按照大小排序的对象类型列表,在列表的最后可以看到经常要使用的类型字符串。
其他有用的参数是 –type 和 –mt (即:MethodTable),使用这些命令可以查看指定类型的对象。例如:假设想查看堆上 System.String 对象,拷贝上面列表中 MethodTable 列值 793308ec,并使用 !dumpheap –mt 即可:
0:000> !dumpheap -mt 793308ec Address MT Size 01421198 793308ec 20 014211c8 793308ec 160 01421268 793308ec 212 0142141c 793308ec 28 01421438 793308ec 32 01421458 793308ec 20 0142146c 793308ec 52 014214a0 793308ec 40 014214c8 793308ec 48 014214f8 793308ec 44 01421524 793308ec 48 01421554 793308ec 36 01421578 793308ec 32 01421598 793308ec 48 014215c8 793308ec 56 01421600 793308ec 64 01421640 793308ec 36 01421664 793308ec 44 01421690 793308ec 64 014216d0 793308ec 68 01421714 793308ec 56 0142174c 793308ec 60 01421788 793308ec 48 014217b8 793308ec 40 014218c0 793308ec 28 014218ec 793308ec 40 01421928 793308ec 32 01421948 793308ec 36 0142199c 793308ec 44 014219c8 793308ec 48 01421bb8 793308ec 56 01421c08 793308ec 36 01421c2c 793308ec 36 01421c50 793308ec 60 01421c8c 793308ec 64 01421ccc 793308ec 56 01421d04 793308ec 76 01421d50 793308ec 60 01421d8c 793308ec 60 01421dc8 793308ec 68 01421e0c 793308ec 2216 014226b4 793308ec 3384 014233ec 793308ec 36 01423410 793308ec 32 01423430 793308ec 36 01423454 793308ec 52 01423488 793308ec 44 014234b4 793308ec 56 014234ec 793308ec 32 0142350c 793308ec 52 01423540 793308ec 40 01423568 793308ec 60 014235a4 793308ec 60 014235e0 793308ec 80 01423630 793308ec 40 01423658 793308ec 60 01423694 793308ec 48 014236c4 793308ec 68 01423708 793308ec 48 01423738 793308ec 68 0142377c 793308ec 52 014237b0 793308ec 72 014237f8 793308ec 60 01423834 793308ec 80 01423884 793308ec 68 014238c8 793308ec 88 01423920 793308ec 52 01423954 793308ec 72 014239f4 793308ec 100 01423a58 793308ec 68 01423b68 793308ec 48 01423b98 793308ec 60 01423bd4 793308ec 124 01423c50 793308ec 220 01423d2c 793308ec 164 01423e24 793308ec 156 01423ef4 793308ec 248 01424020 793308ec 44 0142404c 793308ec 56 01424188 793308ec 28 014241a4 793308ec 52 014241d8 793308ec 48 01424208 793308ec 40 01424230 793308ec 44 0142425c 793308ec 56 01424294 793308ec 88 014242ec 793308ec 40 01426750 793308ec 48 01426780 793308ec 32 014267a0 793308ec 20 014267b4 793308ec 44 014267e0 793308ec 28 014267fc 793308ec 76 01426848 793308ec 28 01426864 793308ec 44 01426890 793308ec 28 014268ac 793308ec 44 014268d8 793308ec 28 01426918 793308ec 72 01426960 793308ec 64 014269a0 793308ec 88 01426bac 793308ec 28 01426bc8 793308ec 48 01426bf8 793308ec 40 01426c20 793308ec 48 01426c70 793308ec 20 01426c84 793308ec 24 01426c9c 793308ec 20 01426ef4 793308ec 120 01426fa4 793308ec 140 01427030 793308ec 52 01427064 793308ec 124 0142723c 793308ec 44 014272f4 793308ec 84 0142738c 793308ec 28 014273d8 793308ec 40 01427400 793308ec 40 014276f8 793308ec 40 01427778 793308ec 28 01427874 793308ec 28 014278d4 793308ec 28 014278f0 793308ec 48 01427920 793308ec 28 0142793c 793308ec 40 01427964 793308ec 28 014279f0 793308ec 28 01427a18 793308ec 28 01427a78 793308ec 28 01427a94 793308ec 40 01427abc 793308ec 28 01427af0 793308ec 28 01427b0c 793308ec 32 01427be8 793308ec 20 01427bfc 793308ec 20 01427c10 793308ec 20 01427c24 793308ec 20 01427c38 793308ec 20 01427c4c 793308ec 20 01427c60 793308ec 24 01427c78 793308ec 36 01427c9c 793308ec 36 01427cc0 793308ec 20 01427cd4 793308ec 20 01427ce8 793308ec 20 01427cfc 793308ec 20 01427d10 793308ec 20 01427d24 793308ec 20 01427d38 793308ec 20 01427d4c 793308ec 20 01427d60 793308ec 20 01427d74 793308ec 20 01427d88 793308ec 20 01427d9c 793308ec 20 01427db0 793308ec 20 01427dc4 793308ec 20 01427dd8 793308ec 20 01427dec 793308ec 20 01427e00 793308ec 20 01427e4c 793308ec 20 01427e60 793308ec 20 01427e74 793308ec 20 01427e88 793308ec 20 01427e9c 793308ec 20 01427eb0 793308ec 20 01427ec4 793308ec 20 01427ed8 793308ec 20 01427eec 793308ec 20 01427f00 793308ec 20 01427f34 793308ec 20 01427f48 793308ec 36 01427f6c 793308ec 36 01427f90 793308ec 24 01428030 793308ec 20 014280ac 793308ec 36 014280d0 793308ec 32 01428804 793308ec 28 01428820 793308ec 28 0142883c 793308ec 36 01428860 793308ec 36 01428884 793308ec 36 01428f9c 793308ec 28 01428fb8 793308ec 32 01429324 793308ec 156 014293c0 793308ec 68 01429404 793308ec 48 01429434 793308ec 60 01429470 793308ec 72 014294b8 793308ec 72 01429500 793308ec 68 01429544 793308ec 72 0142958c 793308ec 24 014295a4 793308ec 40 014295cc 793308ec 48 014295fc 793308ec 48 0142962c 793308ec 36 01429650 793308ec 40 01429678 793308ec 48 014296a8 793308ec 64 014296e8 793308ec 40 01429b84 793308ec 20 01429be0 793308ec 32 01429c00 793308ec 32 01429c2c 793308ec 20 01429c74 793308ec 24 01429c8c 793308ec 24 01429ca4 793308ec 24 01429cbc 793308ec 24 01429cd4 793308ec 24 01429cec 793308ec 24 01429d04 793308ec 24 01429d1c 793308ec 24 01429d34 793308ec 24 01429d4c 793308ec 24 01429d64 793308ec 24 01429d7c 793308ec 28 01429d98 793308ec 28 01429db4 793308ec 28 01429dd0 793308ec 28 01429dec 793308ec 28 01429e08 793308ec 28 01429e24 793308ec 28 01429e40 793308ec 28 01429e5c 793308ec 28 01429e78 793308ec 28 01429e94 793308ec 28 01429eb0 793308ec 28 01429ecc 793308ec 28 01429ee8 793308ec 28 01429f04 793308ec 28 01429f20 793308ec 28 01429f3c 793308ec 28 01429f58 793308ec 28 01429f74 793308ec 28 01429f90 793308ec 28 01429fac 793308ec 28 01429fc8 793308ec 28 01429fe4 793308ec 28 0142a000 793308ec 28 0142a01c 793308ec 28 0142a038 793308ec 28 0142a054 793308ec 28 0142a070 793308ec 28 0142a08c 793308ec 28 0142a0a8 793308ec 28 0142a0c4 793308ec 28 0142a0e0 793308ec 32 0142a100 793308ec 32 0142a120 793308ec 32 0142a140 793308ec 32 0142a160 793308ec 32 0142a180 793308ec 32 0142a1a0 793308ec 32 0142a1c0 793308ec 32 0142a1e0 793308ec 32 0142a200 793308ec 32 0142a220 793308ec 32 0142a240 793308ec 32 0142a260 793308ec 32 0142a280 793308ec 32 0142a2a0 793308ec 32 0142a2c0 793308ec 32 0142a2e0 793308ec 32 0142a300 793308ec 32 0142a320 793308ec 32 0142a340 793308ec 32 0142a360 793308ec 32 0142a380 793308ec 32 0142a3a0 793308ec 32 0142a3c0 793308ec 36 0142a3e4 793308ec 36 0142a408 793308ec 36 0142a42c 793308ec 36 0142a450 793308ec 36 0142a474 793308ec 36 0142a498 793308ec 36 0142a4bc 793308ec 36 0142a4e0 793308ec 36 0142a504 793308ec 36 0142a528 793308ec 36 0142a54c 793308ec 36 0142a570 793308ec 36 0142a594 793308ec 36 0142a5b8 793308ec 36 0142a5dc 793308ec 36 0142a600 793308ec 36 0142a624 793308ec 40 0142a64c 793308ec 40 0142a88c 793308ec 24 0142a924 793308ec 20 0142a938 793308ec 20 0142a94c 793308ec 20 0142a960 793308ec 20 0142a974 793308ec 20 0142a988 793308ec 20 0142a9d4 793308ec 20 0142a9e8 793308ec 20 0142a9fc 793308ec 20 0142aa10 793308ec 20 0142aa24 793308ec 20 0142aa38 793308ec 20 0142aa4c 793308ec 20 0142aa60 793308ec 20 0142aa74 793308ec 20 0142aa88 793308ec 20 0142aabc 793308ec 20 0142aad0 793308ec 28 0142aaec 793308ec 28 0142ab08 793308ec 24 0142ab20 793308ec 20 0142ab34 793308ec 28 0142ab50 793308ec 20 0142ae68 793308ec 28 0142ae84 793308ec 28 0142aea0 793308ec 32 0142aec0 793308ec 32 0142aee0 793308ec 28 0142af38 793308ec 24 0142af50 793308ec 24 0142af68 793308ec 24 0142af80 793308ec 48 0142afb0 793308ec 20 0142afc4 793308ec 32 0142afe4 793308ec 32 0142b004 793308ec 40 0142b02c 793308ec 44 0142b058 793308ec 24 0142b070 793308ec 20 0142b084 793308ec 28 0142b0a0 793308ec 36 0142b0c4 793308ec 36 0142b0e8 793308ec 24 0142b100 793308ec 32 0142b120 793308ec 40 0142b148 793308ec 36 0142b16c 793308ec 40 0142b194 793308ec 40 0142b1bc 793308ec 40 0142b1e4 793308ec 44 0142b210 793308ec 24 0142b228 793308ec 32 0142b248 793308ec 64 0142b288 793308ec 32 0142b2a8 793308ec 48 0142b2d8 793308ec 28 0142b2f4 793308ec 28 0142b310 793308ec 28 0142b32c 793308ec 28 0142b460 793308ec 24 0142b478 793308ec 24 0142b490 793308ec 68 0142b4d4 793308ec 20 0142b638 793308ec 28 0142b780 793308ec 28 0142b7dc 793308ec 180 0142b890 793308ec 32 0142bb18 793308ec 20 0142bb3c 793308ec 28 0142c35c 793308ec 36 0142c380 793308ec 48 0142c3b0 793308ec 24 0142c3c8 793308ec 24 0142c3e0 793308ec 32 0142c400 793308ec 24 0142c418 793308ec 24 0142c430 793308ec 40 0142c468 793308ec 24 0142c480 793308ec 24 0142c498 793308ec 28 0142c4b4 793308ec 28 0142c4d0 793308ec 32 0142c4f0 793308ec 32 0142c570 793308ec 20 0142c584 793308ec 20 0142c598 793308ec 80 0142c5e8 793308ec 20 0142c67c 793308ec 20 0142c690 793308ec 24 0142c6a8 793308ec 180 0142c75c 793308ec 32 0142c92c 793308ec 180 0142c9e0 793308ec 32 0142cbb0 793308ec 180 0142cc64 793308ec 32 0142ce34 793308ec 180 0142cee8 793308ec 32 0142d0b8 793308ec 180 0142d16c 793308ec 32 0142d33c 793308ec 180 0142d3f0 793308ec 32 0142d5c0 793308ec 180 0142d674 793308ec 32 0142d844 793308ec 180 0142d8f8 793308ec 32 0142dac8 793308ec 180 0142db7c 793308ec 32 0142dd4c 793308ec 36 0142dd70 793308ec 44 0142dd9c 793308ec 60 0142ddd8 793308ec 2964 0142e96c 793308ec 180 0142ea20 793308ec 32 0142ed68 793308ec 180 0142ee1c 793308ec 32 0142f048 793308ec 52 0142f090 793308ec 52 0142f2f0 793308ec 152 0142f388 793308ec 160 0142f478 793308ec 180 0142f52c 793308ec 32 0142f764 793308ec 84 0142f7d0 793308ec 28 0142f818 793308ec 188 0142f96c 793308ec 360 0142fae8 793308ec 36 total 414 objects Statistics: MT Count TotalSize Class Name 793308ec 414 27288 System.String Total 414 objects |
这样我们就得到了对象的地址,如果想更进一步查看对象,使用 !dumpobj [object address]即可。
!dumpheap –type 也是同样的有用,朱勇用在查看指定类的类型。!dumpheap –type 只需要提供一个字符串的一部分即可,因此假设输入 !dumpheap –type System ,将会输出许多包含 System 名称的对象。
其他比较有用的参数是 –min / -max ,该参数接受一个最小/最大的对象字节数。该类型的命令对查找字符串滥用等问题非常有用,使用 !dumpheap –stat –min 85000 可以查看托管堆上的大对象。
命令试用
现在将在一些实例上使用上述已经讲过的命令,继续使用前面的dump文件,该应用程序运行在双核web服务器上,Session状态由Sql Server保存。客户遇到性能问题,最好有个大概的描述,无论如何有许多dump文件需要分析,只需要简单大致的了解发生的情况。我首先做的就是查看缓存,从客户那得到的信息,他们根本就没有使用缓存,但是我们最好还是仔细好好检查该种类型。
检查缓存大小
为了找到缓存数据的数据,首先的查找 System.Web.Caching.Cache 类型,运行 !dumpheap –stat –type System.Web.Caching.Cache,注意同时使用 –stat 命令参数,如果不用该参数,将会同时看到关于 System.Web.Caching.CacheKeys 和 System.Web.Caching.CacheEntrys 的长长的列表,结果如下:
0:050> !dumpheap -type
System.Web.Caching.Cache -stat |
好了,到这里就得到了 System.Web.Caching.Cache 对象的方法表,因此就可以得到对象的地址。通过输入 !dumpheap –mt 1230494c 就可以得到1230494c方法表中所有对象,就像下面所列的一样:
0:050> !dumpheap -mt
1230494c |
此时,输入 !objsize 即可得到该对系那个的大小。计算将要耗费一定的时间,因为缓存有一定的复杂性,加上它有许多子级对象需要反复计算。
0:050> !objsize 03392d20 |
因此得到缓存大小为 266M ,此时对于客户一直强调的根本没有使用缓存的问题好好考虑一下了。
什么内容被缓存了?
为了对客户缓存进行抽样检查,查看了一些 CacheEntrys 对象,当运行!dumpheap –stat –type System.Web.Caching 后,即可得到 System.Web.Caching.CacheEntry 的方法表,由此可继续查找所有 CacheEntrys。
0:050> !dumpheap -mt
12306820 |
另一个可以达到同样效果的命令当然是 !dumpheap –type System.Web.Caching.CacheEntry
到此,得到了一长串关于 CacheEntrys 的列表,为了继续检查内容,可以挑选其中的一个地址,并使用 !dumpobj 即可检查对象的所有内容。
0:050> !do 03b2c674 |
这样就可以得到 CacheEntry 的整个内容,在如此众多的信息中最关心的是 _value ,拷贝下这个对象的地址(Value 列值),并再次使用 !dumpobj
0:000> !do 03e160c8 |
至此,我发现了一些有趣的事:value 里面真正存储的是,在此之前你并不知道的InProcSessionState 对象,而该对象又被保存在缓存中。这就意味着应用程序使用 SQL Server Session 状态的断言是不正确的。
事实证明,客户临时切换到进程内做短暂的测试而忘记切换回来。在应用程序运行的任何时间,他们都可以发现这个问题,但是因为只是做压力测试,他们并没有注意服务器返回的是什么,而只观察到服务器返回了,不知不觉中压力测试就影响到了会话状态的这几个方面。比如:
- 工作线程的内存使用率比想象的更多
- 网络负载能力也不是像正常情况下高负荷运转
- 返回时间不确定
- 任何一个没有注意的潜在瓶颈都可能影响到sql 服务器,而达不到它应有的扩展能力
最后也没能找到一个解决该性能问题的最终解决方案。还有许多事情我们不得不做的,但是我想这个倒是一个非常棒的实例,教你如何仅仅只是用三个命令(!dumpheap , !objsize , !dumpobj )来找到更多更有用的信息。
继续! / Johan
【标记1】:因版本问题,在 windbg 6.10 中的clr10/sos.dll 没有提供!dumparray 命令,所以这个实例就采用原文的内容。