canvas_performance.html 15 KB

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