Torus Solutions 改

Ello 2021-11-16T06:05:43.112Z

Spine の UE4 ランタイムが盛大にメモリリークを引き起こしていたので、Deleaker というツールを使って調べてみた。結果からいうと、Spine プラグインのコードに以下のような変更を加えることでリークしなくなった。

diff --git a/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponent.cpp b/Plugins/SpinePlugin/Sou
rce/SpinePlugin/Private/SpineSkeletonRendererComponent.cpp
index 6e1b5ada..f9612ee6 100644
--- a/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponent.cpp
+++ b/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponent.cpp
@@ -41,6 +41,7 @@ USpineSkeletonRendererComponent::USpineSkeletonRendererComponent (const FObjectI
        PrimaryComponentTick.bCanEverTick = true;
        bTickInEditor = true;
        bAutoActivate = true;
+       bUseAsyncCooking = true;

       static ConstructorHelpers::FObjectFinder<UMaterialInterface> NormalMaterialRef(TEXT("/SpinePlugin/SpineUnlitNorm
alMaterial"));
        NormalBlendMaterial = NormalMaterialRef.Object;

ここで加えた bUseAsyncCooking という変数は、プロシージャルメッシュの生成の動作に影響を与える。プロシージャルメッシュが生成されるとき、内部でコリジョンのアップデートのために下のような関数が呼ばれる:

void UProceduralMeshComponent::UpdateCollision()
{
    (...)
	if(bUseAsyncCook)
	{
		UseBodySetup->CreatePhysicsMeshesAsync(FOnAsyncPhysicsCookFinished::CreateUObject(this, &UProceduralMeshComponent::FinishPhysicsAsyncCook, UseBodySetup));
	}
	else
	{
		// New GUID as collision has changed
		UseBodySetup->BodySetupGuid = FGuid::NewGuid();
		// Also we want cooked data for this
		UseBodySetup->bHasCookedCollisionData = true;
		UseBodySetup->InvalidatePhysicsData();
		UseBodySetup->CreatePhysicsMeshes();
		RecreatePhysicsState();
	}
}

ここで bUseAsyncCook が偽の時は、FGuid::NewGuid() が呼ばれるんだけど、これが内部的に Windows API の CoCreateGuid という関数を呼び出し、これがクリティカルセクションを作る。

なぜクリティカルセクションがひどいメモリリークにつながるのかは分からないけど、この部分が実行されないように bUseAsyncCook を真に設定したら実際にメモリリークが起こらなくなった。

上の画像が変更後で、下が変更前。これを見ると、変更前は何らかの原因で GC が阻害されていたように見える。

Twitter のスレッド:Toru Hisai on Twitter: "https://t.co/ycdj5D9s13 Spine の UE4 ランタイムが盛大にメモリリークしているようなので、Deleaker というのを試してみる。" / Twitter

#UE4 #Spine