Reputation: 386
I`ve got memory leak when i try to use web workers. I have 4Gb RAM and i5 processor. Usually i have free ram near 80% and 90% CPU, but when i running this script my computer freezes in two minutes, when memory ends. I do not know how to investigate the problem. I made some heap snapshots but did not find the problem(i have not any experience in mem leaks). Can anybody help me? A can provide any additional info. The main task is to find primes and save it to database. I think that the problem can be in working with db or sending data from client to worker and vice versa. Sorry for my english. thx
$(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;
};
};
Upvotes: 0
Views: 738
Reputation: 28420
I haven't worked much web workers or browser database storage, but it appears the footprint for the database commands are asynchronous - meaning you must wait for them to finish before doing anything. At a quick glance, I would expect all calls to executeSql
to have a "done" handler in which you call things like finder()
and work && finder()
. You would need to be able to pass a callback function around:
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();
});
});
};
And then use it in your code like this:
...
writeDataToDatabase(json['value'], function() {
work && finder();
});
...
...
getMaxPrimeFromDb(function() {
finder();
});
...
Upvotes: 1