Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracy #2127

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open

Tracy #2127

Show file tree
Hide file tree
Changes from 22 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<Project>
<Import Project="RobustToolbox/Directory.Packages.props" />
<ItemGroup>
<PackageVersion Include="NUnit.ConsoleRunner" Version="3.15.0" />
<PackageVersion Include="Byond.TopicSender" Version="8.0.1" />
</ItemGroup>
<Import Project="RobustToolbox/Directory.Packages.props" />
<ItemGroup>
<PackageVersion Include="NUnit.ConsoleRunner" Version="3.15.0" />
<PackageVersion Include="Byond.TopicSender" Version="8.0.1" />
<PackageVersion Include="Tracy-CSharp" Version="0.11.1-hotfix" />
</ItemGroup>
</Project>
41 changes: 28 additions & 13 deletions OpenDreamRuntime/DreamManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,17 @@ public void StartWorld() {
Initialized = true;
InitializedTick = _gameTiming.CurTick;

// Call global <init> with waitfor=FALSE
_objectTree.GlobalInitProc?.Spawn(WorldInstance, new());
using (Profiler.BeginZone("StartWorld", color:(uint)Color.OrangeRed.ToArgb())) {
// Call global <init> with waitfor=FALSE
_objectTree.GlobalInitProc?.Spawn(WorldInstance, new());

// Call New() on all /area and /turf that exist, each with waitfor=FALSE separately. If <global init> created any /area, call New a SECOND TIME
// new() up /objs and /mobs from compiled-in maps [order: (1,1) then (2,1) then (1,2) then (2,2)]
_dreamMapManager.InitializeAtoms(_compiledJson.Maps);
// Call New() on all /area and /turf that exist, each with waitfor=FALSE separately. If <global init> created any /area, call New a SECOND TIME
// new() up /objs and /mobs from compiled-in maps [order: (1,1) then (2,1) then (1,2) then (2,2)]
_dreamMapManager.InitializeAtoms(_compiledJson.Maps);

// Call world.New()
WorldInstance.SpawnProc("New");
// Call world.New()
WorldInstance.SpawnProc("New");
}
}

