Как я могу ускорить мой холст приложение? Как я могу улучшить использование памяти? - PullRequest
0 голосов
/ 18 сентября 2018

Я некоторое время пытался изучить холст 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, поэтому я не знаю, что он думает, что это неправильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...