Я некоторое время пытался изучить холст HTML5, и я создал короткий скрипт, который позволяет передавать строки в объект, который затем отображает его на холсте.Однако его производительность очень противоречива, и у меня есть несколько идей, почему.
При использовании fillRect выигрывает ли производительность при использовании beginPath и endPath?Насколько я могу судить, они на самом деле только для строк.
Что еще более важно, похоже, что есть некоторые серьезные утечки памяти, и я предполагаю, что когда начинается сборка мусора, это когда программапыхтит.Я пытался прочитать о том, как javascript управляет распределением памяти, но, честно говоря, все это за пределами моего понимания.У меня нет каких-либо объявлений переменных внутри циклов (кроме как в начале цикла for, но я попытался изменить это и не увидел улучшения), но объект, который я имею для рисования на холсте, находится внутри функции, поэтому, возможно, он делаеткуча новых переменных для каждого вызова этого объекта?
Короче говоря, я не знаю, как заставить JavaScript работать быстрее и разумнее обрабатывать память.
Вот ссылка на само приложение.
Вот код, который берет строку и отображает ее на холсте, за которой следуют html и js, которые создают объекти передает отображаемую информацию в него:
/* screen.js */
function screen(id, pSize, w, h) {
var pixelSize;
var screenWidth;
var screenHeight;
var canvas;
var context;
var palette = new Array(16);
palette = [
"#000000", "#111111", "#222222", "#333333", "#444444", "#555555", "#666666", "#777777",
"#888888", "#999999", "#AAAAAA", "#BBBBBB", "#CCCCCC", "#DDDDDD", "#EEEEEE", "#FFFFFF"
];
this.setScreenAttributes = function(pSize, w, h) {
pixelSize = pSize;
screenWidth = w;
screenHeight = h;
canvas.setAttribute("width", screenWidth * pixelSize);
canvas.setAttribute("height", screenHeight * pixelSize);
console.log("set screen attributes to " + screenWidth * pixelSize + "x" + screenHeight * pixelSize);
};
this.buildScreen = function(id, pSize, w, h) {
canvas = document.getElementById(id);
context = canvas.getContext("2d");
this.setScreenAttributes(pSize, w, h);
console.log("built screen " + id);
};
this.setPalette = function(pal) {
if (pal.length == 16) {
for (var i = 0; i < 16; i++)
palette[i] = pal[i];
} else
console.log("error, palettes must contain 16 colors");
};
this.returnWidth = function() {
return screenWidth;
};
this.returnHeight = function() {
return screenHeight;
};
this.draw16 = function(str) {
if (str.length == screenWidth * screenHeight) {
context.clearRect(0, 0, screenWidth * pixelSize, screenHeight * pixelSize);
for (var y = 0; y < screenHeight; y++) {
for (var x = 0; x < screenWidth; x++) {
switch (str.charAt((y * screenWidth) + x)) {
case '0':
context.fillStyle = palette[0];
break;
case '1':
context.fillStyle = palette[1];
break;
case '2':
context.fillStyle = palette[2];
break;
case '3':
context.fillStyle = palette[3];
break;
case '4':
context.fillStyle = palette[4];
break;
case '5':
context.fillStyle = palette[5];
break;
case '6':
context.fillStyle = palette[6];
break;
case '7':
context.fillStyle = palette[7];
break;
case '8':
context.fillStyle = palette[8];
break;
case '9':
context.fillStyle = palette[9];
break;
case 'a':
case 'A':
context.fillStyle = palette[10];
break;
case 'b':
case 'B':
context.fillStyle = palette[11];
break;
case 'c':
case 'C':
context.fillStyle = palette[12];
break;
case 'd':
case 'D':
context.fillStyle = palette[13];
break;
case 'e':
case 'E':
context.fillStyle = palette[14];
break;
case 'f':
case 'F':
context.fillStyle = palette[15];
break;
default:
rgba(255, 0, 0, 0);
console.log("error, wrong character in string passed to draw16!");
break;
}
context.fillRect(0 + pixelSize * x, 0 + pixelSize * y, pixelSize, pixelSize);
}
}
//console.log("drew to screen");
} else {
console.log("incorrect length of string passed into draw16!");
console.log("length is " + str.length + ", but should be " + (screenWidth * screenHeight) + "!");
}
};
this.buildScreen(id, pSize, w, h); // constructor
}
/* inline-js */
// Palettes to pass to screen
var p0 = ["#000000", "#111111", "#222222", "#333333", "#444444", "#555555", "#666666", "#777777", "#888888", "#999999", "#AAAAAA", "#BBBBBB", "#CCCCCC", "#DDDDDD", "#EEEEEE", "#FFFFFF"];
var p1 = ["#111111", "#222222", "#333333", "#444444", "#555555", "#666666", "#777777", "#888888", "#999999", "#AAAAAA", "#BBBBBB", "#CCCCCC", "#DDDDDD", "#EEEEEE", "#FFFFFF", "#000000"];
var p2 = ["#222222", "#333333", "#444444", "#555555", "#666666", "#777777", "#888888", "#999999", "#AAAAAA", "#BBBBBB", "#CCCCCC", "#DDDDDD", "#EEEEEE", "#FFFFFF", "#000000", "#111111"];
var p3 = ["#333333", "#444444", "#555555", "#666666", "#777777", "#888888", "#999999", "#AAAAAA", "#BBBBBB", "#CCCCCC", "#DDDDDD", "#EEEEEE", "#FFFFFF", "#000000", "#111111", "#222222"];
var p4 = ["#444444", "#555555", "#666666", "#777777", "#888888", "#999999", "#AAAAAA", "#BBBBBB", "#CCCCCC", "#DDDDDD", "#EEEEEE", "#FFFFFF", "#000000", "#111111", "#222222", "#333333"];
var p5 = ["#555555", "#666666", "#777777", "#888888", "#999999", "#AAAAAA", "#BBBBBB", "#CCCCCC", "#DDDDDD", "#EEEEEE", "#FFFFFF", "#000000", "#111111", "#222222", "#333333", "#444444"];
var p6 = ["#666666", "#777777", "#888888", "#999999", "#AAAAAA", "#BBBBBB", "#CCCCCC", "#DDDDDD", "#EEEEEE", "#FFFFFF", "#000000", "#111111", "#222222", "#333333", "#444444", "#555555"];
var p7 = ["#777777", "#888888", "#999999", "#AAAAAA", "#BBBBBB", "#CCCCCC", "#DDDDDD", "#EEEEEE", "#FFFFFF", "#000000", "#111111", "#222222", "#333333", "#444444", "#555555", "#666666"];
var p8 = ["#888888", "#999999", "#AAAAAA", "#BBBBBB", "#CCCCCC", "#DDDDDD", "#EEEEEE", "#FFFFFF", "#000000", "#111111", "#222222", "#333333", "#444444", "#555555", "#666666", "#777777"];
var p9 = ["#999999", "#AAAAAA", "#BBBBBB", "#CCCCCC", "#DDDDDD", "#EEEEEE", "#FFFFFF", "#000000", "#111111", "#222222", "#333333", "#444444", "#555555", "#666666", "#777777", "#888888"];
var pA = ["#AAAAAA", "#BBBBBB", "#CCCCCC", "#DDDDDD", "#EEEEEE", "#FFFFFF", "#000000", "#111111", "#222222", "#333333", "#444444", "#555555", "#666666", "#777777", "#888888", "#999999"];
var pB = ["#BBBBBB", "#CCCCCC", "#DDDDDD", "#EEEEEE", "#FFFFFF", "#000000", "#111111", "#222222", "#333333", "#444444", "#555555", "#666666", "#777777", "#888888", "#999999", "#AAAAAA"];
var pC = ["#CCCCCC", "#DDDDDD", "#EEEEEE", "#FFFFFF", "#000000", "#111111", "#222222", "#333333", "#444444", "#555555", "#666666", "#777777", "#888888", "#999999", "#AAAAAA", "#BBBBBB"];
var pD = ["#DDDDDD", "#EEEEEE", "#FFFFFF", "#000000", "#111111", "#222222", "#333333", "#444444", "#555555", "#666666", "#777777", "#888888", "#999999", "#AAAAAA", "#BBBBBB", "#CCCCCC"];
var pE = ["#EEEEEE", "#FFFFFF", "#000000", "#111111", "#222222", "#333333", "#444444", "#555555", "#666666", "#777777", "#888888", "#999999", "#AAAAAA", "#BBBBBB", "#CCCCCC", "#DDDDDD"];
var pF = ["#FFFFFF", "#000000", "#111111", "#222222", "#333333", "#444444", "#555555", "#666666", "#777777", "#888888", "#999999", "#AAAAAA", "#BBBBBB", "#CCCCCC", "#DDDDDD", "#EEEEEE"];
var t;
var i = 0;
var running = true;
var command = '(x * y / 2) % 16';
var testStr = "";
var s = new screen("mycanvas", 5, 160, 100);
function drawTest() { // Creates the string
testStr = "";
for (var y = 0; y < s.returnHeight(); y++) {
for (var x = 0; x < s.returnWidth(); x++) {
switch (parseInt(eval(command))) {
case 0:
testStr = testStr.concat('0');
break;
case 1:
testStr = testStr.concat('1');
break;
case 2:
testStr = testStr.concat('2');
break;
case 3:
testStr = testStr.concat('3');
break;
case 4:
testStr = testStr.concat('4');
break;
case 5:
testStr = testStr.concat('5');
break;
case 6:
testStr = testStr.concat('6');
break;
case 7:
testStr = testStr.concat('7');
break;
case 8:
testStr = testStr.concat('8');
break;
case 9:
testStr = testStr.concat('9');
break;
case 10:
testStr = testStr.concat('A');
break;
case 11:
testStr = testStr.concat('B');
break;
case 12:
testStr = testStr.concat('C');
break;
case 13:
testStr = testStr.concat('D');
break;
case 14:
testStr = testStr.concat('E');
break;
case 15:
testStr = testStr.concat('F');
break;
default:
testStr = testStr.concat('X');
console.log("incorrect entry in testStrPass: " + temp);
break;
}
}
}
};
function runTest() { // Cycles through palettes
if (running == true) {
if (i >= 16) {
i = 0
};
switch (i) {
case 0:
s.setPalette(p0);
break;
case 1:
s.setPalette(p1);
break;
case 2:
s.setPalette(p2);
break;
case 3:
s.setPalette(p3);
break;
case 4:
s.setPalette(p4);
break;
case 5:
s.setPalette(p5);
break;
case 6:
s.setPalette(p6);
break;
case 7:
s.setPalette(p7);
break;
case 8:
s.setPalette(p8);
break;
case 9:
s.setPalette(p9);
break;
case 10:
s.setPalette(pA);
break;
case 11:
s.setPalette(pB);
break;
case 12:
s.setPalette(pC);
break;
case 13:
s.setPalette(pD);
break;
case 14:
s.setPalette(pE);
break;
case 15:
s.setPalette(pF);
break;
}
s.draw16(testStr); // Draws to screen
i++;
t = setTimeout(runTest, 16);
}
};
function stop() {
clearTimeout(t);
running = false;
};
function restart() {
if (running == false) {
running = true;
runTest();
}
};
document.getElementById("stopButton").addEventListener("click", function() {
stop()
});
document.getElementById("restartButton").addEventListener("click", function() {
restart()
});
document.getElementById("evalButton").addEventListener("click", function() {
command = document.getElementById('code').value;
s.setScreenAttributes(document.getElementById('pSize').value, document.getElementById('x').value, document.getElementById('y').value);
testStr = "";
drawTest();
restart()
});
document.addEventListener("DOMContentLoaded", function() {
drawTest();
runTest();
});
body{margin-bottom: 50vh;}
<canvas id="mycanvas" style="border: 1px solid #000000"></canvas>
<br />
<button id="stopButton">stop</button>
<button id="restartButton">restart</button>
<br /><br /> pixel size: <input type="text" id="pSize" size="2" value="5" /> x: <input type="text" id="x" size="2" value="160" /> y: <input type="text" id="y" size="2" value="100" />
<br />
<input type="text" id="code" value="(x * y / 2) % 16" /><button id="evalButton">evaluate</button>
По какой-то причине фрагмент кода stackoverflow говорит, что конструктор неверен, но он работает в Chrome, Firefox, Edge и iOS Safari, поэтому я не знаю, что он думает, что это неправильно.