canvas_performance.html 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. <!--This file executes some benchmarks with HTML Canvas and VexFlow rendering-->
  2. <!doctype html><html><head><script defer="defer">(function(){//---------------->
  3. //----------------------------------------------------------------------------->
  4. // TODO
  5. // * More complex VexFlow systems
  6. // Init function
  7. window.onload = function () {
  8. window.setTimeout(start, 0);
  9. }
  10. var start = function () {
  11. document.title = "HTML Canvas Performance Tests";
  12. document.write("<h1>[OSMD] HTML Canvas Performance Tests</h1>");
  13. var t = timer();
  14. // Run the tests
  15. repeat(
  16. "Canvas creation", 100,
  17. "create an empty huge 1920 x (1080*30) canvas.",
  18. function(){
  19. var canvas = document.createElement("canvas");
  20. canvas.width = 1920;
  21. canvas.height = 1080 * 30;
  22. }
  23. );
  24. repeat(
  25. "Fill canvas with white", 10,
  26. "create a huge canvas and fill it completely with white.",
  27. function(){
  28. var canvas = document.createElement("canvas");
  29. canvas.width = 1920;
  30. canvas.height = 1080 * 30;
  31. var ctx = canvas.getContext("2d");
  32. ctx.fillRect(0, 0, canvas.width, canvas.height);
  33. }
  34. );
  35. repeat(
  36. "[VexFlow] Draw systems", 100,
  37. "Draw 20 empty staves on a normal (1920x200) canvas (one instrument).",
  38. function(){
  39. var canvas = document.createElement("canvas");
  40. canvas.width = 1920;
  41. canvas.height = 200;
  42. var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);
  43. var ctx = renderer.getContext();
  44. for (var j=0; j < 20; j++)
  45. (new Vex.Flow.Stave(
  46. Math.floor(Math.random()*canvas.width),
  47. Math.floor(Math.random()*canvas.height),
  48. Math.floor(Math.random()*canvas.width)
  49. )).addClef("treble")
  50. .setContext(ctx)
  51. .draw();
  52. }
  53. );
  54. repeat(
  55. "[VexFlow] Draw systems", 100,
  56. "Draw 20 empty staves on a big (1920x1080) canvas (one instrument).",
  57. function(){
  58. var canvas = document.createElement("canvas");
  59. canvas.width = 1920;
  60. canvas.height = 1080;
  61. var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);
  62. var ctx = renderer.getContext();
  63. for (var j=0; j < 20; j++)
  64. (new Vex.Flow.Stave(
  65. Math.floor(Math.random()*canvas.width),
  66. Math.floor(Math.random()*canvas.height),
  67. Math.floor(Math.random()*canvas.width)
  68. )).addClef("treble")
  69. .setContext(ctx)
  70. .draw();
  71. }
  72. );
  73. repeat(
  74. "[VexFlow] Draw systems", 50,
  75. "Draw 20 empty staves on a huge canvas (one instrument).",
  76. function(){
  77. var canvas = document.createElement("canvas");
  78. canvas.width = 1920;
  79. canvas.height = 1080 * 30;
  80. var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);
  81. var ctx = renderer.getContext();
  82. for (var j=0; j < 20; j++)
  83. (new Vex.Flow.Stave(
  84. Math.floor(Math.random()*canvas.width),
  85. Math.floor(Math.random()*canvas.height),
  86. Math.floor(Math.random()*canvas.width)
  87. )).addClef("treble")
  88. .setContext(ctx)
  89. .draw();
  90. }
  91. );
  92. repeat(
  93. "[VexFlow] Format & draw complex system", 50,
  94. "Draw 20 staves with one voice, ties and beams on a big canvas.",
  95. function(){
  96. var canvas = document.createElement("canvas");
  97. canvas.width = 1920;
  98. canvas.height = 1080;
  99. var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);
  100. var ctx = renderer.getContext();
  101. for (var j=0; j < 20; j++) {
  102. var stave = new Vex.Flow.Stave(10, 0, 500);
  103. // From the VexFlow Tutorial:
  104. stave.addClef("treble");
  105. stave.setContext(ctx).draw();
  106. var notes = [
  107. new Vex.Flow.StaveNote({ keys: ["e##/5"], duration: "8d" }).
  108. addAccidental(0, new Vex.Flow.Accidental("##")).addDotToAll(),
  109. new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "16" }).
  110. addAccidental(0, new Vex.Flow.Accidental("b"))
  111. ];
  112. var notes2 = [
  113. new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "8" }),
  114. new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "16" }),
  115. new Vex.Flow.StaveNote({ keys: ["c/4", "e/4"], duration: "16" }).
  116. addAccidental(0, new Vex.Flow.Accidental("b"))
  117. ];
  118. var notes3 = [
  119. new Vex.Flow.StaveNote({ keys: ["c/4", "e/4"], duration: "8" }),
  120. new Vex.Flow.StaveNote({ keys: ["e/4"], duration: "8" }).
  121. addAccidental(0, new Vex.Flow.Accidental("#"))
  122. ];
  123. var notes4 = [
  124. new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "8" }),
  125. new Vex.Flow.StaveNote({ keys: ["e/4"], duration: "8" }),
  126. ];
  127. // Create the beams
  128. var beam = new Vex.Flow.Beam(notes);
  129. var beam2 = new Vex.Flow.Beam(notes2);
  130. var beam3 = new Vex.Flow.Beam(notes3);
  131. var beam4 = new Vex.Flow.Beam(notes4);
  132. // Create a tie between the last note of the first group and the
  133. // first note of the last group.
  134. var tie = new Vex.Flow.StaveTie({
  135. first_note: notes[1],
  136. last_note: notes2[0],
  137. first_indices: [0],
  138. last_indices: [0]
  139. });
  140. // Create another tie between the two chords in the tune
  141. var tie2 = new Vex.Flow.StaveTie({
  142. first_note: notes2[2],
  143. last_note: notes3[0],
  144. first_indices: [0, 1],
  145. last_indices: [0, 1]
  146. });
  147. var all_notes = notes.concat(notes2).concat(notes3).concat(notes4);
  148. // Helper function to justify and draw a 4/4 voice
  149. Vex.Flow.Formatter.FormatAndDraw(ctx, stave, all_notes);
  150. // Render beams
  151. beam.setContext(ctx).draw();
  152. beam2.setContext(ctx).draw();
  153. beam3.setContext(ctx).draw();
  154. beam4.setContext(ctx).draw();
  155. // Render ties
  156. tie.setContext(ctx).draw();
  157. tie2.setContext(ctx).draw();
  158. }
  159. }
  160. );
  161. repeat(
  162. "[VexFlow|big] Format & draw 20 staves 5 voices each.", 50,
  163. "...",
  164. function(){
  165. var canvas = document.createElement("canvas");
  166. canvas.width = 1920;
  167. canvas.height = 1080;
  168. var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);
  169. var ctx = renderer.getContext();
  170. for (var j=0; j < 20; j++) {
  171. var stave = new Vex.Flow.Stave(
  172. Math.floor(Math.random()*canvas.width),
  173. Math.floor(Math.random()*canvas.height),
  174. Math.floor(Math.random()*canvas.width)
  175. );
  176. stave.addClef("treble");
  177. stave.setContext(ctx).draw();
  178. var voices = [];
  179. for (var i = 0, voice; i < 5; i++) {
  180. voice = new Vex.Flow.Voice({
  181. num_beats: 4,
  182. beat_value: 4,
  183. resolution: Vex.Flow.RESOLUTION
  184. });
  185. voice.addTickables(randomNotes());
  186. voices.push(voice);
  187. }
  188. var formatter = new Vex.Flow.Formatter().
  189. joinVoices(voices).format(voices, 500);
  190. for (var i = 0; i < 5; i++) {
  191. voices[i].draw(ctx, stave);
  192. }
  193. }
  194. }
  195. );
  196. repeat(
  197. "[VexFlow|huge] Format & draw 20 staves with 5 voices each.", 50,
  198. "...",
  199. function(){
  200. var canvas = document.createElement("canvas");
  201. canvas.width = 1920;
  202. canvas.height = 1080 * 30;
  203. var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);
  204. var ctx = renderer.getContext();
  205. for (var j=0; j < 20; j++) {
  206. var stave = new Vex.Flow.Stave(
  207. Math.floor(Math.random()*canvas.width),
  208. Math.floor(Math.random()*canvas.height),
  209. Math.floor(Math.random()*canvas.width)
  210. );
  211. stave.addClef("treble");
  212. stave.setContext(ctx).draw();
  213. var voices = [];
  214. for (var i = 0, voice; i < 5; i++) {
  215. voice = new Vex.Flow.Voice({
  216. num_beats: 4,
  217. beat_value: 4,
  218. resolution: Vex.Flow.RESOLUTION
  219. });
  220. voice.addTickables(randomNotes());
  221. voices.push(voice);
  222. }
  223. var formatter = new Vex.Flow.Formatter().
  224. joinVoices(voices).format(voices, 500);
  225. for (var i = 0; i < 5; i++) {
  226. voices[i].draw(ctx, stave);
  227. }
  228. }
  229. }
  230. );
  231. var tmp_canvas = document.createElement("canvas");
  232. tmp_canvas.width = 1920;
  233. tmp_canvas.height = 1080;
  234. var tmp_renderer = new Vex.Flow.Renderer(tmp_canvas, Vex.Flow.Renderer.Backends.CANVAS);
  235. var ctx = tmp_renderer.getContext();
  236. repeat(
  237. "[VexFlow|big] Format & draw system", 50,
  238. "Draw a measure with a voice.",
  239. function(){
  240. var stave = new Vex.Flow.Stave(
  241. Math.floor(Math.random()*tmp_canvas.width),
  242. Math.floor(Math.random()*tmp_canvas.height),
  243. Math.floor(Math.random()*tmp_canvas.width)
  244. );
  245. // From the VexFlow Tutorial:
  246. stave.addClef("treble");
  247. stave.setContext(ctx).draw();
  248. var notes = [
  249. new Vex.Flow.StaveNote({ keys: ["e##/5"], duration: "8d" }).
  250. addAccidental(0, new Vex.Flow.Accidental("##")).addDotToAll(),
  251. new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "16" }).
  252. addAccidental(0, new Vex.Flow.Accidental("b"))
  253. ];
  254. var notes2 = [
  255. new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "8" }),
  256. new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "16" }),
  257. new Vex.Flow.StaveNote({ keys: ["c/4", "e/4"], duration: "16" }).
  258. addAccidental(0, new Vex.Flow.Accidental("b"))
  259. ];
  260. var notes3 = [
  261. new Vex.Flow.StaveNote({ keys: ["c/4", "e/4"], duration: "8" }),
  262. new Vex.Flow.StaveNote({ keys: ["e/4"], duration: "8" }).
  263. addAccidental(0, new Vex.Flow.Accidental("#"))
  264. ];
  265. var notes4 = [
  266. new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "8" }),
  267. new Vex.Flow.StaveNote({ keys: ["e/4"], duration: "8" }),
  268. ];
  269. // Create the beams
  270. var beam = new Vex.Flow.Beam(notes);
  271. var beam2 = new Vex.Flow.Beam(notes2);
  272. var beam3 = new Vex.Flow.Beam(notes3);
  273. var beam4 = new Vex.Flow.Beam(notes4);
  274. // Create a tie between the last note of the first group and the
  275. // first note of the last group.
  276. var tie = new Vex.Flow.StaveTie({
  277. first_note: notes[1],
  278. last_note: notes2[0],
  279. first_indices: [0],
  280. last_indices: [0]
  281. });
  282. // Create another tie between the two chords in the tune
  283. var tie2 = new Vex.Flow.StaveTie({
  284. first_note: notes2[2],
  285. last_note: notes3[0],
  286. first_indices: [0, 1],
  287. last_indices: [0, 1]
  288. });
  289. var all_notes = notes.concat(notes2).concat(notes3).concat(notes4);
  290. // Helper function to justify and draw a 4/4 voice
  291. Vex.Flow.Formatter.FormatAndDraw(ctx, stave, all_notes);
  292. // Render beams
  293. beam.setContext(ctx).draw();
  294. beam2.setContext(ctx).draw();
  295. beam3.setContext(ctx).draw();
  296. beam4.setContext(ctx).draw();
  297. // Render ties
  298. tie.setContext(ctx).draw();
  299. tie2.setContext(ctx).draw();
  300. }
  301. );
  302. finish(t);
  303. }
  304. //----------------------------------------------------------------------------->
  305. // Helper functions
  306. var randomNotes = function () {
  307. var notes = [];
  308. for (var i = 0, note, key; i < 8; i ++) {
  309. key = ("abcdefg".charAt(Math.floor(Math.random()*7))) + "/" + Math.floor(Math.random()*3+2);
  310. note = new Vex.Flow.StaveNote({ keys: [key], duration: "8" });
  311. notes.push(note);
  312. }
  313. return notes;
  314. }
  315. //----------------------------------------------------------------------------->
  316. var finish = function (t) {
  317. window.setTimeout(function(){
  318. document.write("<hr><p><b>Total Elapsed Time: ~" + Math.floor(t()/1000) + " seconds.</b></p>");
  319. document.close();
  320. }, 0);
  321. }
  322. // Display the result of a test on the page
  323. function formatResult(label, descr, times, elapsed) {
  324. document.write("<p><b>" + label + "</b>: " + descr + "<br>");
  325. document.write("<i>Elapsed time: " + (elapsed/times) + "ms each (" + times + " iterations)</i></Op>");
  326. }
  327. // A simple timer
  328. var timer = function() {
  329. var start = new Date();
  330. return function() {
  331. return (new Date()).getTime() - start.getTime();
  332. }
  333. }
  334. // Repeat a test
  335. var repeat0 = function(label, times, descr, func) {
  336. var t = timer();
  337. for (var i = 0; i < times; i++) func();
  338. formatResult(label, descr, times, t());
  339. }
  340. var repeat = function(label, times, descr, func) {
  341. window.setTimeout(function(){
  342. repeat0(label, times, descr, func);
  343. }, 0);
  344. }
  345. //----------------------------------------------------------------------------->
  346. }());</script><!--------------------------------------------------------------->
  347. <script src="../node_modules/vexflow/releases/vexflow-min.js"></script><!------>
  348. </head></html><!--------------------------------------------------------------->