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