SpanによるUniGLTF.NativeArrayManager.CreateNativeArray(ArraySegment)の改善 #2606
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
CreateNativeArray<T>(ArraySegment)
による GC Alloc の様子以下のスクリーンショットは、手元のアプリケーションプログラムを実行した際、
VRM ファイルをロードしたフレームでの Unity Profiler の様子です
ここで、 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
ループ内の
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 を使用しています
NativeArray<T0>.AsSpan
MemoryExtensions.AsSpan(ArraySegment)
Span<T>.CopyTo(Span<T>)