0

当我尝试使用网络工作者时,我遇到了内存泄漏。我有 4Gb RAM 和 i5 处理器。通常我有接近 80% 和 90% CPU 的空闲内存,但是当我运行这个脚本时,我的计算机会在两分钟内冻结,当内存结束时。我不知道如何调查这个问题。我做了一些堆快照,但没有发现问题(我没有任何内存泄漏经验)。有谁能够帮我?A 可以提供任何附加信息。主要任务是找到素数并将其保存到数据库中。我认为问题可能在于使用 db 或将数据从客户端发送到工作人员,反之亦然。对不起我的英语不好。谢谢

    $(document).ready( function() {
  $('#start_button').click( function() {
    toggleButton();
  });
});
var db = openDatabase("primeNumbers", "0.1", "Prime numbers db", 200000);

//check if db can be used
if(!db){alert("Failed to connect to database.");}

var currNumber = 2;
var work;

//create db if not exists
db.transaction(function (tx) {
  tx.executeSql("CREATE TABLE  IF NOT EXISTS primeNumbers (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, value INTEGER NOT NULL UNIQUE)", [], null, null);
});

//create worker for async calculations
var blob = new Blob([
  "                                                     \
  onmessage = function(event) {                         \
    self.postMessage(isPrime(parseInt(event.data)));    \
  };                                                    \
  function isPrime(n) {                                 \
    if(n < 2) return '{\"status\":\"false\"}';          \
    var q = parseInt(Math.sqrt(n));                     \
    for(var i = 2; i <= q; i++) {                       \
      if (n % i == 0) {                                 \
        return '{\"status\":\"false\"}';                \
      };                                                \
    };                                                  \
    return '{\"status\":\"true\",\"value\":\"'+n+'\"}'; \
  };"
]);
var blobURL = window.URL.createObjectURL(blob);
var worker = new Worker(blobURL);

//worker event listener
worker.onmessage = function(event) {
  json = $.parseJSON(event.data);
  switch(Boolean(json['status'])) {
    case true:
      writeDataToDatabase(json['value']);
      work && finder();
      break;
    case false:
      currNumber++;
      work && finder();
      break;
    default:
      alert('Something went wrong');
  };
};

function finder() {
  if(work) {
    worker.postMessage(currNumber);
    currNumber++;
  };
};

function writeDataToDatabase(value) {
  db.transaction(function(tx) {
    tx.executeSql('INSERT INTO primeNumbers (value) VALUES ('+ parseInt(value) +')');
  });
};

function getMaxPrimeFromDb() {
 var res;
 db.transaction(function(tx) {
   tx.executeSql('select max(value) as highestvalue from primenumbers', [], function(tx, result) {
     res = result.rows.item(0)['highestvalue'];
   });
   if(res != undefined) {
     currNumber = parseInt(res) + 1;
   };
 });
};

function toggleButton() {
  btn = $('#start_button');
  if(btn.text() != 'pause_calculations') {
    btn.text('pause_calculations');
    work = true;
    getMaxPrimeFromDb();
    finder();
  } else {
    btn.text('resume_calculations');
    work = false;
  };
};
4

1 回答 1

1

我没有使用太多的网络工作者或浏览器数据库存储,但似乎数据库命令的足迹是异步的——这意味着你必须等待它们完成才能做任何事情。快速浏览一下,我希望所有调用executeSql都有一个“完成”处理程序,您可以在其中调用诸如finder()and之类的东西work && finder()。您需要能够传递回调函数:

function writeDataToDatabase( value, callback ) {
    db.transaction(function(tx) {
        tx.executeSql('INSERT INTO primeNumbers (value) VALUES ('+ parseInt(value) +')', [], function() {
            if( typeof callback === "function" ) callback();
        });
    });
};

function getMaxPrimeFromDb( callback ) {
    var res;
    db.transaction(function(tx) {
        tx.executeSql('select max(value) as highestvalue from primenumbers', [], function(tx, result) {
            res = result.rows.item(0)['highestvalue'];

            if(res != undefined) {
                currNumber = parseInt(res) + 1;
            };

            if( typeof callback === "function" ) callback();
        });
    });
};

然后在你的代码中使用它,如下所示:

...
writeDataToDatabase(json['value'], function() {
    work && finder();
});
...


...
getMaxPrimeFromDb(function() {
    finder();
});
...
于 2013-08-09T16:56:02.647 回答