Javascript приложение зависает примерно через два часа (утечка памяти?) - PullRequest
2 голосов
/ 19 июня 2020

В настоящее время я разрабатываю пользовательский интерфейс домашней автоматизации, работающий на настенном планшете android (версия 4.2.2), который после пары минут бездействия отображает страницу html "заставки" .

enter image description here

Как вы можете видеть на скриншоте выше, эта «заставка» в основном состоит из следующих функций:

  1. часы, отображающие текущее время и дату, запускаемые скриптом date_time. js и обновляемые с интервалом в одну секунду;
  2. изображение в верхнем правом углу, которое показывает текущий статус сигнала тревоги;
  3. изображение «Touchez l'écran pour quitter le mode veille», которое случайным образом перемещается каждые 3500 миллисекунд .

Оба пункта 2) и 3) выше выполняются другим сценарием, хранящимся в сценарии, называемом "screensaver_run. js". Метод getAlarmDataFromDatabase извлекает данные из моей mysql базы данных.

Теперь о формулировке проблемы: примерно через два часа весь экран зависает (как часы, так и сценарий изменения положения) таким образом, что даже планшет больше не пингуется. Я подозреваю, что происходит утечка памяти, но после пары бессонных ночей ... и большого количества кофе ... я не могу выяснить причину root моей проблемы.

Читая некоторую документацию по inte rnet, в частности https://www.lambdatest.com/blog/eradicating-memory-leaks-in-javascript, я уже внес некоторые изменения, такие как изменение объявления переменных с «var» на «let».

В Chrome, я запускаю скрипт в течение 2 1/2 минут и профилирую использование памяти (у меня есть файл heaptimeline, если он может помочь, но здесь я не совсем уверен как это проанализировать?):

enter image description here

Кроме того, я запросил у консоли:

  • производительность. memory.usedJSHeapSize и получил несколько изменяющихся значений: 3430886, 3195206, 4743246, 3402767, et c

  • performance.memory.jsHeapSizeLimit и получил: 4294705152

Есть ли у кого-нибудь подсказки, с чего начать расследование, зная, что возможности отладки этого планшета не такие продвинутые, как в современном браузере? Моему планшету "уже" 5 лет ... Обновление этого планшета не вариант.

Большое спасибо за то, что вы прочитали меня, и я очень надеюсь, что мой пост понятен, хорошо документирован и в будущем, может помочь другим провести спокойные ночи :)

