String.Format和垃圾收集

时间:2015-08-10 09:03:23

标签: c# .net performance debugging garbage

在我对我们的应用程序中高CPU使用率的持续调查中,我得出的结论是GC占用了大部分CPU时间。 看一下w3wp进程的memdump(应用程序是iis托管的)我发现了一些奇怪的东西:堆上有很多46字节的大字符串对象,它们都已经死了并准备收集。  进一步调查以下命令:

!dumpheap -mt 00007ff9bd160e08 -dead -min 2e -max 2e

将所有大小为46的死字符串对象转储出来告诉我,我目前有260000个这种大小的死字符串。查看其中的一些内容很快就会发现所有这些都来自同一个地方,这是一种为我们的缓存创建密钥的辅助方法:

private static string Key(Guid ssoId)
{
    return string.Format("BasicUser:{0}-Brand:{1}", ssoId, MemBag.Client.BrandEnum);
}

46byte字符串是“BasicUser:”,仅此而已,至少就我所见:

0:000> !do 000000f1d48d49a0
Name:        System.String
MethodTable: 00007ff9bd160e08
EEClass:     00007ff9bca84860
Size:        46(0x2e) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      BasicUser:
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
00007ff9bd163980  40000ab        8         System.Int32  1 instance               10 m_stringLength
00007ff9bd1620f0  40000ac        c          System.Char  1 instance               42 m_firstChar
00007ff9bd160e08  40000ad       18        System.String  0   shared           static Empty
                                 >> Domain:Value  000000ee12ced200:NotInit  000000ee138a4440:NotInit  <<

所有这些分配似乎不仅导致gen0集合,而且还有很多完整的集合,大约80-90%的集合是完整的集合!

该方法确实被调用了很多,但它对GC施加如此大的压力毫无意义!这里发生了什么?方法实施方式不好吗?为什么堆上的字符串“BasicUser:”?字符串的其余部分在哪里?即使有空的参数,“品牌”部分仍然缺失。

我对这个问题非常困惑,真的需要一些输入,非常感谢任何帮助!

更新

似乎总是10个字符长,我将代码更改为:

  return string.Format("BasicUsr:{0}-Brand:{1}", ssoId, MemBag.Client.BrandEnum);

更改用户 - &gt; Usr,结果是我现在在堆上看到这样的字符串:“BasicUsr:b”它似乎总是10个第一个字符,我是否将字符串转出错了?

更新2

我有机会从实时服务器获取1分钟的perfview捕获,这是我得到的,如果我正确读取它,我们分配了大量的数据,这是高内存压力的原因,几乎每个集合是gen2

Hard working GC

0 个答案:

没有答案