Open2
GCを避ける

大きなオブジェクトの頻繁な生成
原因
大きなオブジェクトは LOHに確保され、頻繁な割り当てと解放がGCの負荷を増やす
class Program
{
static void Main()
{
for (int i = 0; i < 1000; i++)
{
byte[] largeArray = new byte[100_000]; // 100KB の配列
}
}
}
解決策
オブジェクトプール
using System;
using System.Collections.Concurrent;
class Program
{
static ConcurrentBag<byte[]> _pool = new ConcurrentBag<byte[]>();
static void Main()
{
for (int i = 0; i < 1000; i++)
{
if (!_pool.TryTake(out byte[] largeArray))
{
largeArray = new byte[100_000];
}
// 使い終わったらプールに戻す
_pool.Add(largeArray);
}
}
}
ArrayPool<T>
using System;
using System.Buffers;
class Program
{
static void Main()
{
var pool = ArrayPool<byte>.Shared;
for (int i = 0; i < 1000; i++)
{
byte[] largeArray = pool.Rent(100_000);
// 使い終わったら返す
pool.Return(largeArray);
}
}
}

短命オブジェクトの大量生成
問題
ループ内で小さなオブジェクトを大量に生成するとGCが頻繁に発生
class Program
{
static void Main()
{
for (int i = 0; i < 100000; i++)
{
string message = $"Count: {i}"; // 毎回新しい文字列を生成
}
}
}
解決策
StringBuilder
using System;
using System.Text;
class Program
{
static void Main()
{
var sb = new StringBuilder();
for (int i = 0; i < 100000; i++)
{
sb.Clear();
sb.Append("Count: ").Append(i);
string message = sb.ToString();
}
}
}
Span<T> や Memory<T>
using System;
class Program
{
static void Main()
{
Span<char> buffer = stackalloc char[32];
for (int i = 0; i < 100000; i++)
{
int length = $"Count: {i}".AsSpan().CopyTo(buffer);
string message = new string(buffer.Slice(0, length));
}
}
}