diff --git a/OpenDreamRuntime/Objects/DreamObject.cs b/OpenDreamRuntime/Objects/DreamObject.cs index cfa73be66b..8148662b42 100644 --- a/OpenDreamRuntime/Objects/DreamObject.cs +++ b/OpenDreamRuntime/Objects/DreamObject.cs @@ -17,6 +17,7 @@ namespace OpenDreamRuntime.Objects { [Virtual] public class DreamObject { + private ProfilerMemory? _tracyMemoryId; public DreamObjectDefinition ObjectDefinition; [Access(typeof(DreamObject))] @@ -87,6 +88,8 @@ public DreamObject(DreamObjectDefinition objectDefinition) { if (this is not DreamObjectAtom && IsSubtypeOf(ObjectTree.Datum)) { ObjectDefinition.DreamManager.Datums.AddLast(new WeakDreamRef(this)); } + + _tracyMemoryId = Profiler.BeginMemoryZone((ulong)(Unsafe.SizeOf() + ObjectDefinition.Variables.Count * Unsafe.SizeOf() ), "object"); } public virtual void Initialize(DreamProcArguments args) { @@ -145,6 +148,7 @@ public void Delete(bool possiblyThreaded = false) { } public bool IsSubtypeOf(TreeEntry ancestor) { + if(Deleted) return false; return ObjectDefinition.IsSubtypeOf(ancestor); } diff --git a/OpenDreamRuntime/Profile.cs b/OpenDreamRuntime/Profile.cs index 50034028d8..9926e27c4f 100644 --- a/OpenDreamRuntime/Profile.cs +++ b/OpenDreamRuntime/Profile.cs @@ -1,5 +1,6 @@ using System.Diagnostics.Contracts; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using bottlenoselabs.C2CS.Runtime; using static Tracy.PInvoke; @@ -8,6 +9,7 @@ namespace OpenDreamRuntime; public static class Profiler{ //whether these procs are NOPs or not. Defaults to false. Use ActivateTracy() to set true private static bool _tracyActivated; + private static UInt64 _memoryUID = 0; // Plot names need to be cached for the lifetime of the program // seealso Tracy docs section 3.1 @@ -72,6 +74,17 @@ public static bool IsActivated() { return new ProfilerZone(context); } + public static ProfilerMemory? BeginMemoryZone(ulong size, string? name) + { + if(!_tracyActivated) + return null; + + var namestr = name is null ? GetPlotCString("null") : GetPlotCString(name); + unsafe { + return new ProfilerMemory((void*)_memoryUID++, size, namestr); + } + } + /// /// Configure how Tracy will display plotted values. /// @@ -234,3 +247,19 @@ public void Dispose(){ TracyEmitZoneEnd(Context); } } + +public sealed unsafe class ProfilerMemory { + + private readonly void* _ptr; + private CString _name; + + internal ProfilerMemory(void* pointer, ulong size, CString name){ + _ptr = pointer; + _name = name; + TracyEmitMemoryAllocNamed(_ptr, size, 0, _name); + } + + ~ProfilerMemory(){ + TracyEmitMemoryFreeNamed(_ptr, 0, _name); + } +} diff --git a/OpenDreamRuntime/Resources/DreamResource.cs b/OpenDreamRuntime/Resources/DreamResource.cs index 44ad6a5a94..09374ee8e0 100644 --- a/OpenDreamRuntime/Resources/DreamResource.cs +++ b/OpenDreamRuntime/Resources/DreamResource.cs @@ -19,16 +19,19 @@ public byte[]? ResourceData { private readonly string? _filePath; private byte[]? _resourceData; + private ProfilerMemory? _tracyMemoryId; public DreamResource(int id, string? filePath, string? resourcePath) { Id = id; ResourcePath = resourcePath; _filePath = filePath; + _tracyMemoryId = Profiler.BeginMemoryZone(ResourceData is null? 0 : (ulong)ResourceData.Length, "resource"); } public DreamResource(int id, byte[] data) { Id = id; _resourceData = data; + _tracyMemoryId = Profiler.BeginMemoryZone(ResourceData is null? 0 : (ulong)ResourceData.Length, "resource"); } public virtual string? ReadAsString() {