Profile.hx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. package hl;
  2. typedef Symbol = hl.Abstract<"hl_symbol">;
  3. enum TrackKind {
  4. Alloc;
  5. Cast;
  6. DynField;
  7. DynCall;
  8. }
  9. class Result {
  10. public var t : hl.Type;
  11. public var kind : TrackKind;
  12. public var count : Int;
  13. public var info : Int;
  14. public var stack : Array<String>;
  15. public function new(t, count, info) {
  16. this.t = t;
  17. this.count = count;
  18. this.info = info;
  19. }
  20. @:keep public function toString() {
  21. return t + "(" + count + ")";
  22. }
  23. }
  24. @:hlNative("std")
  25. class Profile {
  26. public static var threadBits(get,set) : haxe.EnumFlags<TrackKind>;
  27. public static var globalBits(get,set) : haxe.EnumFlags<TrackKind>;
  28. static var KINDS = null;
  29. public static function getData( sortBySize = false, reset = true ) {
  30. var old = globalBits;
  31. globalBits = new haxe.EnumFlags();
  32. if( buf == null ) buf = new hl.Bytes(BUFSIZE*2);
  33. track_lock(true);
  34. var maxDepth = 0;
  35. var count = track_count(maxDepth);
  36. var arr = new hl.NativeArray<Symbol>(maxDepth);
  37. var out = [];
  38. if( KINDS == null ) KINDS = TrackKind.createAll();
  39. for( i in 0...count ) {
  40. var t : hl.Type = null, count = 0, info = 0;
  41. var k = track_entry(i, t, count, info, arr);
  42. if( count == 0 ) continue;
  43. var a = new Result(t, count, info);
  44. a.kind = KINDS[k];
  45. a.stack = [for( a in arr ) resolveSymbol(a)];
  46. out.push(a);
  47. }
  48. out.sort(function(a1,a2) {
  49. if( a1.kind != a2.kind )
  50. return a1.kind.getIndex() - a2.kind.getIndex();
  51. if( sortBySize && a1.kind == Alloc )
  52. return a2.info - a1.info;
  53. return a2.count - a1.count;
  54. });
  55. track_lock(false);
  56. if( reset ) Profile.reset();
  57. globalBits = old;
  58. return out;
  59. }
  60. public static function dump( fileName = "track.dump", sortBySize = false, reset = true ) {
  61. var old = globalBits;
  62. globalBits = new haxe.EnumFlags();
  63. var f = sys.io.File.write(fileName);
  64. var data = getData(sortBySize, reset);
  65. var allocCount = 0, allocSize = 0, castCount = 0, dynCount = 0;
  66. for( o in data ) {
  67. switch( o.kind ) {
  68. case Alloc:
  69. allocCount += o.count;
  70. allocSize += o.info;
  71. case Cast:
  72. castCount += o.count;
  73. case DynCall, DynField:
  74. dynCount += o.count;
  75. }
  76. }
  77. if( data.length == 0 )
  78. f.writeString("Nothing\n");
  79. if( allocCount > 0 )
  80. f.writeString(allocCount +" total allocs (" + allocSize+" bytes)\n");
  81. if( castCount > 0 )
  82. f.writeString(castCount+" total casts\n");
  83. if( dynCount > 0 )
  84. f.writeString(dynCount+" total dynamic accesses/calls\n");
  85. for( o in data ) {
  86. var pcount = StringTools.lpad(""+o.count," ",5);
  87. switch( o.kind ) {
  88. case Alloc:
  89. f.writeString("alloc "+pcount+" "+o.t + " (" + o.info + " bytes)\n");
  90. case Cast:
  91. f.writeString("cast "+pcount+" "+o.t + "\n");
  92. case DynCall:
  93. f.writeString("dyncall "+pcount+" "+o.t+"."+getFieldName(o.info)+"()\n");
  94. case DynField:
  95. f.writeString("dynfield "+pcount+" "+o.t+"."+getFieldName(o.info)+"\n");
  96. }
  97. for( s in o.stack )
  98. f.writeString("\t\t\t\t" + s + "\n");
  99. }
  100. f.close();
  101. globalBits = old;
  102. }
  103. /**
  104. Reset accumulated tracked data.
  105. **/
  106. @:hlNative("std","track_reset") public static function reset() {
  107. }
  108. /**
  109. Restart tracking after being stopped.
  110. **/
  111. @:hlNative("std","track_init") public static function restart() {
  112. }
  113. /**
  114. Stop tracking for all threads.
  115. **/
  116. public static function stop() {
  117. globalBits = new haxe.EnumFlags();
  118. }
  119. /**
  120. Set maximum stack depth for reports (default = 10)
  121. **/
  122. @:hlNative("std","track_set_depth") public static function setMaxDepth( v : Int ) {
  123. }
  124. static function get_threadBits() return new haxe.EnumFlags(track_get_bits(true));
  125. static function set_threadBits(v:haxe.EnumFlags<TrackKind>) { track_set_bits(v.toInt(),true); return v; }
  126. static function get_globalBits() return new haxe.EnumFlags(track_get_bits(false));
  127. static function set_globalBits(v:haxe.EnumFlags<TrackKind>) { track_set_bits(v.toInt(),false); return v; }
  128. static var BUFSIZE = 512;
  129. static var buf : hl.Bytes;
  130. static function resolveSymbol( s : Symbol ) {
  131. var size = BUFSIZE;
  132. if( buf == null ) buf = new hl.Bytes(BUFSIZE*2);
  133. var bytes = resolve_symbol(s, buf, size);
  134. if( bytes == null ) return "<???>";
  135. return @:privateAccess String.fromUCS2(bytes.sub(0,(size+1)*2));
  136. }
  137. static function resolve_symbol( s : Symbol, buf : hl.Bytes, bufSize : hl.Ref<Int> ) : hl.Bytes { return null; }
  138. static function track_count( maxDepth : hl.Ref<Int> ) : Int { return 0; }
  139. static function track_entry( id : Int, type : hl.Ref<hl.Type>, count : hl.Ref<Int>, info : hl.Ref<Int>, stack : NativeArray<Symbol> ) : Int { return 0; }
  140. static function track_init() : Void {}
  141. static function track_lock(b:Bool) : Void {}
  142. static function track_get_bits(thread:Bool) : Int { return 0; }
  143. static function track_set_bits(bits:Int,thread:Bool) : Void {}
  144. static function __init__() track_init();
  145. // todo : move later to hl.Bytes
  146. @:hlNative("std","field_name")
  147. public static function getFieldName( hash : Int ) : Bytes {
  148. return null;
  149. }
  150. }