Async loading levels

Hi ^^ノシ
I’m trying to asynchronously load a level using LoadPackageAsync(). Simply using OpenLevel() freezes the game for about 10 seconds. The level has lots of static mesh actors placed inside (around 17k) which I believe is the reason it takes so long to load. I tried async loading it with this code:

void UCustomGameInstance::PostLevelLoadProcess(FName const& PackageName, UPackage* LoadedPackage, EAsyncLoadingResult::Type Result)
{
	// Prevent Garbage collector from deleting loaded package and world
	PackageBeingLoaded = LoadedPackage;
	WorldBeingLoaded   = UWorld::FindWorldInPackage(LoadedPackage);
	if (AfterLoadPreHeatDuration > 0)
	{
		FTimerHandle TimerHandle;
		GetWorld()->GetTimerManager().SetTimer(TimerHandle, [this, PackageName]()
			{
				// Loading level PreLevelChangeDispatch
				if(AAdvancedBaseGameMode* GameMode = Cast<AAdvancedBaseGameMode>(GetWorld()->GetAuthGameMode()))
				{
					GameMode->PreLevelChangeDispatch();
				}

				// Reset Defaults
				AfterLoadPreHeatDuration = 0.f;
				bAbsoluteLoad            = true;
				LoadOptions              = FString(L"");

				// Open loaded level
				UGameplayStatics::OpenLevel(GetWorld(), WorldBeingLoaded->GetFName(), bAbsoluteLoad, LoadOptions);
		}, AfterLoadPreHeatDuration, false);
	}
	else
	{
		// Loading level PreLevelChangeDispatch
		if(AAdvancedBaseGameMode* GameMode = Cast<AAdvancedBaseGameMode>(GetWorld()->GetAuthGameMode()))
		{
			GameMode->PreLevelChangeDispatch();
		}

		// Reset Defaults
		AfterLoadPreHeatDuration = 0.f;
		bAbsoluteLoad            = true;
		LoadOptions              = FString(L"");

		// Open loaded level
		UGameplayStatics::OpenLevel(this, PackageName, bAbsoluteLoad, LoadOptions);
	}
}

void UCustomGameInstance::PostLoadedLevelInitialization(UWorld* LoadedWorld, UWorld::InitializationValues InitializationValues)
{
	// Loaded World should be the same as the pointer we saved unless its the loading level or first game open
	if (LoadedWorld == WorldBeingLoaded)
	{
		WorldBeingLoaded   = nullptr;
		PackageBeingLoaded = nullptr;
	}
}

void UCustomGameInstance::ChangeMainLevelAsync(const FString& InLevelName, float PreHeatDuration, bool bAbsolute, FString Options)
{
	if(AAdvancedBaseGameMode* GameMode = Cast<AAdvancedBaseGameMode>(GetWorld()->GetAuthGameMode()))
	{
		GameMode->PreLevelChangeDispatch();
	}

	// Change load properties
	AfterLoadPreHeatDuration = PreHeatDuration;
	bAbsoluteLoad            = bAbsolute;
	LoadOptions              = Options;

	// Open loading level
	UGameplayStatics::OpenLevel(this, Levels::LoadingLevelFullName, bAbsolute, Options);

	// Load target level asynchronously
	LoadPackageAsync(InLevelName, FLoadPackageAsyncDelegate::CreateLambda([this](FName const& PackageName, UPackage* LoadedPackage, EAsyncLoadingResult::Type Result)
	{
		if (Result == EAsyncLoadingResult::Succeeded)
		{
			PostLevelLoadProcess(PackageName, LoadedPackage, Result);
		}
		else
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to load level: %s"), *PackageName.ToString());
		}
	}),0 , PKG_ContainsMap);
}

void UCustomGameInstance::Init()
{
	Super::Init();

	FWorldDelegates::OnPostWorldInitialization.AddUObject(this, &UCustomGameInstance::PostLoadedLevelInitialization);
}

Now the problem is PostLevelLoadProcess() gets called almost instantly after the LoadPackageAsync() but when I open level the game goes on 10 seconds freeze again. I save pointers from the Uworld and UPackage of the loaded package to prevent them from being garbage collected before openLevel getting called but when I checked the pointer for the opened world inside the PostLoadedLevelInitialization() it is different from the UWorld pointer I saved O.o I even went as far as checking if the saved pointer using ISValid ( thinking maybe the world from the package got moved under the hood? not sure if moving will make the result of IsValid false, have to try it later) and the original pointer is still valid. Can anyone please explain what is going on here? I also found this inside logs
LogStreaming: Display: FlushAsyncLoading(): 0 QueuedPackages, 1 AsyncPackages
LogStreaming: Display: FlushAsyncLoading(): 16284 QueuedPackages, 0 AsyncPackages
Is LoadPackageAsync simply loading level without any of it’s placed actors and then openLevel can’t use it because of that? Any help is appreciated here…