2
0

Profile.hx 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * Copyright (C)2005-2019 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. */
  22. package hl;
  23. typedef Symbol = hl.Abstract<"hl_symbol">;
  24. enum TrackKind {
  25. Alloc;
  26. Cast;
  27. DynField;
  28. DynCall;
  29. }
  30. class Result {
  31. public var t:hl.Type;
  32. public var kind:TrackKind;
  33. public var count:Int;
  34. public var info:Int;
  35. public var stack:Array<String>;
  36. public function new(t, count, info) {
  37. this.t = t;
  38. this.count = count;
  39. this.info = info;
  40. }
  41. @:keep public function toString() {
  42. return t + "(" + count + ")";
  43. }
  44. }
  45. enum abstract EventCode(Int) to Int from Int {
  46. final EndOfFrame = 0;
  47. final Pause = -1;
  48. final Resume = -2;
  49. final ClearData = -3;
  50. final PauseAll = -4;
  51. final ResumeAll = -5;
  52. final Dump = -6;
  53. final Setup = -7;
  54. }
  55. @:hlNative("std")
  56. class Profile {
  57. public static var threadBits(get, set):haxe.EnumFlags<TrackKind>;
  58. public static var globalBits(get, set):haxe.EnumFlags<TrackKind>;
  59. static var KINDS = null;
  60. public static function getData(sortBySize = false, reset = true) {
  61. var old = globalBits;
  62. globalBits = new haxe.EnumFlags();
  63. if (buf == null)
  64. buf = new hl.Bytes(BUFSIZE * 2);
  65. track_lock(true);
  66. var maxDepth = 0;
  67. var count = track_count(maxDepth);
  68. var arr = new hl.NativeArray<Symbol>(maxDepth);
  69. var out = [];
  70. if (KINDS == null)
  71. KINDS = TrackKind.createAll();
  72. for (i in 0...count) {
  73. var t:hl.Type = null, count = 0, info = 0;
  74. var k = track_entry(i, t, count, info, arr);
  75. if (count == 0)
  76. continue;
  77. var a = new Result(t, count, info);
  78. a.kind = KINDS[k];
  79. a.stack = [for (a in arr) resolveSymbol(a)];
  80. out.push(a);
  81. }
  82. out.sort(function(a1, a2) {
  83. if (a1.kind != a2.kind)
  84. return a1.kind.getIndex() - a2.kind.getIndex();
  85. if (sortBySize && a1.kind == Alloc)
  86. return a2.info - a1.info;
  87. return a2.count - a1.count;
  88. });
  89. track_lock(false);
  90. if (reset)
  91. Profile.reset();
  92. globalBits = old;
  93. return out;
  94. }
  95. public static function dump(fileName = "track.dump", sortBySize = false, reset = true) {
  96. var old = globalBits;
  97. globalBits = new haxe.EnumFlags();
  98. var f = sys.io.File.write(fileName);
  99. var data = getData(sortBySize, reset);
  100. var allocCount = 0, allocSize = 0, castCount = 0, dynCount = 0;
  101. for (o in data) {
  102. switch (o.kind) {
  103. case Alloc:
  104. allocCount += o.count;
  105. allocSize += o.info;
  106. case Cast:
  107. castCount += o.count;
  108. case DynCall, DynField:
  109. dynCount += o.count;
  110. }
  111. }
  112. if (data.length == 0)
  113. f.writeString("Nothing\n");
  114. if (allocCount > 0)
  115. f.writeString(allocCount + " total allocs (" + allocSize + " bytes)\n");
  116. if (castCount > 0)
  117. f.writeString(castCount + " total casts\n");
  118. if (dynCount > 0)
  119. f.writeString(dynCount + " total dynamic accesses/calls\n");
  120. for (o in data) {
  121. var pcount = StringTools.lpad("" + o.count, " ", 5);
  122. switch (o.kind) {
  123. case Alloc:
  124. f.writeString("alloc " + pcount + " " + o.t + " (" + o.info + " bytes)\n");
  125. case Cast:
  126. f.writeString("cast " + pcount + " " + o.t + "\n");
  127. case DynCall:
  128. f.writeString("dyncall " + pcount + " " + o.t + "." + getFieldName(o.info) + "()\n");
  129. case DynField:
  130. f.writeString("dynfield " + pcount + " " + o.t + "." + getFieldName(o.info) + "\n");
  131. }
  132. for (s in o.stack)
  133. f.writeString("\t\t\t\t" + s + "\n");
  134. }
  135. f.close();
  136. globalBits = old;
  137. }
  138. /**
  139. Reset accumulated tracked data.
  140. **/
  141. @:hlNative("std", "track_reset") public static function reset() {}
  142. /**
  143. Restart tracking after being stopped.
  144. **/
  145. @:hlNative("std", "track_init") public static function restart() {}
  146. /**
  147. Stop tracking for all threads.
  148. **/
  149. public static function stop() {
  150. globalBits = new haxe.EnumFlags();
  151. }
  152. /**
  153. Set maximum stack depth for reports (default = 10)
  154. **/
  155. @:hlNative("std", "track_set_depth") public static function setMaxDepth(v:Int) {}
  156. static function get_threadBits()
  157. return new haxe.EnumFlags(track_get_bits(true));
  158. static function set_threadBits(v:haxe.EnumFlags<TrackKind>) {
  159. track_set_bits(v.toInt(), true);
  160. return v;
  161. }
  162. static function get_globalBits()
  163. return new haxe.EnumFlags(track_get_bits(false));
  164. static function set_globalBits(v:haxe.EnumFlags<TrackKind>) {
  165. track_set_bits(v.toInt(), false);
  166. return v;
  167. }
  168. static var BUFSIZE = 512;
  169. static var buf:hl.Bytes;
  170. static function resolveSymbol(s:Symbol) {
  171. var size = BUFSIZE;
  172. if (buf == null)
  173. buf = new hl.Bytes(BUFSIZE * 2);
  174. var bytes = resolve_symbol(s, buf, size);
  175. if (bytes == null)
  176. return "<???>";
  177. return @:privateAccess String.fromUCS2(bytes.sub(0, (size + 1) * 2));
  178. }
  179. static function resolve_symbol(s:Symbol, buf:hl.Bytes, bufSize:hl.Ref<Int>):hl.Bytes {
  180. return null;
  181. }
  182. static function track_count(maxDepth:hl.Ref<Int>):Int {
  183. return 0;
  184. }
  185. static function track_entry(id:Int, type:hl.Ref<hl.Type>, count:hl.Ref<Int>, info:hl.Ref<Int>, stack:NativeArray<Symbol>):Int {
  186. return 0;
  187. }
  188. static function track_init():Void {}
  189. static function track_lock(b:Bool):Void {}
  190. static function track_get_bits(thread:Bool):Int {
  191. return 0;
  192. }
  193. static function track_set_bits(bits:Int, thread:Bool):Void {}
  194. static function __init__()
  195. track_init();
  196. // todo : move later to hl.Bytes
  197. @:hlNative("std", "field_name")
  198. public static function getFieldName(hash:Int):Bytes {
  199. return null;
  200. }
  201. @:hlNative(1.11)
  202. static function sys_profile_event( code : Int, data : hl.Bytes, dataLen : Int ) : Void {}
  203. public static function event( code : EventCode, ?data : String ) @:privateAccess {
  204. sys_profile_event(code,data == null ? null : data.bytes, data == null ? 0 : (data.length<<1));
  205. }
  206. public static function eventBytes( code : EventCode, data : haxe.io.Bytes ) @:privateAccess {
  207. sys_profile_event(code,data == null ? null : data, data == null ? 0 : data.length);
  208. }
  209. }