是 .NET 中垃圾回收中除此之外的暂留字符串

本文关键字:除此之外 字符串 NET | 更新日期: 2023-09-27 18:30:18

我正在尝试减少执行Gen2集合所需的时间。我的应用创建并保存大量字符串对象,这些对象在其生命周期中持续存在。

减少

扫描对象的数量应该可以减少GC时间。我想知道实习生池是否被排除在垃圾收集之外。反正那里没有什么可收集的。如果是这样,我可以实习所有这些字符串并加快 GC 的速度。

是 .NET 中垃圾回收中除此之外的暂留字符串

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

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

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

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

强调我的。