2013-08-09 2 views
0

У меня возникла утечка памяти, когда я пытаюсь использовать веб-работников. У меня 4Gb RAM и i5 процессор. Обычно у меня есть свободный баран около 80% и 90% процессора, но когда я запускаю этот скрипт, мой компьютер зависает через две минуты, когда память заканчивается. Я не знаю, как исследовать проблему. Я сделал несколько снимков кучи, но не нашел проблемы (у меня нет опыта в утечке памяти). Кто-нибудь может мне помочь? A может предоставить любую дополнительную информацию. Основная задача - найти простые числа и сохранить их в базе данных. Я думаю, что проблема может заключаться в работе с db или передаче данных от клиента к работнику и наоборот. Извините за мой английский. ТНХУтечка памяти в js web-работниках

$(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; 
    }; 
}; 

ответ

1

Я не работал много веб-рабочих или хранения базы данных браузера, но он появляется след для команд базы данных асинхронно - означает, что вы должны ждать их, чтобы закончить, прежде чем делать что-нибудь. Вкратце я ожидаю, что все вызовы executeSql будут иметь обработчик «done», в котором вы называете такие вещи, как finder() и 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(); 
}); 
... 
+0

Я думал об этом д.в. попробовал ваш пример, но я могу получить только 2 простых с ним, после этого ничего не добавляет. Когда я попытался отладить скрипт, я получил только неправильный порядок выполнения. Если у вас есть время, вы можете сделать то же самое в своем браузере (Chromium). thx – r90t

+0

Я переработал некоторый код, поэтому теперь ваш пример работает. спасибо – r90t

+0

Рад, что это сработало. Асинхронное кодирование занимает некоторое время, чтобы привыкнуть, но как только вы его получите ... это приятно –