Performance.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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( options = {} ) {
  8. super( 'Performance', options );
  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. let name = item.userData.name;
  84. if ( stats.isComputeStats ) {
  85. name += ' [ Compute ]';
  86. }
  87. setText( item.data[ 0 ], name );
  88. setText( item.data[ 1 ], data.cpu.toFixed( 2 ) );
  89. setText( item.data[ 2 ], stats.gpuNotAvailable === true ? '-' : data.gpu.toFixed( 2 ) );
  90. setText( item.data[ 3 ], data.total.toFixed( 2 ) );
  91. //
  92. const previousItem = this.currentItem;
  93. this.currentItem = item;
  94. for ( const child of stats.children ) {
  95. this.resolveStats( inspector, child );
  96. }
  97. this.currentItem = previousItem;
  98. this.frameItems.set( stats.cid, item );
  99. }
  100. updateGraph( inspector/*, frame*/ ) {
  101. this.graph.addPoint( 'fps', inspector.fps );
  102. this.graph.update();
  103. }
  104. addNotInUse( cid, item ) {
  105. item.domElement.firstElementChild.classList.add( 'alert' );
  106. this.notInUse.set( cid, {
  107. item,
  108. time: performance.now()
  109. } );
  110. this.updateNotInUse( cid );
  111. }
  112. updateNotInUse( cid ) {
  113. const { item, time } = this.notInUse.get( cid );
  114. const current = performance.now();
  115. const duration = 5;
  116. const remaining = duration - Math.floor( ( current - time ) / 1000 );
  117. if ( remaining >= 0 ) {
  118. const counter = '*'.repeat( Math.max( 0, remaining ) );
  119. const element = item.domElement.querySelector( '.list-item-cell .value' );
  120. setText( element, item.userData.name + ' (not in use) ' + counter );
  121. } else {
  122. item.domElement.firstElementChild.classList.remove( 'alert' );
  123. item.parent.remove( item );
  124. this.notInUse.delete( cid );
  125. }
  126. }
  127. updateText( inspector, frame ) {
  128. const oldFrameItems = new Map( this.frameItems );
  129. this.frameItems.clear();
  130. this.currentItem = this.frameStats;
  131. for ( const child of frame.children ) {
  132. this.resolveStats( inspector, child );
  133. }
  134. // remove unused frame items
  135. for ( const [ cid, item ] of oldFrameItems ) {
  136. if ( ! this.frameItems.has( cid ) ) {
  137. this.addNotInUse( cid, item );
  138. oldFrameItems.delete( cid );
  139. }
  140. }
  141. // update not in use items
  142. for ( const cid of this.notInUse.keys() ) {
  143. this.updateNotInUse( cid );
  144. }
  145. //
  146. setText( 'graph-fps-counter', inspector.fps.toFixed() + ' FPS' );
  147. //
  148. setText( this.frameStats.data[ 1 ], frame.cpu.toFixed( 2 ) );
  149. setText( this.frameStats.data[ 2 ], frame.gpu.toFixed( 2 ) );
  150. setText( this.frameStats.data[ 3 ], frame.total.toFixed( 2 ) );
  151. //
  152. setText( this.miscellaneous.data[ 1 ], frame.miscellaneous.toFixed( 2 ) );
  153. setText( this.miscellaneous.data[ 2 ], '-' );
  154. setText( this.miscellaneous.data[ 3 ], frame.miscellaneous.toFixed( 2 ) );
  155. //
  156. this.currentItem = null;
  157. }
  158. }
  159. export { Performance };
粤ICP备19079148号