Код моей html страницы (названной в честь 'screen_saver. html) следующий:

<!DOCTYPE html>
<html>
  <head>
    <title>Domoos | Screen saver screen</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
    <meta http-equiv="pragma" content="no-cache">
    <link rel="shortcut icon" href="favicon.ico">
    <link rel="stylesheet" type="text/css" href="css/mystyle_saver.css?rnd=999" />
    <script type="text/javascript" src="scripts/date_time.js"></script>
    <script type="text/javascript" src="scripts/screensaver_run.js"></script>
  </head>
  <body onload="runScreenSaver(); setup();">
    <div style="position:absolute" id="randomPlacement">
      <p><img src="assets/pictures/texte_sortie_veille.png" alt ="" style="width:90px;height:90px;" border="0"></p>
    </div>
    <div id="svg">
      <svg height="210" width="1020">
        <line x1="11" y1="100" x2="1015" y2="100" style="stroke:rgb(69,69,66);stroke-width:3" />
      </svg>
    </div>
    <div id="date"></div>
    <div id="time"></div>
    <div id="icon_alarm">
      <img id="img_alarm" src="assets/icons/alarme_eteinte.png" alt ="" style="width:27px;height:35px;">
    </div>
    <div id="tag_temperature">
      <p>21&deg;C</p>
    </div>
    <div id="tag_free_text">
      <p>151<sup>&egrave;me</sup> jour de l'ann&eacute;e 2020.<br>Bonsoir</p>
    </div>
    <div id="meteo_icon">
      <img src="assets/meteo_icons/eclaircies-big.png" alt="" style="width:40px;height:40px;">
    </div>
    <div id="tag_weather_condition">
      <p>Eclaircies</p>
    </div>
  </body>
</html>

Код моего javasript файл screensaver_run. js:

function runScreenSaver()
{
  let xmin = 0;
  let xmax = 890;
  let ymin = 0;
  let ymax = 430;
  let sDate;
  let sTime;
  let bOverlapAuthorised;
  let bDisplayPos;
  let zRandomImage;
  let xCoord;
  let yCoord;
  let xCoordStr;
  let yCoordStr;

  bOverlapAuthorised = true;
  bDisplayPos = false;

  // If overlap is forbidden, the x min and y min parameters will be redefined to be slightly below the line
  if (!bOverlapAuthorised)
  {
    xmin = 15;
    ymin = 130;
  }

  // Computes a random x and y, based on the min and ma
  xCoord = Math.floor((Math.random()*xmax)+xmin);
  yCoord = Math.floor((Math.random()*ymax)+ymin);

  xCoordStr = xCoord.toString() + "px";
  yCoordStr = yCoord.toString() + "px";

  zRandomImage = document.getElementById("randomPlacement");
  zRandomImage.style.left = xCoordStr;
  zRandomImage.style.top = yCoordStr;

  // Instead of displaying a message in the 'tag_free_text',
  // shows the randomly defined coordinates of the 'randomPlacement' object
  if (bDisplayPos)
  {
    document.getElementById("tag_free_text").innerHTML = 'X:' + xCoordStr + '<br>Y:' + yCoordStr;
  }

  document.getElementById("date").innerhtml=getTimeDate('date');

  getAlarmDataFromDatabase();

  zRandomImage = null;
  xCoord = null;
  yCoord = null;
  xCoordStr = null;
  yCoordStr = null;
  setTimeout('runScreenSaver()','3500');
}

function setup()
{
  this.addEventListener("mousemove", exitScreenSaver, false);
  this.addEventListener("mousedown", exitScreenSaver, false);
  this.addEventListener("keypress", exitScreenSaver, false);
  this.addEventListener("DOMMouseScroll", exitScreenSaver, false);
  this.addEventListener("mousewheel", exitScreenSaver, false);
  this.addEventListener("touchstart", exitScreenSaver, false);
  this.addEventListener("MSPointerMove", exitScreenSaver, false);
}

function getAlarmDataFromDatabase()
{
  let ajax = new XMLHttpRequest();
  let id_component;
  let technical_name_html;
  let comp_value;
  let data;

  ajax.open("GET", "php/data4screensaver1.php", true);
  ajax.send();
  ajax.onreadystatechange = function() 
  {
    if (this.readyState == 4 && this.status == 200) 
    {
      data = JSON.parse(this.responseText);

      for(var a = 0; a < data.length; a++) 
      {
        id_component = data[a]['id_component'];
        technical_name_html = data[a]['technical_name_html'];
        comp_value = parseInt(data[a]['value']);
      }

      data = null;

      console.log("ID Component: " + id_component);
      //console.log("Valeur de l'alarme : " + comp_value);

      switch (comp_value) 
      {
        case 0:
        case 50:
        case 100:
          displayPictureAlarm(comp_value);
          break;

        default:
          displayPictureAlarm(-1);
          break;
      }
    }
  };

  ajax = null;
  id_component = null;
  technical_name_html = null;
  comp_value = null;
}

function exitScreenSaver(e)
{
  goActive(e);
}

function goActive(event)
{
  // do something
  console.log(".. active ..");
  //event.preventDefault();

  this.removeEventListener("mousemove", exitScreenSaver);
  this.removeEventListener("mousedown", exitScreenSaver);
  this.removeEventListener("keypress", exitScreenSaver);
  this.removeEventListener("DOMMouseScroll", exitScreenSaver);
  this.removeEventListener("mousewheel", exitScreenSaver);
  this.removeEventListener("touchstart", exitScreenSaver);
  this.removeEventListener("MSPointerMove", exitScreenSaver);

  window.open("index.html","_self");
}


function displayPictureAlarm(pValue)
{
  let z;

  z = document.getElementById("img_alarm");

  if (pValue == 0) // désarmée
  {
    z.src = "assets/icons/alarme_desarmee.png";
  }

  if (pValue == 50) // partielle
  {
    z.src = "assets/icons/alarme_partielle.png";
  }

  if (pValue == 100) // totale
  {
    z.src = "assets/icons/alarme_totale.png";
  }

  if (pValue == -1) // éteinte
  {
    z.src = "assets/icons/alarme_eteinte.png";
  }

  z = null;
}

Код моего javascript файла datetime. js (как это вызывается в методе runScreenSaver выше):

function getDate(id)
{
  date = new Date;
  year = date.getFullYear();
  month = date.getMonth();
  month += 1;        
  d = date.getDate();
  day = date.getDay();
  days = new Array('Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi');

  if (d<10)
  {
    d = "0"+d;
  }
  if(month<10)
  {
    month = "0"+month;
  }

  result = ''+days[day]+' '+d+'.'+month+'.'+year;
  result = days[day]+' '+d+'.'+month+'.'+year;
  document.getElementById(id).innerHTML = result;
  setTimeout('getDate("'+id+'");','1000');

  return true;
}

function getTimeDateMainScreen()
{
  var za;
  var zb;
  var zc;
  var mydate;
  var result1;
  var result2;
  var result3;

  mydate = new Date;
  year = mydate.getFullYear();
  month = mydate.getMonth();
  day = mydate.getDate();
  weekday = mydate.getDay();
  hrs = mydate.getHours();
  mns = mydate.getMinutes();
  secs = mydate.getSeconds();

  days = new Array('Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi');

  month += 1;

  if (day < 10)
  {
    day = "0" + day;
  }

  if(month < 10)
  {
    month = "0" + month;
  }

  if(hrs < 10)
  {
    hrs = "0" + hrs;
  }
  if(mns < 10)
  {
    mns = "0" + mns;
  }
  if(secs < 10)
  {
    secs = "0" + secs;
  }

  //result = ''+days[weekday]+' '+d+'.'+month+'.'+year;
  //result = days[weekday]+' '+d+'.'+month+'.'+year;
  result1 = day + "." + month + "." + year;
  result2 = days[weekday];
  result3 = hrs + ":" + mns + ":" + secs;

  za = document.getElementById("curr_date");
  zb = document.getElementById("curr_weekday");
  zc = document.getElementById("curr_time");

  za.innerHTML = result1;
  zb.innerHTML = result2;
  zc.innerHTML = result3;

  za = null;
  zb = null;
  zc = null;
  mydate = null;
  result1 = null;
  result2 = null;
  result3 = null;

  setTimeout('getTimeDateMainScreen();','500');
}

function getTime(id)
{
  date = new Date;

  h = date.getHours();

  if(h<10)
  {
          h = "0"+h;
  }
  m = date.getMinutes();
  if(m<10)
  {
          m = "0"+m;
  }
  s = date.getSeconds();
  if(s<10)
  {
    s = "0"+s;
  }
  result = ''+h+':'+m+':'+s;
  document.getElementById(id).innerHTML = result;
  setTimeout('getTime("'+id+'");','1000');

  return true;
}

function getTime2()
{
  date = new Date;

  h = date.getHours();

  if(h<10)
  {
          h = "0"+h;
  }
  m = date.getMinutes();
  if(m<10)
  {
          m = "0"+m;
  }
  s = date.getSeconds();
  if(s<10)
  {
    s = "0"+s;
  }
  result = ''+h+':'+m+':'+s;
  document.getElementById("time").innerHTML = result;
  setTimeout('getTime2();','1000');
}

function getTimeDate(id)
{
  let date;
  let year;
  let month;
  let d;
  let day;
  let days;
  let h;
  let m;
  let s;
  let result;

  date = new Date;
  console.log("J'affiche la date3");
  year = date.getFullYear();
  month = date.getMonth();
  month += 1;
  d = date.getDate();
  day = date.getDay();
  days = new Array('Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi');
  h = date.getHours();
  m = date.getMinutes();
  s = date.getSeconds();


  if (d<10)
  {
    d = "0"+d;
  }

  if(month<10)
  {
    month = "0"+month;
  }

  if(h<10)
  {
    h = "0"+h;
  }

  if(m<10)
  {
    m = "0"+m;
  }

  if(s<10)
  {
    s = "0"+s;
  }

  result = ''+days[day]+' '+d+'.'+month+'.'+year +' ' + h+':'+m+':'+s;
  document.getElementById(id).innerHTML = result;

  date = null;
  year = null;
  month = null;
  d = null;
  day = null;
  days = null;
  h = null;
  m = null;
  s = null;
  result = null;

  setTimeout('getTimeDate("'+id+'");','1000');
  return true;   

 }

И, наконец, вот мой php (data4screensaver1. php) для извлечения данных из моей mysql базы данных:

<?php

$host = "ip_Address_db";
$db_user_encoded = "user_encoded";
$db_password_encoded = "pw_encoded";
$db_name_encoded = "db_name_encoded";

$conn = mysqli_connect($host, (encrypt_decrypt('decrypt', $db_user_encoded)), (encrypt_decrypt('decrypt', $db_password_encoded)), (encrypt_decrypt('decrypt', $db_name_encoded )));
$result = mysqli_query($conn, "CALL sp_tbl_domotique_components_get_lab61()");

$data = array();
while ($row = mysqli_fetch_object($result))
{
    array_push($data, $row);
}

echo json_encode($data);
exit();


function encrypt_decrypt($action, $string) 
{
    $output = false;
    $encrypt_method = "AES-256-CBC";
    $secret_key = '$SecretKey$';
    $secret_iv = '$SecretIV$';
    // hash
    $key = hash('sha256', $secret_key);

    // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
    $iv = substr(hash('sha256', $secret_iv), 0, 16);
    if ( $action == 'encrypt' ) {
        $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
        $output = base64_encode($output);
    } else if( $action == 'decrypt' ) {
        $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
    }
    return $output;
}

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