public void Shutdown() {
Expand All @@ -102,13 +104,26 @@ public void Shutdown() {
public void Update() {
if (!Initialized)
return;
using (Profiler.BeginZone("Tick", color:(uint)Color.OrangeRed.ToArgb()))
{
using (Profiler.BeginZone("DM Execution", color:(uint)Color.LightPink.ToArgb()))
_procScheduler.Process();

using (Profiler.BeginZone("Map Update", color:(uint)Color.LightPink.ToArgb())){
UpdateStat();
_dreamMapManager.UpdateTiles();
}

using (Profiler.BeginZone("Disk IO", color:(uint)Color.LightPink.ToArgb()))
Fixed Show fixed Hide fixed
DreamObjectSavefile.FlushAllUpdates();

WorldInstance.SetVariableValue("cpu", WorldInstance.GetVariable("tick_usage"));

using (Profiler.BeginZone("Deletion Queue", color:(uint)Color.LightPink.ToArgb()))
ProcessDelQueue();
}

_procScheduler.Process();
UpdateStat();
_dreamMapManager.UpdateTiles();
DreamObjectSavefile.FlushAllUpdates();
WorldInstance.SetVariableValue("cpu", WorldInstance.GetVariable("tick_usage"));
ProcessDelQueue();
Profiler.EmitFrameMark();
Fixed Show fixed Hide fixed
}

public void ProcessDelQueue() {
Expand Down
54 changes: 52 additions & 2 deletions OpenDreamRuntime/DreamThread.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,10 @@
public abstract class ProcState : IDisposable {
private static int _idCounter = 0;
public int Id { get; } = ++_idCounter;

#if TOOLS
public abstract (string SourceFile, int Line) TracyLocationId { get; }
public ProfilerZone? TracyZoneId { get; set; }
#endif
public DreamThread Thread { get; set; }

[Access(typeof(ProcScheduler))]
Expand Down Expand Up @@ -210,7 +213,10 @@
var context = new DreamThread(proc.ToString());

if (proc is NativeProc nativeProc) {
return nativeProc.Call(context, src, usr, new(arguments));
// ReSharper disable ExplicitCallerInfoArgument
using(Profiler.BeginZone(filePath:"Native Proc", lineNumber:0, memberName:nativeProc.Name))
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
return nativeProc.Call(context, src, usr, new(arguments));
// ReSharper restore ExplicitCallerInfoArgument
}

var state = proc.CreateState(context, src, usr, new DreamProcArguments(arguments));
Expand Down Expand Up @@ -252,6 +258,15 @@
while (_current != null) {
ProcStatus status;
try {
#if TOOLS
if (_current.TracyZoneId is null && _current.Proc != null) {
var location =_current.TracyLocationId;
var procpath = (_current.Proc.OwningType.Path.Equals("/") ? "/proc/" : _current.Proc.OwningType.Path+"/") +_current.Proc.Name;
// ReSharper disable ExplicitCallerInfoArgument
_current.TracyZoneId = Profiler.BeginZone(filePath: location.SourceFile, lineNumber: location.Line, memberName: procpath);
// ReSharper restore ExplicitCallerInfoArgument
}
#endif
// _current.Resume may mutate our state!!!
status = _current.Resume();
} catch (DMError dmError) {
Expand All @@ -274,8 +289,25 @@
switch (status) {
// The entire Thread is stopping
case ProcStatus.Cancelled:
#if TOOLS
if (_current.TracyZoneId is not null) {
_current.TracyZoneId.Value.Dispose();
_current.TracyZoneId = null;
}
#endif

var current = _current;
_current = null;

#if TOOLS
foreach (var s in _stack) {
if (s.TracyZoneId is null)
continue;
s.TracyZoneId.Value.Dispose();
s.TracyZoneId = null;
}
#endif

_stack.Clear();
resultStatus = status;
return current.Result;
Expand All @@ -298,6 +330,19 @@

// The context is done executing for now
case ProcStatus.Deferred:
#if TOOLS
if (_current.TracyZoneId is not null) {
_current.TracyZoneId.Value.Dispose();
_current.TracyZoneId = null;
}

foreach (var s in _stack) {
Fixed Show fixed Hide fixed
if (s.TracyZoneId is null)
continue;
s.TracyZoneId.Value.Dispose();
s.TracyZoneId = null;
}
#endif
// We return the current return value here even though it may not be the final result
resultStatus = status;
return _current.Result;
Expand Down Expand Up @@ -334,6 +379,11 @@
}

public void PopProcState(bool dispose = true) {
if (_current?.TracyZoneId is not null) {

Check failure on line 382 in OpenDreamRuntime/DreamThread.cs

View workflow job for this annotation

GitHub Actions / build

'ProcState' does not contain a definition for 'TracyZoneId' and no accessible extension method 'TracyZoneId' accepting a first argument of type 'ProcState' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 382 in OpenDreamRuntime/DreamThread.cs

View workflow job for this annotation

GitHub Actions / build

'ProcState' does not contain a definition for 'TracyZoneId' and no accessible extension method 'TracyZoneId' accepting a first argument of type 'ProcState' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 382 in OpenDreamRuntime/DreamThread.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

'ProcState' does not contain a definition for 'TracyZoneId' and no accessible extension method 'TracyZoneId' accepting a first argument of type 'ProcState' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 382 in OpenDreamRuntime/DreamThread.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

'ProcState' does not contain a definition for 'TracyZoneId' and no accessible extension method 'TracyZoneId' accepting a first argument of type 'ProcState' could be found (are you missing a using directive or an assembly reference?)
_current.TracyZoneId.Value.Dispose();

Check failure on line 383 in OpenDreamRuntime/DreamThread.cs

View workflow job for this annotation

GitHub Actions / build

'ProcState' does not contain a definition for 'TracyZoneId' and no accessible extension method 'TracyZoneId' accepting a first argument of type 'ProcState' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 383 in OpenDreamRuntime/DreamThread.cs

View workflow job for this annotation

GitHub Actions / build

'ProcState' does not contain a definition for 'TracyZoneId' and no accessible extension method 'TracyZoneId' accepting a first argument of type 'ProcState' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 383 in OpenDreamRuntime/DreamThread.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

'ProcState' does not contain a definition for 'TracyZoneId' and no accessible extension method 'TracyZoneId' accepting a first argument of type 'ProcState' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 383 in OpenDreamRuntime/DreamThread.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

'ProcState' does not contain a definition for 'TracyZoneId' and no accessible extension method 'TracyZoneId' accepting a first argument of type 'ProcState' could be found (are you missing a using directive or an assembly reference?)
_current.TracyZoneId = null;

Check failure on line 384 in OpenDreamRuntime/DreamThread.cs

View workflow job for this annotation

GitHub Actions / build

'ProcState' does not contain a definition for 'TracyZoneId' and no accessible extension method 'TracyZoneId' accepting a first argument of type 'ProcState' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 384 in OpenDreamRuntime/DreamThread.cs

View workflow job for this annotation

GitHub Actions / build

'ProcState' does not contain a definition for 'TracyZoneId' and no accessible extension method 'TracyZoneId' accepting a first argument of type 'ProcState' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 384 in OpenDreamRuntime/DreamThread.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

'ProcState' does not contain a definition for 'TracyZoneId' and no accessible extension method 'TracyZoneId' accepting a first argument of type 'ProcState' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 384 in OpenDreamRuntime/DreamThread.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

'ProcState' does not contain a definition for 'TracyZoneId' and no accessible extension method 'TracyZoneId' accepting a first argument of type 'ProcState' could be found (are you missing a using directive or an assembly reference?)
}

if (_current?.WaitFor == false) {
_syncCount--;
}
Expand Down
7 changes: 7 additions & 0 deletions OpenDreamRuntime/DreamValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,16 @@ public static DreamValue False {
private object? _refValue;
private readonly float _floatValue;

#if TOOLS
//ReSharper disable once NotAccessedField.Local
Fixed Show fixed Hide fixed
private readonly ProfilerMemory? _tracyMemoryId; //only used for strings, since everything else is a value type or handled in DreamObject
#endif
public DreamValue(string value) {
DebugTools.Assert(value != null);
Type = DreamValueType.String;
#if TOOLS
_tracyMemoryId = Profiler.BeginMemoryZone((ulong) (1+value.Length*sizeof(char)), "string");
#endif
_refValue = value;
}

Expand Down
1 change: 0 additions & 1 deletion OpenDreamRuntime/EntryPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using OpenDreamRuntime.Objects.Types;
using OpenDreamRuntime.Procs.DebugAdapter;
using OpenDreamShared;
using Robust.Server.ServerStatus;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
Expand Down
11 changes: 11 additions & 0 deletions OpenDreamRuntime/Objects/DreamObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
namespace OpenDreamRuntime.Objects {
[Virtual]
public class DreamObject {
#if TOOLS
protected ProfilerMemory? _tracyMemoryId;
Fixed Show fixed Hide fixed

Check warning

Code scanning / InspectCode

Inconsistent Naming Warning

Name '_tracyMemoryId' does not match rule 'Instance fields (not private)'. Suggested name is 'TracyMemoryId'.
#endif
public DreamObjectDefinition ObjectDefinition;

[Access(typeof(DreamObject))]
Expand Down Expand Up @@ -86,7 +89,11 @@
// Atoms are in world.contents
if (this is not DreamObjectAtom && IsSubtypeOf(ObjectTree.Datum)) {
ObjectDefinition.DreamManager.Datums.AddLast(new WeakDreamRef(this));
}
#if TOOLS
if(_tracyMemoryId is null) //if it's not null, subclasses have done their own allocation
Fixed Show fixed Hide fixed
_tracyMemoryId = Profiler.BeginMemoryZone((ulong)(Unsafe.SizeOf<DreamObject>() + ObjectDefinition.Variables.Count * Unsafe.SizeOf<DreamValue>() ), "/datum");
#endif
}

public virtual void Initialize(DreamProcArguments args) {
Expand All @@ -106,6 +113,9 @@
Variables = null;

ObjectDefinition = null!;
#if TOOLS
_tracyMemoryId?.ReleaseMemory();
#endif
}

/// <summary>
Expand Down Expand Up @@ -145,6 +155,7 @@
}

public bool IsSubtypeOf(TreeEntry ancestor) {
if(Deleted) return false;
return ObjectDefinition.IsSubtypeOf(ancestor);
}

Expand Down
74 changes: 38 additions & 36 deletions OpenDreamRuntime/Objects/DreamObjectTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,42 +139,44 @@ public IEnumerable<TreeEntry> GetAllDescendants(TreeEntry treeEntry) {
/// (by calling the result of <see cref="DreamObject.InitProc(DreamThread, DreamObject?, DreamProcArguments)"/> or <see cref="DreamObject.InitSpawn(DreamProcArguments)"/>)
/// </remarks>
public DreamObject CreateObject(TreeEntry type) {
if (type == List)
return CreateList();
if (type == Savefile)
return new DreamObjectSavefile(Savefile.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(DatabaseQuery))
return new DreamObjectDatabaseQuery(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Database))
return new DreamObjectDatabase(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Matrix))
return new DreamObjectMatrix(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Sound))
return new DreamObjectSound(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Regex))
return new DreamObjectRegex(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Image))
return new DreamObjectImage(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Icon))
return new DreamObjectIcon(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Filter))
return new DreamObjectFilter(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Mob))
return new DreamObjectMob(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Movable))
return new DreamObjectMovable(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Area))
return new DreamObjectArea(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Atom))
return new DreamObjectAtom(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Client))
throw new Exception("Cannot create objects of type /client");
if (type.ObjectDefinition.IsSubtypeOf(Turf))
throw new Exception("New turfs must be created by the map manager");
if (type.ObjectDefinition.IsSubtypeOf(Exception))
return new DreamObjectException(type.ObjectDefinition);

return new DreamObject(type.ObjectDefinition);
using(Profiler.BeginZone($"new {type}")){
if (type == List)
return CreateList();
if (type == Savefile)
return new DreamObjectSavefile(Savefile.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(DatabaseQuery))
return new DreamObjectDatabaseQuery(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Database))
return new DreamObjectDatabase(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Matrix))
return new DreamObjectMatrix(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Sound))
return new DreamObjectSound(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Regex))
return new DreamObjectRegex(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Image))
return new DreamObjectImage(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Icon))
return new DreamObjectIcon(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Filter))
return new DreamObjectFilter(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Mob))
return new DreamObjectMob(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Movable))
return new DreamObjectMovable(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Area))
return new DreamObjectArea(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Atom))
return new DreamObjectAtom(type.ObjectDefinition);
if (type.ObjectDefinition.IsSubtypeOf(Client))
throw new Exception("Cannot create objects of type /client");
if (type.ObjectDefinition.IsSubtypeOf(Turf))
throw new Exception("New turfs must be created by the map manager");
if (type.ObjectDefinition.IsSubtypeOf(Exception))
return new DreamObjectException(type.ObjectDefinition);

return new DreamObject(type.ObjectDefinition);
}
}

public T CreateObject<T>(TreeEntry type) where T : DreamObject {
Expand Down
32 changes: 31 additions & 1 deletion OpenDreamRuntime/Objects/Types/DreamList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ namespace OpenDreamRuntime.Objects.Types;
public class DreamList : DreamObject {
private readonly List<DreamValue> _values;
private Dictionary<DreamValue, DreamValue>? _associativeValues;

#if TOOLS
private ProfilerMemory? _tracyContentsMemoryId;
#endif
public override bool ShouldCallNew => false;

public virtual bool IsAssociative => (_associativeValues != null && _associativeValues.Count > 0);
Expand All @@ -28,6 +30,10 @@ public DreamList(DreamObjectDefinition listDef, int size) : base(listDef) {
public DreamList(DreamObjectDefinition listDef, List<DreamValue> values, Dictionary<DreamValue, DreamValue>? associativeValues) : base(listDef) {
_values = values;
_associativeValues = associativeValues;
#if TOOLS
_tracyMemoryId = Profiler.BeginMemoryZone(1, "/list instance");
_tracyContentsMemoryId = Profiler.BeginMemoryZone((ulong)(Unsafe.SizeOf<DreamList>() + _values.Count * Unsafe.SizeOf<DreamValue>() + (_associativeValues?.Count ?? 0) * Unsafe.SizeOf<DreamValue>()), "/list contents");
#endif
}

public override void Initialize(DreamProcArguments args) {
Expand Down Expand Up @@ -127,6 +133,10 @@ public virtual void SetValue(DreamValue key, DreamValue value, bool allowGrowth
_associativeValues ??= new Dictionary<DreamValue, DreamValue>(1);
_associativeValues[key] = value;
}
#if TOOLS
_tracyContentsMemoryId?.ReleaseMemory();
_tracyContentsMemoryId = Profiler.BeginMemoryZone((ulong)(Unsafe.SizeOf<DreamList>() + _values.Count * Unsafe.SizeOf<DreamValue>() + (_associativeValues?.Count ?? 0) * Unsafe.SizeOf<DreamValue>()), "/list contents");
#endif
}

public virtual void RemoveValue(DreamValue value) {
Expand All @@ -136,10 +146,18 @@ public virtual void RemoveValue(DreamValue value) {
_associativeValues?.Remove(value);
_values.RemoveAt(valueIndex);
}
#if TOOLS
_tracyContentsMemoryId?.ReleaseMemory();
_tracyContentsMemoryId = Profiler.BeginMemoryZone((ulong)(Unsafe.SizeOf<DreamList>() + _values.Count * Unsafe.SizeOf<DreamValue>() + (_associativeValues?.Count ?? 0) * Unsafe.SizeOf<DreamValue>()), "/list contents");
#endif
}

public virtual void AddValue(DreamValue value) {
_values.Add(value);
#if TOOLS
_tracyContentsMemoryId?.ReleaseMemory();
_tracyContentsMemoryId = Profiler.BeginMemoryZone((ulong)(Unsafe.SizeOf<DreamList>() + _values.Count * Unsafe.SizeOf<DreamValue>() + (_associativeValues?.Count ?? 0) * Unsafe.SizeOf<DreamValue>()), "/list contents");
#endif
}

//Does not include associations
Expand Down Expand Up @@ -176,10 +194,18 @@ public virtual void Cut(int start = 1, int end = 0) {

if (end > start)
_values.RemoveRange(start - 1, end - start);
#if TOOLS
_tracyContentsMemoryId?.ReleaseMemory();
_tracyContentsMemoryId = Profiler.BeginMemoryZone((ulong)(Unsafe.SizeOf<DreamList>() + _values.Count * Unsafe.SizeOf<DreamValue>() + (_associativeValues?.Count ?? 0) * Unsafe.SizeOf<DreamValue>()), "/list contents");
#endif
}

public void Insert(int index, DreamValue value) {
_values.Insert(index - 1, value);
#if TOOLS
_tracyContentsMemoryId?.ReleaseMemory();
_tracyContentsMemoryId = Profiler.BeginMemoryZone((ulong)(Unsafe.SizeOf<DreamList>() + _values.Count * Unsafe.SizeOf<DreamValue>() + (_associativeValues?.Count ?? 0) * Unsafe.SizeOf<DreamValue>()), "/list contents");
#endif
}

public void Swap(int index1, int index2) {
Expand All @@ -199,6 +225,10 @@ public void Resize(int size) {
} else {
Cut(size + 1);
}
#if TOOLS
_tracyContentsMemoryId?.ReleaseMemory();
_tracyContentsMemoryId = Profiler.BeginMemoryZone((ulong)(Unsafe.SizeOf<DreamList>() + _values.Count * Unsafe.SizeOf<DreamValue>() + (_associativeValues?.Count ?? 0) * Unsafe.SizeOf<DreamValue>()), "/list contents");
#endif
}

public virtual int GetLength() {
Expand Down
Loading
Loading