🏎️

【Unity】ZLinqを使う

2025/04/09に公開

概要

高パフォーマンスでゼロアロケーションなZLinqがリリースされました。
https://x.com/neuecc/status/1909540788931117574

従来のLinqは、パフォーマンス(処理速度)が悪く、GCが発生してしまう問題がありました。
特にUnityで使う場合にはパフォーマンスの問題は顕著に発生してしまうため、「Update内でLinq使用禁止」というコーディング規約が生まれてしまうほどでした。
今回はそれらの問題が解決されたZLinqのUnityでの導入方法とパフォーマンス比較を紹介します。

導入

https://github.com/Cysharp/ZLinq

まずZLinqを入れるためにNuGetForUnityをインストールします。

Window->Package Managerを開き、左上のInstall package from git URL...を選択します。

そして、下記URLを入力してInstallをクリックします

https://github.com/GlitchEnzo/NuGetForUnity.git?path=/src/NuGetForUnity

NuGetForUnityがインストール出来たらツールバーにNuGetが出てくるので
Manage NuGet Packagesを開きます。

検索ボックスにZLinqを検索し、チェックを入れてInstallします。

最後に再びPackage ManagerからInstall package from git URL...を開き、ZLinqのURLを入力します

https://github.com/Cysharp/ZLinq.git?path=src/ZLinq.Unity/Assets/ZLinq.Unity

これでZLinqのインストールは完了です。

使ってみる

簡単な使い方は下記のとおりです。
従来のLinqから.AsValueEnumerable()を追加すればそのまま移行することができます。

using UnityEngine;
using ZLinq; //usingを追加

public class ZLinqSample : MonoBehaviour
{
    void Start()
    {
        var numbers = new[] { 1, 2, 3, 4, 5 };
        var average = numbers
                        .AsValueEnumerable() //配列に対してはこれを追加
                        .Average();
        Debug.Log($"Average: {average}");
    }
}

パフォーマンス比較

Average,Sum,Whereで比較をしてみました

比較用のテストコード
using UnityEngine;
using ZLinq;
using System.Linq;

public class LinqVS : MonoBehaviour
{
    float[] testArray = new float[10000];

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        for(var i=0;i<testArray.Length;i++)
        {
            testArray[i] = Random.Range(0f, 100f);
        }
    }

    // Update is called once per frame
    void Update()
    {
        DoAverage();
        DoSum();
        DoSelect();

        ZLinqAverage();
        ZLinqSum();
        ZLinqSelect();
    }


    void DoAverage()
    {
        var agerage = testArray.Average();
    }

    void DoSum()
    {
        var sum = testArray.Sum();
    }

    void DoSelect()
    {
        var select = testArray.Where(x => x > 50f);
    }
    

    void ZLinqAverage()
    {
        var agerage = testArray.AsValueEnumerable().Average();
    }
    void ZLinqSum()
    {
        var sum = testArray.AsValueEnumerable().Sum();
    }
    void ZLinqSelect()
    {
        var select = testArray.AsValueEnumerable().Where(x => x > 50f);
    }
}

using 関数 実行時間[ms] GC
System.Linq Average() 1.72 32B
ZLinq Average() 0.57 0B
System.Linq Sum() 1.68 32B
ZLinq Sum() 0.56 0B
System.Linq Where 0.00 48B
ZLinq Where 0.00 0B

いずれの関数でも実行時間が短くGCの発生が抑えられています

まとめ

本記事ではZLinqの導入から使い方、パフォーマンスの比較まで説明しました。
現在使っているLinqのコードを差し替えるだけでパフォーマンスの向上ができるので、導入する価値は十分にあると思います。
是非検討してみてください

Discussion