Wb-rules поджирает память. Чем можно помониторить?

Вообще использую такую обертку:

function makeNewVirtualControl(vdName, nameControl, typeControl){
  //log.info("GetDevice", getDevice("vdName"))
  if (getDevice(vdName) === undefined) {
    log.info("Define new")
    defineVirtualDevice(vdName, {
      title: vdName,
      cells: {},
    })
  }
     //Тут проверим есть ли уже контрол и если нет - создадим.
    if (!getDevice(vdName).isControlExists(nameControl)) {
      log.debug("Контрола "+nameControl+" нет, создаем.")
      getDevice(vdName).addControl(nameControl, typeControl);
    }
}

Пример вызова:

makeNewVirtualControl(namePanel, "Temperature", {type: "value", value: 0, readonly: false}); //Создаем топик в виртуальном устройстве

попробую написать еще скрипт, который будет создавать сотни таймеров, для воспроизведения.
Потому как на живом экспериментировать - не очень хорошо.

1 Like

После суточной проверки могу чуть более уверенно сказать, что память перестаёт жраться, если не использовать startTicker (в моём простейшем случае - ≈100 экземпляров раз в минуту присваивали значение “своему” dev).

За 36 часов после замены всех startTicker на setInterval утечки прекратились.

Сегодня сделаю тест с 100-200 работающих startTicker на 12-24 часа для полной уверенности. Версия с CRON, вроде, тоже память не ест, но внимательно не проверял.

UPD: А вот JSON.stringify(timers) выдаёт список таймеров, которых давно нет - т.е. после пересохранения файла скрипта эти таймеры не удаляются (в отличие от виртуальных устройств и правил)

Да, если вот так:

//200 тикеров с периодом 100..2000 мс.
//Тикеры запускаются при загрузке скрипта и работаюn.
//wb-rules автоматически останавливает старые тикеры при перезагрузке файла. (2do проверить)

log.info("tickerLoadTest: старт, запуск {} тикеров", 200);

var LOAD_VDEV_NAME = "tickerLoadTest";
var TICKER_COUNT = 200;
var MIN_PERIOD_MS = 100;
var MAX_PERIOD_MS = 2000;
var LOG_EVERY_EVENTS = 1000;

var totalFireCount = 0;

defineVirtualDevice(LOAD_VDEV_NAME, {
  title: "Ticker Load Test",
  cells: {
    tickersActive: { type: "value", value: 0, units: "count" },
    fireCount:     { type: "value", value: 0, units: "count" },
    lastTicker:    { type: "text",  value: "" },
    lastPeriodMs:  { type: "value", value: 0, units: "ms" }
  }
});

// Запускаем все 200 тикеров.
// Период равномерно распределён: index 0 → 100 мс, index 199 → 2000 мс.
for (var i = 0; i < TICKER_COUNT; i++) {
  (function (tickerName, periodMs) {
    startTicker(tickerName, periodMs);

    defineRule("loadRule_" + tickerName, {
      when: function () { return timers[tickerName].firing; },
      then: function () {
        totalFireCount += 1;
        dev[LOAD_VDEV_NAME + "/fireCount"] = totalFireCount;
        dev[LOAD_VDEV_NAME + "/lastTicker"] = tickerName;
        dev[LOAD_VDEV_NAME + "/lastPeriodMs"] = periodMs;

        if (totalFireCount % LOG_EVERY_EVENTS === 0) {
          log.info("tickerLoadTest: всего срабатываний = {}", totalFireCount);
        }
      }
    });
  })(
    "loadTicker_" + ("000" + i).slice(-3),
    MIN_PERIOD_MS + Math.round((MAX_PERIOD_MS - MIN_PERIOD_MS) * i / (TICKER_COUNT - 1))
  );
}

dev[LOAD_VDEV_NAME + "/tickersActive"] = TICKER_COUNT;
log.info("tickerLoadTest: {} тикеров запущены, период {}..{} мс", TICKER_COUNT, MIN_PERIOD_MS, MAX_PERIOD_MS);

То видно рост:

При этом я не чищу никак таймеры.
Пожалуй оформлю баг.

Делал нечто похожее. Так и не понял, где косяк с видимостью переменных, но если разбить на 2 цикла - создание правила и запуск таймера, что-то там не срабатывает. Ну и “висят” экземпляры таймеров, которых уже давно нет в коде. Манипуляции со скриптами (сохранение, вкл-выкл) сбрасывают потребление памяти, но потом оно бодро возвращается к предыдущему.

Итого: пока обходной путь - не использовать startTicker, где возможно испольщование setInterval

var dev_name = "testTick";
var cells = {};
var count = 100;

for(var i=1;i<=count;i++) {
  var s = "0000" + i;
  s = s.substring(s.length-3,s.length);
  cells["c_"+s] = { type: "value", readnonly: true, value: 0, forceDefault: true }
}

defineVirtualDevice(dev_name, { title: "Test Ticker", cells: cells });

var j=1;
var iv = setInterval(function() {
  var s = "0000" + j;
  s = s.substring(s.length-3,s.length);
  log.debug('ticker: tmr_'+s);

  defineRule("tick_"+s, {
    when: function() { return timers["tmr_"+s].firing; },
    then: function() {
      var s0 = "c_"+s;
      dev[dev_name][s0] = dev[dev_name][s0] + 1;
    }
  });
  
  startTicker("tmr_"+s, 10000);
  j++;
  if (j > count) clearInterval(iv);
}, 10);


setTimeout(function(){
  log.debug("Timers: "+JSON.stringify(timers));
}, 1000);
1 Like