Performance.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. import { Tab } from '../ui/Tab.js';
  2. import { List } from '../ui/List.js';
  3. import { Graph } from '../ui/Graph.js';
  4. import { Item } from '../ui/Item.js';
  5. import { createValueSpan, setText } from '../ui/utils.js';
  6. class Performance extends Tab {
  7. constructor() {
  8. super( 'Performance' );
  9. const perfList = new List( 'Name', 'CPU', 'GPU', 'Total' );
  10. perfList.setGridStyle( 'minmax(200px, 2fr) 80px 80px 80px' );
  11. perfList.domElement.style.minWidth = '600px';
  12. const scrollWrapper = document.createElement( 'div' );
  13. scrollWrapper.className = 'list-scroll-wrapper';
  14. scrollWrapper.appendChild( perfList.domElement );
  15. this.content.appendChild( scrollWrapper );
  16. //
  17. const graphContainer = document.createElement( 'div' );
  18. graphContainer.className = 'graph-container';
  19. const graph = new Graph();
  20. graph.addLine( 'fps', '--accent-color' );
  21. //graph.addLine( 'gpu', '--color-yellow' );
  22. graphContainer.append( graph.domElement );
  23. //
  24. /*
  25. const label = document.createElement( 'label' );
  26. label.className = 'custom-checkbox';
  27. const checkbox = document.createElement( 'input' );
  28. checkbox.type = 'checkbox';
  29. const checkmark = document.createElement( 'span' );
  30. checkmark.className = 'checkmark';
  31. label.appendChild( checkbox );
  32. label.appendChild( checkmark );
  33. */
  34. const graphStats = new Item( 'Graph Stats', createValueSpan(), createValueSpan(), createValueSpan( 'graph-fps-counter' ) );
  35. perfList.add( graphStats );
  36. const graphItem = new Item( graphContainer );
  37. graphItem.itemRow.childNodes[ 0 ].style.gridColumn = '1 / -1';
  38. graphStats.add( graphItem );
  39. //
  40. const frameStats = new Item( 'Frame Stats', createValueSpan(), createValueSpan(), createValueSpan() );
  41. perfList.add( frameStats );
  42. const miscellaneous = new Item( 'Miscellaneous & Idle', createValueSpan(), createValueSpan(), createValueSpan() );
  43. miscellaneous.domElement.firstChild.style.backgroundColor = '#00ff0b1a';
  44. miscellaneous.domElement.firstChild.classList.add( 'no-hover' );
  45. frameStats.add( miscellaneous );
  46. //
  47. this.notInUse = new Map();
  48. this.frameStats = frameStats;
  49. this.graphStats = graphStats;
  50. this.graph = graph;
  51. this.miscellaneous = miscellaneous;
  52. //
  53. this.currentRender = null;
  54. this.currentItem = null;
  55. this.frameItems = new Map();
  56. }
  57. resolveStats( inspector, stats ) {
  58. const data = inspector.getStatsData( stats.cid );
  59. let item = data.item;
  60. if ( item === undefined ) {
  61. item = new Item( createValueSpan(), createValueSpan(), createValueSpan(), createValueSpan() );
  62. if ( stats.name ) {
  63. if ( stats.isComputeStats === true ) {
  64. stats.name = `${ stats.name } [ Compute ]`;
  65. }
  66. } else {
  67. stats.name = `Unnamed ${ stats.cid }`;
  68. }
  69. item.userData.name = stats.name;
  70. this.currentItem.add( item );
  71. data.item = item;
  72. } else {
  73. item.userData.name = stats.name;
  74. if ( this.notInUse.has( stats.cid ) ) {
  75. item.domElement.firstElementChild.classList.remove( 'alert' );
  76. this.notInUse.delete( stats.cid );
  77. }
  78. const statsIndex = stats.parent.children.indexOf( stats );
  79. if ( item.parent === null || item.parent.children.indexOf( item ) !== statsIndex ) {
  80. this.currentItem.add( item, statsIndex );
  81. }
  82. }
  83. setText( item.data[ 0 ], item.userData.name );
  84. setText( item.data[ 1 ], data.cpu.toFixed( 2 ) );
  85. setText( item.data[ 2 ], data.gpu.toFixed( 2 ) );
  86. setText( item.data[ 3 ], data.total.toFixed( 2 ) );
  87. //
  88. const previousItem = this.currentItem;
  89. this.currentItem = item;
  90. for ( const child of stats.children ) {
  91. this.resolveStats( inspector, child );
  92. }
  93. this.currentItem = previousItem;
  94. this.frameItems.set( stats.cid, item );
  95. }
  96. updateGraph( inspector/*, frame*/ ) {
  97. this.graph.addPoint( 'fps', inspector.softFPS );
  98. this.graph.update();
  99. }
  100. addNotInUse( cid, item ) {
  101. item.domElement.firstElementChild.classList.add( 'alert' );
  102. this.notInUse.set( cid, {
  103. item,
  104. time: performance.now()
  105. } );
  106. this.updateNotInUse( cid );
  107. }
  108. updateNotInUse( cid ) {
  109. const { item, time } = this.notInUse.get( cid );
  110. const current = performance.now();
  111. const duration = 5;
  112. const remaining = duration - Math.floor( ( current - time ) / 1000 );
  113. if ( remaining >= 0 ) {
  114. const counter = '*'.repeat( Math.max( 0, remaining ) );
  115. const element = item.domElement.querySelector( '.list-item-cell .value' );
  116. setText( element, item.userData.name + ' (not in use) ' + counter );
  117. } else {
  118. item.domElement.firstElementChild.classList.remove( 'alert' );
  119. item.parent.remove( item );
  120. this.notInUse.delete( cid );
  121. }
  122. }
  123. updateText( inspector, frame ) {
  124. const oldFrameItems = new Map( this.frameItems );
  125. this.frameItems.clear();
  126. this.currentItem = this.frameStats;
  127. for ( const child of frame.children ) {
  128. this.resolveStats( inspector, child );
  129. }
  130. // remove unused frame items
  131. for ( const [ cid, item ] of oldFrameItems ) {
  132. if ( ! this.frameItems.has( cid ) ) {
  133. this.addNotInUse( cid, item );
  134. oldFrameItems.delete( cid );
  135. }
  136. }
  137. // update not in use items
  138. for ( const cid of this.notInUse.keys() ) {
  139. this.updateNotInUse( cid );
  140. }
  141. //
  142. setText( 'graph-fps-counter', inspector.softFPS.toFixed() + ' FPS' );
  143. //
  144. setText( this.frameStats.data[ 1 ], frame.cpu.toFixed( 2 ) );
  145. setText( this.frameStats.data[ 2 ], frame.gpu.toFixed( 2 ) );
  146. setText( this.frameStats.data[ 3 ], frame.total.toFixed( 2 ) );
  147. //
  148. setText( this.miscellaneous.data[ 1 ], frame.miscellaneous.toFixed( 2 ) );
  149. setText( this.miscellaneous.data[ 2 ], '-' );
  150. setText( this.miscellaneous.data[ 3 ], frame.miscellaneous.toFixed( 2 ) );
  151. //
  152. this.currentItem = null;
  153. }
  154. }
  155. export { Performance };
粤ICP备19079148号