一、背景1、讲故事前,有朋友加微信求助,说他的程序有零星的CPU爆炸,以及如何解决。截图如下:建议朋友在CPU高的时候使用procdump连续抓取两次dump,这样分析更稳定,朋友如期成功抓取。下面我们一起用windbg来分析一下。2.Windbg分析1.先查看CPU使用率使用!tp查看两个dump的cpu使用率0:112>!tpCPUutilization:100%WorkerThread:Total:138Running:128Idle:10MaxLimit:2000MinLimit:队列中的400工作请求:17未知函数:00007ffe1a6617d0上下文:000001fd9bcb20c8...------------------------------------定时器数量:2----------------------------------------完成端口线程:总计:2免费:2最大免费:16当前限制:2最大限制:2000最小限制:4000:014>!tpCPU利用率:96%工作线程:总计:173运行:67空闲:106最大限制:2000最小限制:400队列中的工作请求:1未知函数:00007ffe1a6617d0上下文:000001fda1a20be8------------------------------------定时器数量:2-------------------------------------完成端口线程:总计:7个免费:7个MaxFree:16CurrentLimit:7MaxLimit:2000MinLimit:400果然如朋友所说,那你试试看是不是GC触发导致的?2.检查GCtrigger是否只是简单地使用~*e!dumpstack来导出托管和Unmanaged堆栈,然后搜索GarbageCollectGeneration就好了。果然,GC被触发了。从调用栈信息来看,可能是当前宿主层在进行高频的new操作,导致只向某个堆写入数据,导致堆不平衡。服务器模式的GC为了平衡多个堆,做了一次堆平衡操作,接下来的线索是为什么会有狂写?您必须查看托管层并使用!clrstack命令。0:112>!clrstackOSThreadId:0x3278(112)ChildSPIPCallSite000000b4ddc7909800007ffe28b9fa74[HelperMethodFrame:000000b4ddc79098]000000b4ddc791a000007ffda6c229cbSystem.Data.Entity.ModelConfiguration.Utilities.EdmPropertyPath.System.Collections.Generic.IEnumerable.GetEnumerator()000000b4ddc7920000007ffe01a179ebSystem.Linq.Enumerable.SequenceEqual[[System.__Canon,mscorlib]](System.Collections.Generic.IEnumerable`1,系统.Collections.Generic.IEnumerable`1,System.Collections.Generic.IEqualityComparer`1)000000b4ddc7928000007ffda6c2297eSystem.Data.Entity.ModelConfiguration.Configuration.Mapping.EntityMappingConfiguration+c__DisplayClass14.b__11(System.Data.Entity.Core.Mapping.ColumnMappingBuilder)000000b4ddc792b000007ffe01a13f8fSystem.Linq.Enumerable.SingleOrDefault[[System.__Canon,mscorlib]](System.Collections.Generic.IEnumerable`1,System.Func`2)000000b4ddc7933000007ffda6c2087cSystem.Data.Entity.ModelConfiguration.Configuration.Mapping.EntityMappingConfiguration.Configure(System.Data.Entity.Core.Metadata.Edm.DbDatabaseMapping、System.Data.Entity.Core.Common.DbProviderManifest、System.Data.Entity.Core.Metadata.Edm.EntityType、System.Data.Entity.Core.Mapping。StorageEntityTypeMappingByRef,布尔值,Int32,Int32)000000b4ddc7952000007ffda6c20128System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.ConfigureUnconfiguredType(System.Data.Entity.Core.Metadata.Edm.DbDatabaseMapping,System.Data.Entity.Core.Common.DbProviderManifest,System.Data.Entity.Core.Metadata.Edm.EntityType)000000b4ddc795a000007ffda6c1ffaftorageEntityTypeMapping,System.Data.Entity.Core.Metadata.Edm.DbDatabaseMapping,System.Data.Entity.Core.Common.DbProviderManifest)000000b4ddc7962000007ffda6c055c0System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.ConfigureEntityTypes(System.Data.Entity。Core.Metadata.Edm.DbDatabaseMapping,System.Data.Entity.Core.Common.DbProviderManifest)000000b4ddc7968000007ffda6c05474System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.Configure(System.Data.Entity.Core.Metadata.Edm.DbDatabaseMapping,System.Data.Entity.Core.Common.DbProviderManifest)000000b4ddc796d000007ffda69ae5c2System.Data.Entity.DbModelBuilder.Build(System.Data.Entity.Core.Common.DbProviderManifest,System.Data.Entity.Infrastructure.DbProviderInfo)000000b4ddc76.ffdaSystem0907400Data.Entity.DbModelBuilder.Build(System.Data.Common.DbConnection)000000b4ddc7978000007ffda7b4b2d3System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(系统。Data.Entity.DbContext,System.Xml.XmlWriter)000000b4ddc797c000007ffda7b4acbeClass125.smethod_0(System.Data.Entity.DbContext)000000b4ddc7982000007ffda7b4aba4Class617.smethod_22(System.Data.Entity.DbContext)000000b4ddc7986000007ffda7b4aa90Class617.smethod_27(System.Data.Entity.DbContext)000000b4ddc798c000007ffda7b3e9ecDbContextExtensions.GetModel(System.Data.Entity.DbContext)000000b4ddc7991000007ffda7b3e49bClass124.smethod_0(System.Data.Entity.DbContext,System.String)000000b4ddc7995000007ffda7b3d6c3Class486.smethod_3[[System.__Canon,mscorlib]](System.Data.Entity.DbContext,Z.BulkOperations.BulkOperation`1,System.Collections.Generic.IEnumerable`1,System.Collections.Generic.List`1)000000b4ddc79a0000007ffda7b36871DbContextExtensions.BulkInsert[[System.__Canon,mscorlib]](System.Data.Entity.DbContext,System.Collections.Generic.IEnumerable`1,系统从堆栈信息看,大概有如下三条信息:EFisbeingusedforbatchinsertoperations。BulkInsert使用Z.EntityFramework插件。有很多Build,Configure的话,好像是在做配置,搭建什么的。3、是否是插入数据过多造成的?首先想到的是列表太大了。为了验证,您可以使用!clrstack-a导出BulkInsert方法的列表参数。0:112>!clrstack-aOS线程ID:0x3278(112)子SPIP调用站点000000b4ddc79b9000007ffda7b31ee8xxx.BLL.BaseService`1[[System.__Canon,mscorlib]].BulkInsert(System.__Canon[])0x000000b4ddc79d10)=0x000001fa14bbb630_tArr(0x000000b4ddc79d18)=0x000001fa14c1a2f80:112>!do0x000001fa14c1a2f8Name:xxx.EntityModel.xxx[]MethodTable:00007ffda9437968EEClass:00007ffe02f556b0Size:56(0x38)bytesArray:Rank1,Numberofelements4,TypeCLASS(PrintArray)Fields:None从输出来看,当前的list.length=4,很迷惑。由于堆处于平衡状态,是否有几个线程在攻击?要验证,请在所有托管线程堆栈中使用DbContextExtensions.BulkInsert搜索关键字查看。可以看到,目前有10个地方处于攻势。依次来看,他们的名单并不大。我很困惑。