IL2CPPでsealedを付けても速くならない

最終更新日


Unityでclassを定義するときにsealedを付けると高速化すると言う話があります。この話の大本のソースはIL2CPP Optimizations: Devirtualizationだと思います。

では実際にどのくらい速くなるのか計測するために以下のコードで試してみました。記事通りならInvokeNonSealedよりもInvokeSealedの方が高速なはずです。

using NUnit.Framework;
using Unity.PerformanceTesting;

public abstract class Parent
{
    public abstract string Method();
}

public class NonSealedChild : Parent
{
    public override string Method() => nameof(NonSealedChild);
}

public sealed class SealedChild : Parent
{
    public override string Method() => nameof(SealedChild);
}


public class PerformanceTest
{
    [Test, Performance]
    public void InvokeNonSealed()
    {
        var c = new NonSealedChild();

        Measure.Method(() => { c.Method(); })
            .WarmupCount(10)
            .MeasurementCount(100)
            .IterationsPerMeasurement(100000)
            .Run();
    }

    [Test, Performance]
    public void InvokeSealed()
    {
        var c = new SealedChild();

        Measure.Method(() => { c.Method(); })
            .WarmupCount(10)
            .MeasurementCount(100)
            .IterationsPerMeasurement(100000)
            .Run();
    }
}

Unity2020.3.17での計測結果は以下になります。ほとんど変わりません。

IL2CPPでビルドされたC++のコードを直接確認しても、どちらもVirtFuncInvoker0を使って呼ばれているので速くなる理由がありません。

どうしてこうなったかというと、現在のUnityではDevirtualizationが行われていないためです。Unityの方が明言しています

sealedを付けるべきか?

ややこしいことに、UnityのIL2CPPでは高速化しませんが.NET6では高速化されます。Unityでは.NET5を飛ばして.NET6をサポートするつもりではあるようです。なので将来的にはUnityでも高速化される可能性があります。将来のためにも可能な箇所ではsealedを付けておくのが良いと思います。


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

コメントする