dollar
@dollar
Делай добро и бросай его в воду.

В чём заключается утечка памяти в коде?

Профайлер
5cbf006d6cdea282694185.png
Код функции, где проблема
const MAX_DB_TIMEOUT = 60000;
let saveDB_timer;
let db_saved_called;
function saveDB(no_pause) {
	let now = (new Date()).getTime();
	db_saved_called = db_saved_called || now;
	if (saveDB_timer !== undefined) clearTimeout(saveDB_timer);
	function saveDB_Now() {
		//let check1 = performance.now();
		for(let i=0;i<db_clean_steps.length;i++) {
			clean_db(db_clean_steps[i]);
			try {
				localStorage.db = JSON.stringify(db);
				break;
			} catch(e) {
				console.log("Can't save DB");
			}
		}
		db_saved_called = undefined;
		//let check2 = performance.now();
		//console.log('DB_SAVED!', (check2-check1)+'мс');
	}
	if ((now - db_saved_called > MAX_DB_TIMEOUT) || no_pause) saveDB_Now();
	else saveDB_timer = setTimeout(saveDB_Now,15000);
}
Скачок наблюдается по окончании работы функции saveDB_Now(). По идее мы просто заменяем переменную localStorage.db, которая даже не объект, а строка. Но внезапно оказывается, что память где-то остаётся. Как же так?

Если поможет, вот ещё код функции clean_db(), но она видимо ни при чем
const db_clean_steps = [7, 3, 2, 1, 0.5, 0.2];
function clean_db(timeout_days) {
	const timeout = timeout_days *24*60*60*1000;
	//remove pending status
	for(let id in db.user) {
		if (!db.user[id]) {
			delete db.user[id];
			continue;
		}
		delete db.user[id].solutions_pending;
		delete db.user[id].karma_pending;
	}
	//remove users
	let now = (new Date()).getTime();
	for(let id in db.user) {
		let user = db.user[id];
		if (!(now - user.update_time < timeout)) delete db.user[id]; // n days
	}
	//remove questions
	for(let id in db.question) {
		let q = db.question[id];
		//ignore subscribtions
		if (q.sub) {
			if (!(now - q.ut < 400 * 24 * 60 * 60000)) delete db.question[id]; // 1 year
			continue;
		}
		//ut means update_time
		if (!(now - q.ut < timeout)) delete db.question[id]; // n days
	}
}


Вот здесь вот самое интересное: чётко видно, что пока выполняется JSON.stringify() примерно 20мс, происходит какая-то дикая магия с выделением памяти. Что за явление такое?
Магия
5cbf17a68a079174520025.png
  • Вопрос задан
  • 298 просмотров
Решения вопроса 1
dollar
@dollar Автор вопроса
Делай добро и бросай его в воду.
Проблема оказалась гораздо глубже. А именно - в движке V8.
То есть она касается только Chrome и Node js.
Копать пришлось долго. И проблема ещё не решена, предстоит изучить этот баг и обойти его во всех местах программы (а их очень много).

В вопросе мало данных, за это прошу прощения.

И профилировщиком сложно пользоваться, так как GC чистит память с большими задержками. Графикам нельзя верить.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы