profiling.html 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <html>
  2. <head>
  3. <title>Customize BJS for a specific Scene</title>
  4. <meta charset="UTF-8">
  5. <script src="../../dist/preview release/babylon.js"></script>
  6. </head>
  7. <body onload="readConfigFile()">
  8. Obtain a FireFox performance file by:
  9. <ol>
  10. <li>Make sure scene uses Babylon MAX.</li>
  11. <li>Load the scene.</li>
  12. <li>Turn on performance profiling.</li>
  13. <li>Reload the scene (very important if code like sceneLoader runs on page load).</li>
  14. <li>Do anything that might call code in babylon.js not yet encountered.</li>
  15. <li>Stop recording, and save the data as a file.</li>
  16. </ol>
  17. On this page:
  18. <ol>
  19. <li>Select File with 'Browse' button below, and pick the file saved from above.</li>
  20. <li>Make any changes of name to babylon file names.</li>
  21. <li>Click Generate.</li>
  22. <li>Copy the 'custom.cofig.json' file generated in Downloads directory to the Gulp directory.</li>
  23. <li>run: 'Gulp build-custom'</li>
  24. <li>Copy generated scripts from dist/preview lease to where needed, and test. Tip: test with the max version</li>
  25. <li>If need stuff did not get recorded in performance file, then select file(s) &amp; click Generate again.</li>
  26. </ol>
  27. <form>
  28. <input type="radio" name="browser" id="firefox" checked="checked"><label for="firefox"> Firefox</label>
  29. <input type="radio" name="browser" id="chrome" disabled data-toggle="tooltip" title="Not yet implemented, Go for it!"><label for="chrome"> Chrome</label>
  30. <input type="radio" name="browser" id="edge" disabled data-toggle="tooltip" title="Not yet implemented, Go for it!"><label for="edge"> Edge</label><br>
  31. <label>Profiling file: <input type="file" id="upload_file" name="upload" accept="text/*" multiple="" onchange="assignProfile(this.files[0])"/></label><br><br>
  32. Filename: <input type="text" id="filename" maxlength="32" value="babylon.custom.max.js">
  33. minFilename: <input type="text" id="minFilename" maxlength="32" value="babylon.custom.js"><br>
  34. Files Not In Recording: (Select those to still keep)
  35. <input type="button" value="Generate" onclick="generate()"><br>
  36. <select id="discards" multiple size="30">
  37. </select>
  38. </form>
  39. <script>
  40. // each "File" is a: [keep: boolean, fullPath: string, search]
  41. // search is initially the file name without the .js.
  42. var files;
  43. var reg = new RegExp('babylon\\.\\w+');
  44. var FIRE_FOX = 0;
  45. var CHROME = 1;
  46. var EDGE = 3;
  47. function readConfigFile() {
  48. // read the regular config file, not custom, in-case custom has already been reduced
  49. // the regular config file has files in 2 separate sections
  50. BABYLON.Tools.LoadFile("./config.json",
  51. function(data){
  52. var startInd = data.indexOf('"files": [') + 11; // 11 for "files": [
  53. var endInd = data.indexOf(']', startInd);
  54. var fileNames = data.substring(startInd, endInd);
  55. fileNames += ","; // for spliting once glued to part 2
  56. var extras = data.indexOf('"extras"');
  57. startInd = data.indexOf('"files": [', extras) + 11; // 11 for "files": [
  58. endInd = data.indexOf(']', startInd);
  59. fileNames += data.substring(startInd, endInd);
  60. fileNames = fileNames.replace(/(\r\n|\n|\r)/gm,""); // strip all line breaks
  61. fileNames = fileNames.replace(/\s+/g, ""); // strip all whitespace
  62. fileNames = fileNames.split(',');
  63. var len = fileNames.length;
  64. files = new Array(len);
  65. for (var i = 0; i < len; i++) {
  66. var name = fileNames[i].match(reg)[0].substring(8); // remove the babylon.
  67. files[i] = [false, fileNames[i], name];
  68. }
  69. appendSecondarySearches("math.js", "mathtools|color3|color4|vector2|vector3|vector4|size|quaternion|matrix|plane|viewport|frustum|bezierCurve"); // got tired
  70. // force stuff to always be added
  71. appendSecondarySearches("decorators.js", "engine"); //needed for Serialize
  72. appendSecondarySearches("stringDictionary.js", "engine"); //needed in Engine Constructor
  73. appendSecondarySearches("loadingScreen.js", "engine"); //needed in Engine Constructor
  74. appendSecondarySearches("postProcessRenderPipelineManager.js", "scene"); //needed in Scene Constructor
  75. appendSecondarySearches("boundingBoxRenderer.js", "scene"); //needed in Scene Constructor
  76. appendSecondarySearches("collisionCoordinator.js", "scene"); //needed in Scene Constructor, from a called set of this.workerCollisions = false;
  77. appendSecondarySearches("collider.js", "abstractMesh"); // needed in abstractMesh constructor
  78. appendSecondarySearches("linesMesh.js", "geometry"); // needed in geometry constructor
  79. appendSecondarySearches("multiMaterial.js", "subMesh"); // needed in subMesh.getMaterial()
  80. appendSecondarySearches("pointLight.js", "subMesh"); // needed in MaterialHelper.PrepareDefinesForLights
  81. appendSecondarySearches("spotLight.js", "subMesh"); // needed in MaterialHelper.PrepareDefinesForLights
  82. appendSecondarySearches("hemisphericLight.js", "subMesh"); // needed in MaterialHelper.PrepareDefinesForLights
  83. appendSecondarySearches("directionalLight.js", "subMesh"); // needed in MaterialHelper.PrepareDefinesForLights
  84. appendSecondarySearches("videoTexture.js", "engine"); //needed in Engine._setTexture()
  85. // there should always some detection of FreeCamera or ArcRotateCamera, but maybe not all inputs got recorded
  86. appendSecondarySearches("cameraInputsManager.js", "freeCamera\\w+|arcRotateCamera\\w+");
  87. appendSecondarySearches("freeCamera.js", "freeCamera\\w+");
  88. appendSecondarySearches("freeCameraInputsManager.js", "freeCamera\\w+");
  89. appendSecondarySearches("freeCameraMouseInput.js" , "freeCamera\\w+");
  90. appendSecondarySearches("freeCameraKeyboardMoveInput.js" , "freeCamera\\w+");
  91. appendSecondarySearches("freeCameraTouchInput.js" , "freeCamera\\w+");
  92. appendSecondarySearches("freeCameraDeviceOrientationInput.js", "freeCamera\\w+");
  93. appendSecondarySearches("freeCameraGamepadInput.js" , "freeCamera\\w+");
  94. appendSecondarySearches("freeCameraVirtualJoystickInput.js" , "freeCamera\\w+");
  95. appendSecondarySearches("arcRotateCamera.js", "arcRotateCamera\\w+");
  96. appendSecondarySearches("arcRotateCameraInputsManager.js", "arcRotateCamera\\w+");
  97. appendSecondarySearches("arcRotateCameraKeyboardMoveInput.js" , "arcRotateCamera\\w+");
  98. appendSecondarySearches("arcRotateCameraMouseWheelInput.js" , "arcRotateCamera\\w+");
  99. appendSecondarySearches("arcRotateCameraPointersInput.js" , "arcRotateCamera\\w+");
  100. appendSecondarySearches("arcRotateCameraGamepadInput.js" , "arcRotateCamera\\w+");
  101. appendSecondarySearches("arcRotateCameraVRDeviceOrientationInput.js", "arcRotateCamera\\w+");
  102. // these are internal classes where class name has a leading '_'
  103. appendSecondarySearches("alphaCullingState.js" , "engine");
  104. appendSecondarySearches("depthCullingState.js" , "_depthCullingState");
  105. appendSecondarySearches("stencilState.js" , "_stencilState");
  106. // dependencies with few / no methods, so no performance to record.
  107. appendSecondarySearches("pushMaterial.js", "standardMaterial");
  108. }, null, true
  109. );
  110. }
  111. // add addition conditions to match a file to.
  112. // additionals is a string with all separated with a '|'
  113. function appendSecondarySearches(baseFilename, additionals) {
  114. for (var i = 0, len = files.length; i < len; i++) {
  115. if (files[i][1].indexOf(baseFilename) !== -1) {
  116. files[i][2] += "|" + additionals;
  117. return;
  118. }
  119. }
  120. throw "'" + baseFilename + "' not found as a base file name";
  121. }
  122. function assignProfile(file) {
  123. BABYLON.Tools.ReadFile(file, analyse, null, false);
  124. }
  125. function analyse(data){
  126. // make sure max was used
  127. if (!data.match('\\.max\\.js')) {
  128. alert('babylon.max not detected. File rejected');
  129. return;
  130. }
  131. var browser;
  132. if (document.getElementById("firefox").checked) browser = FIRE_FOX;
  133. if (document.getElementById("chrome" ).checked) browser = CHROME;
  134. if (document.getElementById("edge" ).checked) browser = EDGE;
  135. var discards = document.getElementById("discards");
  136. discards.options.length = 0;
  137. for (var i = 0, len = files.length; i < len; i++) {
  138. files[i][0] = false; // clean out boolean for additional runs
  139. switch(browser) {
  140. case FIRE_FOX:
  141. var exp = new RegExp('"(' + files[i][2] + ')(\\.prototype|\\.\\w)', 'i');
  142. if (data.match(exp) ) {
  143. files[i][0] = true;
  144. }
  145. break;
  146. case CHROME:
  147. case EDGE:
  148. window.alert("Code from your PR goes here!");
  149. return;
  150. }
  151. // add onto the discard select when not found
  152. if (!files[i][0]){
  153. var option = document.createElement("option");
  154. option.text = files[i][1];
  155. discards.add(option);
  156. }
  157. }
  158. }
  159. function generate() {
  160. // get all the ones from select
  161. var discards = document.getElementById("discards");
  162. var opt;
  163. var asText = "";
  164. for (var i = 0, len = discards.options.length; i < len; i++) {
  165. opt = discards.options[i];
  166. if (opt.selected) {
  167. asText += opt.text;
  168. }
  169. }
  170. var filename = document.getElementById("filename" ).value;
  171. var minFilename = document.getElementById("minFilename").value;
  172. var out = '';
  173. out += '{\n';
  174. out += ' "build": {\n';
  175. out += ' "filename": "' + filename + '",\n';
  176. out += ' "minFilename": "' + minFilename + '",\n';
  177. out += ' "outputDirectory": "../../dist/preview release",\n';
  178. out += ' "srcOutputDirectory": "../../src/"\n';
  179. out += ' },\n';
  180. out += ' "core": {\n';
  181. out += ' "typescript": [\n';
  182. out += ' "../../src/**/*.ts",\n';
  183. out += ' "!../../src/**/*.d.ts"\n';
  184. out += ' ],\n';
  185. out += ' "files": [\n';
  186. var isFirst = true;
  187. for (var i = 0, len = files.length; i < len; i++) {
  188. if (files[i][0] || asText.indexOf(files[i][1]) !== -1) {
  189. if (!isFirst) {
  190. out += ',';
  191. }
  192. isFirst = false;
  193. out += '\n ' + files[i][1];
  194. }
  195. }
  196. out += '\n ]\n';
  197. out += ' }\n';
  198. out += '}\n';
  199. var blob = new Blob ( [ out ], { type : 'text/plain;charset=utf-8' } );
  200. // turn blob into an object URL;
  201. var objectUrl = (window.webkitURL || window.URL).createObjectURL(blob);
  202. var link = window.document.createElement("a");
  203. link.href = objectUrl;
  204. link.download = "custom.config.json";
  205. var click = document.createEvent("MouseEvents");
  206. click.initEvent("click", true, false);
  207. link.dispatchEvent(click);
  208. }
  209. </script>
  210. </body>
  211. </html>