Skip to content

Conversation

matsutaka-pxv
Copy link
Contributor

@matsutaka-pxv matsutaka-pxv commented Mar 12, 2025

CreateNativeArray<T>(ArraySegment) による GC Alloc の様子

以下のスクリーンショットは、手元のアプリケーションプログラムを実行した際、
VRM ファイルをロードしたフレームでの Unity Profiler の様子です

image

ここで、 GC Alloc の量が目立つ場所の1つに NativeArrayManager.CreateNativeArray<T>() 下の ArraySegment`1.ToArray() があります。

UniVRM v0.128.3 の時点での、このコードの実体は以下のようなループコピーですが

https://github.com/vrm-c/UniVRM/blob/v0.128.3/Assets/UniGLTF/Runtime/UniGLTF/IO/NativeArrayManager.cs#L69-L75

public NativeArray<T> CreateNativeArray<T>(
  ArraySegment<T> data
) where T : struct
{
    var array = CreateNativeArray<T>(data.Count);
    for (int i = 0; i < data.Count; i++)
        array[i] = data.Array[data.Offset + i];
    return array;
}

ループ内の data.Array[] によって ArraySegment<>.ToArray() が呼び出されているため、結果として大量の GC Alloc が発生する場合があります。

Span の使用による GC Alloc の軽減案

この PR では、 ArraySegment.ToArray() による GC Alloc を避けるために Span を使用しています。

Unity 2022 以降では、 NativeArray, ArraySegment ともに AsSpan が使用可能になりました。
これを利用して、 Span 間での Span.CopyTo によるコピーを用いることで、 ArraySegment<>.ToArray() の呼び出しを削減するのがこの PR の差分です。
結果として中間オブジェクト生成による GC Alloc が行われないコピーが可能になります。

使用している API

以下の API を使用しています

ArraySegment.AsSpan() によって Span を取得し、
NativeArray.AsSpan() で得たコピー先 Span に向けて
Span.CopyTo() によるコピーを行う。

data.Array[] による ArraySegment.ToArray() の呼び出しが無くなった結果、
GC Alloc が減少する。
Copy link
Contributor

@ousttrue ousttrue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@ousttrue
Copy link
Contributor

Unity 2022 以降では、 NativeArray, ArraySegment ともに AsSpan が使用可能になりました。

UniVRM-0.128.0 以降の Unity Version は 2022 以降

@ousttrue ousttrue merged commit 6cfdebf into vrm-c:master Mar 13, 2025
2 of 3 checks passed
@matsutaka-pxv matsutaka-pxv deleted the remove-arraysegment-toarray branch May 15, 2025 01:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants