1 module profiled; 2 3 import core.sync.mutex; 4 import std; 5 6 private: 7 8 public __gshared Profiler theProfiler; 9 10 abstract class Event 11 { 12 public abstract string toJson(); 13 } 14 15 // TODO 16 string tid2string(Tid id) 17 { 18 import std.conv : text; 19 20 // dfmt off 21 return id 22 .text 23 .replace("Tid(", "") 24 .replace(")", "")[5 .. $ - 1] 25 .to!(long)(16) 26 .to!string; 27 // dfmt on 28 } 29 30 class CompleteEvent : Event 31 { 32 string name; 33 Tid threadId; 34 MonoTime start; 35 Duration duration; 36 this(string name, Tid threadId, MonoTime start, Duration duration) 37 { 38 this.name = name; 39 this.threadId = threadId; 40 this.start = start; 41 this.duration = duration; 42 } 43 44 override public string toJson() 45 { 46 // dfmt off 47 return `{"name":"%s","cat":"category","ph":"X","ts":%s,"dur":%s, "pid":1, "tid":%s}` 48 .format(name, 49 convClockFreq(start.ticks, 50 MonoTime.ticksPerSecond, 1_000_000).to!string, 51 duration.total!("usecs"), 52 tid2string(threadId)); 53 // dfmt on 54 } 55 } 56 57 class CompleteEventProcess 58 { 59 Profiler profiler; 60 string name; 61 Tid tid; 62 MonoTime start; 63 this(Profiler profiler, string name, Tid tid, MonoTime start) 64 { 65 this.profiler = profiler; 66 this.name = name; 67 this.tid = tid; 68 this.start = start; 69 } 70 71 ~this() 72 { 73 profiler.add(new CompleteEvent(name, tid, start, MonoTime.currTime - start)); 74 } 75 } 76 77 public class Profiler 78 { 79 Mutex eventsMutex; 80 Appender!(Event[]) events = appender!(Event[]); 81 this() 82 { 83 eventsMutex = new Mutex(); 84 } 85 86 public Unique!CompleteEventProcess start(string name) 87 { 88 Unique!CompleteEventProcess result = new CompleteEventProcess(this, 89 name, thisTid, MonoTime.currTime); 90 return result; 91 } 92 93 public void add(Event e) 94 { 95 eventsMutex.lock; 96 scope (exit) 97 eventsMutex.unlock; 98 events ~= e; 99 } 100 101 public void dumpJson(string filename) 102 { 103 auto f = File(filename, "w"); 104 f.writeln("["); 105 bool first = true; 106 eventsMutex.lock; 107 scope(exit) 108 eventsMutex.unlock; 109 foreach (e; events[]) 110 { 111 if (first) 112 { 113 first = false; 114 } 115 else 116 { 117 f.writeln(","); 118 } 119 f.write(e.toJson()); 120 } 121 } 122 } 123 124 public class NoopProfiler : Profiler 125 { 126 override public void add(Event e) 127 { 128 } 129 130 override public void dumpJson(string filename) 131 { 132 } 133 }