Open2

GCを避ける

0y00y0

大きなオブジェクトの頻繁な生成

原因

大きなオブジェクトは 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);
        }
    }
}
0y00y0

短命オブジェクトの大量生成

問題

ループ内で小さなオブジェクトを大量に生成すると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));
        }
    }
}