का कारण बनने के लिए लंबे समय तक रहने वाले तारों से कैसे बचें मेरे पास एक ऐसा एप्लिकेशन है जहां मैं सर्कुलर बफर में लॉग स्ट्रिंग रखता हूं। जब एक लॉग भर जाता है, हर नए सम्मिलन के लिए, पुरानी तार कचरा संग्रह के लिए जारी की जाएगी और फिर वे पीढ़ी 2 मेमोरी में हैं। इस प्रकार, अंततः एक पीढ़ी 2 जीसी होगा, जिसे मैं टालना चाहूंगा।पीढ़ी 2 कचरा संग्रह
मैंने स्ट्रिंग को स्ट्रिंग में मार्शल करने की कोशिश की। हैरानी की बात है, मुझे अभी भी पीढ़ी 2 जीसी मिलती है: एस। ऐसा लगता है कि संरचना अभी भी स्ट्रिंग के कुछ संदर्भ रखती है। नीचे पूरा कंसोल ऐप। किसी भी मदद की सराहना की।
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication
{
class Program
{
[StructLayout(LayoutKind.Sequential)]
public struct FixedString
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
private string str;
public FixedString(string str)
{
this.str = str;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct UTF8PackedString
{
private int length;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
private byte[] str;
public UTF8PackedString(int length)
{
this.length = length;
str = new byte[length];
}
public static implicit operator UTF8PackedString(string str)
{
var obj = new UTF8PackedString(Encoding.UTF8.GetByteCount(str));
var bytes = Encoding.UTF8.GetBytes(str);
Array.Copy(bytes, obj.str, obj.length);
return obj;
}
}
const int BufferSize = 1000000;
const int LoopCount = 10000000;
static void Main(string[] args)
{
Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}",
"Type".PadRight(20), "Time", "GC(0)", "GC(1)", "GC(2)");
Console.WriteLine();
for (int i = 0; i < 5; i++)
{
TestPerformance<string>(s => s);
TestPerformance<FixedString>(s => new FixedString(s));
TestPerformance<UTF8PackedString>(s => s);
Console.WriteLine();
}
Console.ReadKey();
}
private static void TestPerformance<T>(Func<string, T> func)
{
var buffer = new T[BufferSize];
GC.Collect(2);
Stopwatch stopWatch = new Stopwatch();
var initialCollectionCounts = new int[] { GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2) };
stopWatch.Reset();
stopWatch.Start();
for (int i = 0; i < LoopCount; i++)
buffer[i % BufferSize] = func(i.ToString());
stopWatch.Stop();
Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}",
typeof(T).Name.PadRight(20),
stopWatch.ElapsedMilliseconds,
(GC.CollectionCount(0) - initialCollectionCounts[0]),
(GC.CollectionCount(1) - initialCollectionCounts[1]),
(GC.CollectionCount(2) - initialCollectionCounts[2])
);
}
}
}
संपादित करें: UnsafeFixedString के साथ अपडेट किया कोड कि आवश्यक काम करता है: अपने कंप्यूटर पर
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication
{
class Program
{
public unsafe struct UnsafeFixedString
{
private int length;
private fixed char str[256];
public UnsafeFixedString(int length)
{
this.length = length;
}
public static implicit operator UnsafeFixedString(string str)
{
var obj = new UnsafeFixedString(str.Length);
for (int i = 0; i < str.Length; i++)
obj.str[i] = str[i];
return obj;
}
}
const int BufferSize = 1000000;
const int LoopCount = 10000000;
static void Main(string[] args)
{
Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}",
"Type".PadRight(20), "Time", "GC(0)", "GC(1)", "GC(2)");
Console.WriteLine();
for (int i = 0; i < 5; i++)
{
TestPerformance(s => s);
TestPerformance<UnsafeFixedString>(s => s);
Console.WriteLine();
}
Console.ReadKey();
}
private static void TestPerformance<T>(Func<string, T> func)
{
var buffer = new T[BufferSize];
GC.Collect(2);
Stopwatch stopWatch = new Stopwatch();
var initialCollectionCounts = new int[] { GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2) };
stopWatch.Reset();
stopWatch.Start();
for (int i = 0; i < LoopCount; i++)
buffer[i % BufferSize] = func(String.Format("{0}", i));
stopWatch.Stop();
Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}",
typeof(T).Name.PadRight(20),
stopWatch.ElapsedMilliseconds,
(GC.CollectionCount(0) - initialCollectionCounts[0]),
(GC.CollectionCount(1) - initialCollectionCounts[1]),
(GC.CollectionCount(2) - initialCollectionCounts[2])
);
}
}
}
आउटपुट है:
Type Time GC(0) GC(1) GC(2)
String 5746 160 71 19
UnsafeFixedString 5345 418 0 0
आप पहले स्थान पर पीढ़ी 2 कचरा संग्रहण से बचना क्यों चाहते हैं? – PVitt
एप्लिकेशन में कुछ वास्तविक समय की आवश्यकताएं हैं। एक जीसी (2) एक पूर्ण फ्रीज का कारण बनता है। –
क्या होगा यदि आप संदेश बाइट [] (encoding.utf8.getbytes के रूप में() तार के बजाय स्टोर –