4

I am trying to reduce time it takes to do a Gen2 collection. My app creates and holds a large number of string objects, which persist through its life.

Reducing number of scanned objects should reduce GC time. I was wondering whether intern pool is excepted from garbage collection. There isn't anything to collect there anyway. If so, I could intern all these strings and speed up GC.

4

2 回答 2

5

我做了一个快速测试,字符串的实习似乎并没有让它们免于被 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 秒。如果将字符串放入数组而不是 intern,则返回 0.26 秒。如果字符串是通过 实习和创建(i % 10).ToString()的,即有少量不同的实例,则基准返回微秒。

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

于 2016-01-15T00:55:39.543 回答
4

如果您试图减少应用程序分配的内存总量,请记住,插入字符串有两个不需要的副作用。首先,在公共语言运行时 (CLR) 终止之前,分配给 interned String 对象的内存可能不会被释放。原因是 CLR 对实习字符串对象的引用可以在您的应用程序甚至您的应用程序域终止后持续存在。其次,要实习字符串,您必须首先创建字符串。仍然必须分配 String 对象使用的内存,即使内存最终会被垃圾回收。

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

强调我的。

于 2016-01-13T23:38:51.863 回答