我正在努力縮短創建Gen2集合所需的時間。我的應用程序創建並保存了大量的字符串對象,它們貫穿其整個生命。.NET中的垃圾收集除外的字符串是否被攔截?
減少掃描對象的數量應該減少GC時間。我想知道實習生池是否從垃圾收集中排除。無論如何都沒有收集到任何東西。如果是這樣,我可以實習所有這些字符串並加速GC。
我正在努力縮短創建Gen2集合所需的時間。我的應用程序創建並保存了大量的字符串對象,它們貫穿其整個生命。.NET中的垃圾收集除外的字符串是否被攔截?
減少掃描對象的數量應該減少GC時間。我想知道實習生池是否從垃圾收集中排除。無論如何都沒有收集到任何東西。如果是這樣,我可以實習所有這些字符串並加速GC。
我做了一個快速測試,並且字符串的實習似乎並不能保護他們免受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.23s。如果將字符串放入數組而不是內聯,則返回0.26s。如果字符串是通過(i % 10).ToString()
實現並創建的,即有少量不同的實例,則基準測試返回微秒。
很遺憾,這不是繞過垃圾收集的方法。我認爲C#應該有一些將字符串標記爲持久性的方法,並停止運行時浪費時間來掃描它們。
如果你想減少內存總量您 應用程序分配,請記住,實習字符串有兩個 有害的副作用。 首先,分配給實習字符串 對象的內存不可能在公共語言運行庫 (CLR)終止之前釋放。原因是CLR對 interned字符串對象的引用可以在您的應用程序或應用程序域終止後繼續存在。其次,要實習一個字符串,你必須首先創建字符串。 String對象 使用的內存仍然必須分配,即使內存最終將被垃圾收集爲 。
編號:https://msdn.microsoft.com/en-us/library/system.string.intern(v=vs.110).aspx
重點煤礦。
這些副作用都很小。 @kaalus已經說過「它貫穿其生命」,額外的GC是一次性負擔。 –
我不是想減少內存使用量,我想減少GC Gen2的時間 – kaalus
@kaalus而我的答案中的大膽聲明表明interned字符串不是垃圾回收。 –
_減少掃描對象的數量應該減少GC time_ - 首先要驗證的東西。它是對需要掃描的字符串的引用,無法避免。但是,由於CLR知道字符串池,它可能會快一點。 –
@HenkHolterman好評,但請參閱下面的測試。看起來,即使一個字符串在內部不包含任何引用並且可以跳過,也可以不必要地掃描intern池以供引用。 – kaalus