Optimize managed memory allocations in Editor profiler
This commit is contained in:
@@ -34,6 +34,7 @@ namespace FlaxEditor.Windows.Profiler
|
|||||||
private List<ClickableRow> _tableRowsCache;
|
private List<ClickableRow> _tableRowsCache;
|
||||||
private Dictionary<Guid, Resource> _resourceCache;
|
private Dictionary<Guid, Resource> _resourceCache;
|
||||||
private StringBuilder _stringBuilder;
|
private StringBuilder _stringBuilder;
|
||||||
|
private Asset[] _assetsCache;
|
||||||
|
|
||||||
public Assets()
|
public Assets()
|
||||||
: base("Assets")
|
: base("Assets")
|
||||||
@@ -138,12 +139,12 @@ namespace FlaxEditor.Windows.Profiler
|
|||||||
_stringBuilder = new StringBuilder();
|
_stringBuilder = new StringBuilder();
|
||||||
|
|
||||||
// Capture current assets usage info
|
// Capture current assets usage info
|
||||||
var assets = FlaxEngine.Content.Assets;
|
FlaxEngine.Content.GetAssets(ref _assetsCache, out var count);
|
||||||
var resources = new Resource[assets.Length];
|
var resources = new Resource[count];
|
||||||
ulong totalMemoryUsage = 0;
|
ulong totalMemoryUsage = 0;
|
||||||
for (int i = 0; i < resources.Length; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
var asset = assets[i];
|
var asset = _assetsCache[i];
|
||||||
ref var resource = ref resources[i];
|
ref var resource = ref resources[i];
|
||||||
if (!asset)
|
if (!asset)
|
||||||
continue;
|
continue;
|
||||||
@@ -179,6 +180,7 @@ namespace FlaxEditor.Windows.Profiler
|
|||||||
if (_resources == null)
|
if (_resources == null)
|
||||||
_resources = new SamplesBuffer<Resource[]>();
|
_resources = new SamplesBuffer<Resource[]>();
|
||||||
_resources.Add(resources);
|
_resources.Add(resources);
|
||||||
|
Array.Clear(_assetsCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -200,6 +202,7 @@ namespace FlaxEditor.Windows.Profiler
|
|||||||
_resourceCache?.Clear();
|
_resourceCache?.Clear();
|
||||||
_tableRowsCache?.Clear();
|
_tableRowsCache?.Clear();
|
||||||
_stringBuilder?.Clear();
|
_stringBuilder?.Clear();
|
||||||
|
_assetsCache = null;
|
||||||
|
|
||||||
base.OnDestroy();
|
base.OnDestroy();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ namespace FlaxEditor.Windows.Profiler
|
|||||||
private Dictionary<string, Guid> _assetPathToId;
|
private Dictionary<string, Guid> _assetPathToId;
|
||||||
private Dictionary<Guid, Resource> _resourceCache;
|
private Dictionary<Guid, Resource> _resourceCache;
|
||||||
private StringBuilder _stringBuilder;
|
private StringBuilder _stringBuilder;
|
||||||
|
private GPUResource[] _gpuResourcesCached;
|
||||||
|
|
||||||
public MemoryGPU()
|
public MemoryGPU()
|
||||||
: base("GPU Memory")
|
: base("GPU Memory")
|
||||||
@@ -138,12 +139,12 @@ namespace FlaxEditor.Windows.Profiler
|
|||||||
|
|
||||||
// Capture current GPU resources usage info
|
// Capture current GPU resources usage info
|
||||||
var contentDatabase = Editor.Instance.ContentDatabase;
|
var contentDatabase = Editor.Instance.ContentDatabase;
|
||||||
var gpuResources = GPUDevice.Instance.Resources;
|
GPUDevice.Instance.GetResources(ref _gpuResourcesCached, out var count);
|
||||||
var resources = new Resource[gpuResources.Length];
|
var resources = new Resource[count];
|
||||||
var sb = _stringBuilder;
|
var sb = _stringBuilder;
|
||||||
for (int i = 0; i < resources.Length; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
var gpuResource = gpuResources[i];
|
var gpuResource = _gpuResourcesCached[i];
|
||||||
ref var resource = ref resources[i];
|
ref var resource = ref resources[i];
|
||||||
|
|
||||||
// Try to reuse cached resource info
|
// Try to reuse cached resource info
|
||||||
@@ -219,6 +220,7 @@ namespace FlaxEditor.Windows.Profiler
|
|||||||
if (_resources == null)
|
if (_resources == null)
|
||||||
_resources = new SamplesBuffer<Resource[]>();
|
_resources = new SamplesBuffer<Resource[]>();
|
||||||
_resources.Add(resources);
|
_resources.Add(resources);
|
||||||
|
Array.Clear(_gpuResourcesCached);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -255,6 +257,7 @@ namespace FlaxEditor.Windows.Profiler
|
|||||||
_assetPathToId?.Clear();
|
_assetPathToId?.Clear();
|
||||||
_tableRowsCache?.Clear();
|
_tableRowsCache?.Clear();
|
||||||
_stringBuilder?.Clear();
|
_stringBuilder?.Clear();
|
||||||
|
_gpuResourcesCached = null;
|
||||||
|
|
||||||
base.OnDestroy();
|
base.OnDestroy();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,20 @@ namespace FlaxEngine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the assets (loaded or during load).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">Output buffer to fill with asset pointers. Can be provided by a user to avoid memory allocation. Buffer might be larger than actual list size. Use <paramref name="count"/> for actual item count.></param>
|
||||||
|
/// <param name="count">Amount of valid items inside <paramref name="buffer"/>.</param>
|
||||||
|
public static void GetAssets(ref Asset[] buffer, out int count)
|
||||||
|
{
|
||||||
|
count = 0;
|
||||||
|
IntPtr ptr = Internal_GetAssetsInternal();
|
||||||
|
ManagedArray array = Unsafe.As<ManagedArray>(ManagedHandle.FromIntPtr(ptr).Target);
|
||||||
|
buffer = NativeInterop.GCHandleArrayToManagedArray<Asset>(array, buffer);
|
||||||
|
count = buffer.Length;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads asset to the Content Pool and holds it until it won't be referenced by any object. Returns null if asset is missing. Actual asset data loading is performed on a other thread in async.
|
/// Loads asset to the Content Pool and holds it until it won't be referenced by any object. Returns null if asset is missing. Actual asset data loading is performed on a other thread in async.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -195,17 +195,19 @@ namespace FlaxEngine.Interop
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">Array element type.</typeparam>
|
/// <typeparam name="T">Array element type.</typeparam>
|
||||||
/// <param name="ptrArray">Input array.</param>
|
/// <param name="ptrArray">Input array.</param>
|
||||||
|
/// <param name="buffer">Cached memory allocation buffer to use for the result (if size fits).</param>
|
||||||
/// <returns>Output array.</returns>
|
/// <returns>Output array.</returns>
|
||||||
public static T[] GCHandleArrayToManagedArray<T>(ManagedArray ptrArray) where T : class
|
public static T[] GCHandleArrayToManagedArray<T>(ManagedArray ptrArray, T[] buffer = null) where T : class
|
||||||
{
|
{
|
||||||
Span<IntPtr> span = ptrArray.ToSpan<IntPtr>();
|
Span<IntPtr> span = ptrArray.ToSpan<IntPtr>();
|
||||||
T[] managedArray = new T[ptrArray.Length];
|
if (buffer == null || buffer.Length < ptrArray.Length)
|
||||||
for (int i = 0; i < managedArray.Length; i++)
|
buffer = new T[ptrArray.Length];
|
||||||
|
for (int i = 0; i < ptrArray.Length; i++)
|
||||||
{
|
{
|
||||||
IntPtr ptr = span[i];
|
IntPtr ptr = span[i];
|
||||||
managedArray[i] = ptr != IntPtr.Zero ? (T)ManagedHandle.FromIntPtr(ptr).Target : default;
|
buffer[i] = ptr != IntPtr.Zero ? (T)ManagedHandle.FromIntPtr(ptr).Target : default;
|
||||||
}
|
}
|
||||||
return managedArray;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -20,6 +20,20 @@ namespace FlaxEngine
|
|||||||
return NativeInterop.GCHandleArrayToManagedArray<GPUResource>(array);
|
return NativeInterop.GCHandleArrayToManagedArray<GPUResource>(array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list with all active GPU resources.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">Output buffer to fill with resource pointers. Can be provided by a user to avoid memory allocation. Buffer might be larger than actual list size. Use <paramref name="count"/> for actual item count.></param>
|
||||||
|
/// <param name="count">Amount of valid items inside <paramref name="buffer"/>.</param>
|
||||||
|
public void GetResources(ref GPUResource[] buffer, out int count)
|
||||||
|
{
|
||||||
|
count = 0;
|
||||||
|
IntPtr ptr = Internal_GetResourcesInternal(__unmanagedPtr);
|
||||||
|
ManagedArray array = Unsafe.As<ManagedArray>(ManagedHandle.FromIntPtr(ptr).Target);
|
||||||
|
buffer = NativeInterop.GCHandleArrayToManagedArray<GPUResource>(array, buffer);
|
||||||
|
count = buffer.Length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
partial struct GPUBufferDescription : IEquatable<GPUBufferDescription>
|
partial struct GPUBufferDescription : IEquatable<GPUBufferDescription>
|
||||||
|
|||||||
Reference in New Issue
Block a user