Performance.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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', 'var( --color-fps )' );
  21. //graph.addLine( 'gpu', 'var( --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. this.graphFpsCounter = createValueSpan();
  35. const graphStats = new Item( 'Graph Stats', createValueSpan(), createValueSpan(), this.graphFpsCounter );
  36. perfList.add( graphStats );
  37. const graphItem = new Item( graphContainer );
  38. graphItem.itemRow.childNodes[ 0 ].style.gridColumn = '1 / -1';
  39. graphStats.add( graphItem );
  40. //
  41. const frameStats = new Item( 'Frame Stats', createValueSpan(), createValueSpan(), createValueSpan() );
  42. perfList.add( frameStats );
  43. const miscellaneous = new Item( 'Miscellaneous & Idle', createValueSpan(), createValueSpan(), createValueSpan() );
  44. miscellaneous.domElement.firstChild.style.backgroundColor = '#00ff0b1a';
  45. miscellaneous.domElement.firstChild.classList.add( 'no-hover' );
  46. frameStats.add( miscellaneous );
  47. //
  48. this.notInUse = new Map();
  49. this.frameStats = frameStats;
  50. this.graphStats = graphStats;
  51. this.graph = graph;
  52. this.miscellaneous = miscellaneous;
  53. //
  54. this.currentRender = null;
  55. this.currentItem = null;
  56. this.frameItems = new Map();
  57. }
  58. resolveStats( inspector, stats ) {
  59. const data = inspector.getStatsData( stats.cid );
  60. let item = data.item;
  61. if ( item === undefined ) {
  62. item = new Item( createValueSpan(), createValueSpan(), createValueSpan(), createValueSpan() );
  63. if ( stats.name ) {
  64. if ( stats.isComputeStats === true ) {
  65. stats.name = `${ stats.name } [ Compute ]`;
  66. }
  67. } else {
  68. stats.name = `Unnamed ${ stats.cid }`;
  69. }
  70. item.userData.name = stats.name;
  71. this.currentItem.add( item );
  72. data.item = item;
  73. } else {
  74. item.userData.name = stats.name;
  75. if ( this.notInUse.has( stats.cid ) ) {
  76. item.domElement.firstElementChild.classList.remove( 'alert' );
  77. this.notInUse.delete( stats.cid );
  78. }
  79. const statsIndex = stats.parent.children.indexOf( stats );
  80. if ( item.parent === null || item.parent.children.indexOf( item ) !== statsIndex ) {
  81. this.currentItem.add( item, statsIndex );
  82. }
  83. }
  84. let name = item.userData.name;
  85. if ( stats.isComputeStats ) {
  86. name += ' [ Compute ]';
  87. }
  88. setText( item.data[ 0 ], name );
  89. setText( item.data[ 1 ], data.cpu.toFixed( 2 ) );
  90. setText( item.data[ 2 ], stats.gpuNotAvailable === true ? '-' : data.gpu.toFixed( 2 ) );
  91. setText( item.data[ 3 ], data.total.toFixed( 2 ) );
  92. //
  93. const previousItem = this.currentItem;
  94. this.currentItem = item;
  95. for ( const child of stats.children ) {
  96. this.resolveStats( inspector, child );
  97. }
  98. this.currentItem = previousItem;
  99. this.frameItems.set( stats.cid, item );
  100. }
  101. updateGraph( inspector/*, frame*/ ) {
  102. this.graph.addPoint( 'fps', inspector.fps );
  103. this.graph.update();
  104. }
  105. addNotInUse( cid, item ) {
  106. item.domElement.firstElementChild.classList.add( 'alert' );
  107. this.notInUse.set( cid, {
  108. item,
  109. time: performance.now()
  110. } );
  111. this.updateNotInUse( cid );
  112. }
  113. updateNotInUse( cid ) {
  114. const { item, time } = this.notInUse.get( cid );
  115. const current = performance.now();
  116. const duration = 5;
  117. const remaining = duration - Math.floor( ( current - time ) / 1000 );
  118. if ( remaining >= 0 ) {
  119. const counter = '*'.repeat( Math.max( 0, remaining ) );
  120. const element = item.domElement.querySelector( '.list-item-cell .value' );
  121. setText( element, item.userData.name + ' (not in use) ' + counter );
  122. } else {
  123. item.domElement.firstElementChild.classList.remove( 'alert' );
  124. item.parent.remove( item );
  125. this.notInUse.delete( cid );
  126. }
  127. }
  128. updateText( inspector, frame ) {
  129. const oldFrameItems = new Map( this.frameItems );
  130. this.frameItems.clear();
  131. this.currentItem = this.frameStats;
  132. for ( const child of frame.children ) {
  133. this.resolveStats( inspector, child );
  134. }
  135. // remove unused frame items
  136. for ( const [ cid, item ] of oldFrameItems ) {
  137. if ( ! this.frameItems.has( cid ) ) {
  138. this.addNotInUse( cid, item );
  139. oldFrameItems.delete( cid );
  140. }
  141. }
  142. // update not in use items
  143. for ( const cid of this.notInUse.keys() ) {
  144. this.updateNotInUse( cid );
  145. }
  146. //
  147. setText( this.graphFpsCounter, inspector.fps.toFixed() + ' FPS' );
  148. //
  149. setText( this.frameStats.data[ 1 ], frame.cpu.toFixed( 2 ) );
  150. setText( this.frameStats.data[ 2 ], inspector.getRenderer().backend.hasTimestamp ? frame.gpu.toFixed( 2 ) : '-' );
  151. setText( this.frameStats.data[ 3 ], frame.total.toFixed( 2 ) );
  152. //
  153. setText( this.miscellaneous.data[ 1 ], frame.miscellaneous.toFixed( 2 ) );
  154. setText( this.miscellaneous.data[ 2 ], '-' );
  155. setText( this.miscellaneous.data[ 3 ], frame.miscellaneous.toFixed( 2 ) );
  156. //
  157. this.currentItem = null;
  158. }
  159. }
  160. export { Performance };
粤ICP备19079148号