SceneProf.hx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. package h3d.impl;
  2. #if sceneprof
  3. private class Frame {
  4. public var samples : Array<{ time : Float, sect: String, stack : Array<String> }> = [];
  5. public var startTime : Float;
  6. public function new() {
  7. }
  8. }
  9. private class StackLink {
  10. static var UID = 1;
  11. public var id : Int;
  12. public var elt : String;
  13. public var parent : StackLink;
  14. public var children : Map<String,StackLink> = new Map();
  15. public var written : Bool;
  16. public function new(elt) {
  17. id = UID++;
  18. this.elt = elt;
  19. }
  20. public function getChildren(elt:String) {
  21. var c = children.get(elt);
  22. if( c == null ) {
  23. c = new StackLink(elt);
  24. c.parent = this;
  25. children.set(elt,c);
  26. }
  27. return c;
  28. }
  29. }
  30. class SceneProf {
  31. static var frames : Array<Frame>;
  32. static var curFrame : Frame;
  33. static var lastFrameId = -1;
  34. static var enable = false;
  35. static var curSection : String;
  36. static var stackCache : Map<h3d.scene.Object, Array<String>>;
  37. static var stackCache2d : Map<h2d.Object, Array<String>>;
  38. public static function start() {
  39. enable = true;
  40. stackCache = new Map();
  41. stackCache2d = new Map();
  42. frames = [];
  43. lastFrameId = -1;
  44. }
  45. public static function stop() {
  46. enable = false;
  47. }
  48. public static function begin(section: String, frame : Int) {
  49. if(!enable) return;
  50. if(frame != lastFrameId) {
  51. var f = new Frame();
  52. f.startTime = Sys.time();
  53. frames.push(f);
  54. curFrame = f;
  55. lastFrameId = frame;
  56. }
  57. curSection = section;
  58. }
  59. static function getStack(o: h3d.scene.Object) : Array<String> {
  60. var r = stackCache.get(o);
  61. if(r != null)
  62. return r;
  63. var s = null;
  64. if(o.parent != null)
  65. s = getStack(o.parent).copy();
  66. else s = [];
  67. var name = o.name != null ? o.name : Type.getClassName(Type.getClass(o));
  68. s.unshift(name);
  69. stackCache.set(o, s);
  70. return s;
  71. }
  72. static function getStack2d(o: h2d.Object) : Array<String> {
  73. var r = stackCache2d.get(o);
  74. if(r != null)
  75. return r;
  76. var s = null;
  77. if(o.parent != null)
  78. s = getStack2d(o.parent).copy();
  79. else s = [];
  80. var name = o.name != null ? o.name : Type.getClassName(Type.getClass(o));
  81. s.unshift(name);
  82. stackCache2d.set(o, s);
  83. return s;
  84. }
  85. public static function mark(?o3d: h3d.scene.Object, ?o2d: h2d.Object) {
  86. if(!enable) return;
  87. var t = Sys.time();
  88. curFrame.samples.push({
  89. time: t,
  90. sect: curSection,
  91. stack: o3d != null ? getStack(o3d) : getStack2d(o2d)
  92. });
  93. }
  94. public static function end() {
  95. if(!enable) return;
  96. curFrame.samples.push({
  97. time: Sys.time(),
  98. sect: curSection,
  99. stack: []
  100. });
  101. }
  102. public static function save(outFile: String) {
  103. function makeStacks( st : Array<StackLink> ) {
  104. var write = [];
  105. for( s in st ) {
  106. var s = s;
  107. while( s != null ) {
  108. if( s.written ) break;
  109. s.written = true;
  110. write.push(s);
  111. s = s.parent;
  112. }
  113. }
  114. write.sort(function(s1,s2) return s1.id - s2.id);
  115. return [for( s in write ) {
  116. callFrame : {
  117. functionName : s.elt,
  118. scriptId : 0,
  119. },
  120. id : s.id,
  121. parent : s.parent == null ? null : s.parent.id,
  122. }];
  123. }
  124. var json : Array<Dynamic> = [
  125. {
  126. pid : 0,
  127. tid : 0,
  128. ts : 0,
  129. ph : "M",
  130. cat : "__metadata",
  131. name : "thread_name",
  132. args : { name : "CrBrowserMain" }
  133. },
  134. {
  135. args: {
  136. data: {
  137. frameTreeNodeId: 0,
  138. frames: [
  139. {
  140. processId: 0,
  141. url: "http://x"
  142. }
  143. ],
  144. persistentIds: true
  145. }
  146. },
  147. cat: "disabled-by-default-devtools.timeline",
  148. name: "TracingStartedInBrowser",
  149. pid: 0,
  150. tid: 0,
  151. ts: 0
  152. }
  153. ];
  154. var count = 1;
  155. var f0 = frames[0];
  156. var t0 = f0.samples.length == 0 ? f0.startTime : f0.samples[0].time;
  157. var tid = 0;
  158. function timeStamp(t:Float) {
  159. return Std.int((t - t0) * 1000000) + 1;
  160. }
  161. var lastT = 0.;
  162. var rootStack = new StackLink("(root)");
  163. var profileId = count++;
  164. json.push({
  165. pid : 0,
  166. tid : tid,
  167. ts : 0,
  168. ph : "P",
  169. cat : "disabled-by-default-v8.cpu_profiler",
  170. name : "Profile",
  171. id : "0x"+profileId,
  172. args: { data : { startTime : 0 } },
  173. });
  174. for( f in frames ) {
  175. if( f.samples.length == 0 ) continue;
  176. var ts = timeStamp(f.startTime);
  177. var tend = timeStamp(f.samples[f.samples.length-1].time);
  178. json.push({
  179. pid : 0,
  180. tid : tid,
  181. ts : ts,
  182. dur : tend - ts,
  183. ph : "X",
  184. cat : "disabled-by-default-devtools.timeline",
  185. name : "RunTask",
  186. });
  187. }
  188. for( f in frames ) {
  189. if( f.samples.length == 0 ) continue;
  190. var timeDeltas = [];
  191. var allStacks = [];
  192. var lines = [];
  193. for( s in f.samples) {
  194. var st = rootStack;
  195. st = st.getChildren(s.sect);
  196. var line = 0;
  197. for( i in 0...s.stack.length ) {
  198. var s = s.stack[s.stack.length - 1 - i];
  199. st = st.getChildren(s);
  200. }
  201. allStacks.push(st);
  202. var t = Math.ffloor((s.time - t0) * 1000000);
  203. timeDeltas.push(t - lastT);
  204. lastT = t;
  205. }
  206. json.push({
  207. pid : 0,
  208. tid : tid,
  209. ts : 0,
  210. ph : "P",
  211. cat : "disabled-by-default-v8.cpu_profiler",
  212. name : "ProfileChunk",
  213. id : "0x"+profileId,
  214. args : {
  215. data : {
  216. cpuProfile : {
  217. nodes : makeStacks(allStacks),
  218. samples : [for( s in allStacks ) s.id]
  219. },
  220. timeDeltas : timeDeltas,
  221. }
  222. }
  223. });
  224. }
  225. sys.io.File.saveContent(outFile, haxe.Json.stringify(json));
  226. }
  227. }
  228. #end