在.NET中,实习字符串是否从垃圾收集中排除?

时间:2016-01-13 23:37:21

标签: c# string garbage-collection string-interning

我正在努力减少进行Gen2收集所需的时间。我的应用程序创建并保存了大量的字符串对象,这些对象在其生命中持续存在。

减少扫描对象的数量应减少GC时间。我想知道实习池是否被排除在垃圾收集之外。无论如何,没有任何东西要收集。如果是这样,我可以实习所有这些字符串并加速GC。

2 个答案:

答案 0 :(得分:4)

  

如果您正在尝试减少您的总内存量   应用程序分配,请记住,实习字符串有两个   不必要的副作用。 首先,为interned String分配的内存   在公共语言运行库之前,不可能释放对象   (CLR)终止。原因是CLR的引用   interned String对象可以在应用程序之后保留,甚至可以保留   您的应用程序域,终止。第二,要实习一个字符串,你   必须先创建字符串。 String对象使用的内存   仍然必须分配,即使内存最终会被分配   垃圾收集。

参考:https://msdn.microsoft.com/en-us/library/system.string.intern(v=vs.110).aspx

强调我的。

答案 1 :(得分:4)

我进行了快速测试并且字符串的实习似乎没有将它们从GC扫描中保存下来。至少不在.NET 4.5 64位中。

class Program
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 20000000; ++i)
        {
            string s = i.ToString("X");
            string.Intern(s);
        }
        GC.Collect(3, GCCollectionMode.Forced, true);
        long t1 = Stopwatch.GetTimestamp();
        GC.Collect(3, GCCollectionMode.Forced, true);
        long t2 = Stopwatch.GetTimestamp();
        Console.WriteLine((double)(t2 - t1) / Stopwatch.Frequency);
    }
}

此基准在i5 3570k上返回0.23秒。如果将字符串放入数组而不是实习,则返回0.26s。如果字符串是通过(i % 10).ToString()实现并创建的,即存在少量不同的实例,则基准返回微秒。

很遗憾,这不是绕过垃圾收集的方法。我认为C#应该有一些方法将字符串标记为持久性,并停止运行时浪费时间扫描它们。