+ -
当前位置:首页 → 问答吧 → javascript memory leak

javascript memory leak

时间:2014-02-20

来源:互联网

汪汪几天都一直研究....都不清楚memory leak的原因

setting.js
复制内容到剪贴板代码:/********************************************************
*
* Setting
* radius - mean of size of falling object.
* radius_sd - standard deviation of probability followed by normal distribution.
*
* wind - strongness of the variation of the wind.
* wind_m - wind direction.
* wind_sd - the variation of the wind.
*
* create_p - probability of creating a new falling object.
*
*/

var fps = 30;
var display_sec = 30;
var fadein_sec = 0.5;
var fullscreen = true;
var backgroundcolor = "black";

var speed = 1 * 50;
var rotatespeed = 0.01 * 50;
var radius = 10;
var radius_sd = 1;
var wind = 0.005;
var wind_m = 0;
var wind_sd = 1;
var create_p = 0.01;

var imageUrlAutoLoadMaxNum = 10;
var imageUrlList = new Array;
include.js
复制内容到剪贴板代码:function sgn(x)
{
if(x < 0)
return -1;
else
return 1;
}
function erf(x)
{
var t1 = 1 / (1 + .3275911 * Math.abs(x));
var t2 = t1 * t1;
var t3 = t2 * t1;
var t4 = t3 * t1;
var t5 = t4 * t1;
var a1 = .254829592;
var a2 = -.284496736;
var a3 = 1.421413741;
var a4 = -1.453152027;
var a5 = 1.061405429;
return sgn(x) * (1 - Math.exp(-x * x) * (a1 * t1 + a2 * t2 + a3 * t3 + a4 * t4 + a5 * t5));
}
function gaussian_rand()
{
var u = 0;
var v = 0;
var s = 0;
do
{
u = Math.random() * 2 - 1;
v = Math.random() * 2 - 1;
s = u * u + s * s;
} while(!s || s >= 1)
return u * Math.sqrt(-2.0 * Math.log(s) / s);
}
function rotate(point, angle)
{
return {x: point.x * Math.cos(angle) - point.y * Math.sin(angle), y: point.x * Math.sin(angle) + point.y * Math.cos(angle)};
}
function xor(a, b)
{
return (a && !b) || (!a && b);
}

golden = (Math.sqrt(5) - 1) / 2;
复制内容到剪贴板代码:<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>wallpaper</title>
<style type="text/css">
html, body
{
position: absolute;
margin: 0px;
padding: 0px;
width: 100%;
height: 100%;
}
#background, #board
{
position: absolute;
width: 100%;
height: 100%;
top: 0px;
right: 0px;
}
</style>
<script language="javascript" src="setting.js"></script>
<script language="javascript" src="images/encoded.js"></script>
<script language="javascript" src="include.js"></script>
<script language="javascript">
function loadImage(imageList, url)
{
var img = new Image;
img.onload = function()
{
imageList.push(this);
};
img.src = url;
img = null;
}
function resize(board)
{
board.width = board.clientWidth;
board.height = board.clientHeight;
}
function drawImage(drawboard, img, backgroundcolor, fullscreen)
{
var ratio = img.width / img.height;
var showWidth = img.width, showHeight = img.height;
var screenWidth = drawboard.canvas.width, screenHeight = drawboard.canvas.height;
if(xor(ratio > screenWidth / screenHeight, !fullscreen))
showWidth = img.height * screenWidth / screenHeight;
else
showHeight = img.width * screenHeight / screenWidth;

if(fullscreen)
{
drawboard.drawImage(img, (img.width - showWidth) / 2, (img.height - showHeight) / 2,
showWidth, showHeight, 0, 0, screenWidth, screenHeight);
} else
{
var overlap = document.createElement("canvas").getContext("2d");
overlap.canvas.width = screenWidth;
overlap.canvas.height = screenHeight;
overlap.fillStyle = backgroundcolor;
overlap.fillRect(0, 0, screenWidth, screenHeight);
overlap.drawImage(img, (img.width - showWidth) / 2, (img.height - showHeight) / 2,
showWidth, showHeight, 0, 0, screenWidth, screenHeight);
drawboard.drawImage(overlap.canvas, 0, 0);
overlap = null;
}
}
function fillsnow(drawboard, x, y, r)
{
var grd = drawboard.createRadialGradient(x, y, r * golden, x, y, r);
grd.addColorStop(0, "rgba(255, 255, 255, 255)");
grd.addColorStop(1, "rgba(255, 255, 255, 0)");
drawboard.fillStyle = grd;
drawboard.fillRect(x - r, y - r, 2 * r, 2 * r);
}
function fillsakura(drawboard, x, y, r, r_1, r_2)
{
var points_0 = rotate({x: r, y: r * r_1}, r_2);
var points_1 = rotate({x: -r, y: -r + r * r_1 * golden}, r_2);
var points_2 = rotate({x: -r, y: r * r_1}, r_2);
var points_3 = rotate({x: -r, y: r + r * r_1 * golden}, r_2);
var grd = drawboard.createRadialGradient(x + points_0.x, y + points_0.y, 0, x + points_0.x, y + points_0.y, r);
grd.addColorStop(0, "rgba(255, 255, 255, 255)");
grd.addColorStop(1, "rgba(255, 183, 197, 255)");
drawboard.fillStyle = grd;
drawboard.strokeStyle = grd;
drawboard.beginPath();
drawboard.moveTo(x + points_0.x, y + points_0.y);
drawboard.lineTo(x + points_2.x, y + points_2.y);
drawboard.stroke();
drawboard.beginPath();
drawboard.moveTo(x + points_0.x, y + points_0.y);
drawboard.bezierCurveTo(x + points_0.x, y + points_0.y, x + points_1.x, y + points_1.y, x + points_2.x, y + points_2.y);
drawboard.closePath();
drawboard.fill();
drawboard.beginPath();
drawboard.moveTo(x + points_2.x, y + points_2.y);
drawboard.bezierCurveTo(x + points_3.x, y + points_3.y, x + points_0.x, y + points_0.y, x + points_0.x, y + points_0.y);
drawboard.closePath();
drawboard.fill();
}
</script>
</head>

<body>
<canvas id="background" name="background"></canvas>
<canvas id="board" name="board"></canvas>
<script language="javascript">
var imageList = new Array;
imageUrlList.forEach(function(url)
{
loadImage(imageList, url);
});
for(var i = 1; i <= imageUrlAutoLoadMaxNum; ++i)
{
loadImage(imageList, "images/" + i + ".jpg");
loadImage(imageList, "images/" + i + ".png");
}

var background = document.getElementById("background").getContext("2d");
var drawboard = document.getElementById("board").getContext("2d");
var fadeIn = 1;
var pastImage = null;
var fallobject = new Array;
var wind_s = 0, wind_t = 0;

var timer = setInterval(function()
{
if(imageList.length)
{
clearInterval(timer);
backgroundtimer();
timer = setInterval(function()
{
var check = {width: background.canvas.width != background.canvas.clientWidth,
height: background.canvas.height != background.canvas.clientHeight};
if(fadeIn == 0 && (check.width || check.height))
{
resize(background.canvas);
drawImage(background, pastImage, backgroundcolor, fullscreen);
}
fallobjecttimer();
}, 1000 / fps);
}
}, 1000 / fps);
function backgroundtimer()
{
resize(background.canvas);
if(fadeIn < 1 && fadein_sec && imageList.length > 1)
{
drawImage(background, pastImage, backgroundcolor, fullscreen);
background.globalAlpha = fadeIn;
drawImage(background, imageList[0], backgroundcolor, fullscreen);
background.globalAlpha = 1;

fadeIn += fps / fadein_sec / 1000;
setTimeout(backgroundtimer, 1000 / fps);
} else
{
pastImage = imageList[0];
drawImage(background, pastImage, backgroundcolor, fullscreen);
imageList = imageList.concat(imageList.shift());

fadeIn = 0;
setTimeout(backgroundtimer, 1000 * display_sec);
}
}
function fallobjecttimer()
{
resize(drawboard.canvas);
if(Math.abs(wind_s - wind_t) < Math.abs(gaussian_rand() / 12))
wind_t = wind_m + gaussian_rand() * wind_sd;
wind_s += erf(wind_t - wind_s) * wind;
if(Math.random() < create_p)
{
var _r = radius + gaussian_rand() * radius_sd;
var new_object = {x: Math.random() * board.width, y: -_r, r: _r};
if(Math.random() < 0.5)
new_object.type = "snow";
else
{
new_object.type = "sakura";
new_object.r_1 = Math.random() * 2 - 1;
new_object.r_2 = Math.random() * 2 * Math.PI;
}
fallobject.push(new_object);
new_object = null;
}
for(var i = 0; i < fallobject.length; ++i)
{
fallobject[i].x += (gaussian_rand() / 12 + wind_s) * (fallobject[i].r / radius) * speed / fps;
fallobject[i].y += Math.abs(gaussian_rand() / 12) * (fallobject[i].r / radius) * speed / fps;
if(fallobject[i].type == "snow")
fillsnow(drawboard, fallobject[i].x, fallobject[i].y, fallobject[i].r)
if(fallobject[i].type == "sakura")
{
fallobject[i].r_1 += (gaussian_rand() / 6) * rotatespeed / fps;
fallobject[i].r_2 += ((gaussian_rand() / 6) * Math.PI) * rotatespeed / fps;
fillsakura(drawboard, fallobject[i].x, fallobject[i].y, fallobject[i].r, fallobject[i].r_1, fallobject[i].r_2)
}
if(fallobject[i].y - fallobject[i].r > board.height)
fallobject.splice(i, 1);
}
}

setTimeout(function(){console.clear()}, 1000);
setInterval(function(){console.log({wind_t: wind_t, wind_s: wind_s})}, 1000);
</script>
</body>
</html>
[ 本帖最后由 Susan﹏汪汪 於 2014-1-29 12:34 AM 编辑 ]

作者: Susan﹏汪汪   发布时间: 2014-02-20

大概系setInterval本身的memory leak问题是十分严重

作者: Susan﹏汪汪   发布时间: 2014-02-20

imageList = imageList.concat(imageList.shift());.............
引用:原帖由 Susan﹏汪汪 於 2014-1-28 23:49 发表
大概系setInterval本身的memory leak问题是十分严重

作者: a8d7e8   发布时间: 2014-02-20

引用:原帖由 a8d7e8 於 2014-1-29 11:45 AM 发表
imageList = imageList.concat(imageList.shift());.............
可能系其中一处

Javascript似乎在任何object上
不论系咪reference都会直接copy一次黎用

作者: Susan﹏汪汪   发布时间: 2014-02-20

你应该学下什么是javascript 的closure和reference.

先看这一段
function loadImage(imageList, url)
{
var img = new Image;
img.onload = function()
{
imageList.push(this);
};
img.src = url;
img = null;
}

img=null; 是没用的
img只是一个reference,你把它由 new Image 产生的object指向null, 没有什么意义.

以上的loadImage function问题所在是每一个img的onload都记存了一个独立的function, 那些function onload之后就没用,但又一直保留着,应该这样写

function loadImage(imageList, url)
{
var img = new Image;
img.onload = function()
{
imageList.push(this);
this.onload=null;
};
img.src = url;
}

作者: slight   发布时间: 2014-02-20

复制内容到剪贴板代码:<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>wallpaper</title>
<style type="text/css">
html, body
{
position: absolute;
margin: 0px;
padding: 0px;
width: 100%;
height: 100%;
}
#background, #board
{
position: absolute;
width: 100%;
height: 100%;
top: 0px;
right: 0px;
}
</style>
<script language="javascript" src="setting.js"></script>
<script language="javascript" src="images/encoded.js"></script>
<script language="javascript" src="include.js"></script>
<script language="javascript">
function loadImage(imageList, url)
{
var img = new Image;
img.onload = function()
{
this.onload = null;
imageList.push(this);
};
img.src = url;
img = null;
}
function resize(board)
{
board.width = board.clientWidth;
board.height = board.clientHeight;
}
function drawImage(drawboard, img, backgroundcolor, fullscreen)
{
var ratio = img.width / img.height;
var showWidth = img.width, showHeight = img.height;
var screenWidth = drawboard.canvas.width, screenHeight = drawboard.canvas.height;
if(xor(ratio > screenWidth / screenHeight, !fullscreen))
showWidth = img.height * screenWidth / screenHeight;
else
showHeight = img.width * screenHeight / screenWidth;

if(fullscreen)
{
drawboard.drawImage(img, (img.width - showWidth) / 2, (img.height - showHeight) / 2,
showWidth, showHeight, 0, 0, screenWidth, screenHeight);
} else
{
var overlap = document.createElement("canvas").getContext("2d");
overlap.canvas.width = screenWidth;
overlap.canvas.height = screenHeight;
overlap.fillStyle = backgroundcolor;
overlap.fillRect(0, 0, screenWidth, screenHeight);
overlap.drawImage(img, (img.width - showWidth) / 2, (img.height - showHeight) / 2,
showWidth, showHeight, 0, 0, screenWidth, screenHeight);
drawboard.drawImage(overlap.canvas, 0, 0);
overlap = null;
}
}
function fillsnow(drawboard, x, y, r)
{
var grd = drawboard.createRadialGradient(x, y, r * golden, x, y, r);
grd.addColorStop(0, "rgba(255, 255, 255, 255)");
grd.addColorStop(1, "rgba(255, 255, 255, 0)");
drawboard.fillStyle = grd;
drawboard.fillRect(x - r, y - r, 2 * r, 2 * r);
}
function fillsakura(drawboard, x, y, r, r_1, r_2)
{
var points_0 = rotate({x: r, y: r * r_1}, r_2);
var points_1 = rotate({x: -r, y: -r + r * r_1 * golden}, r_2);
var points_2 = rotate({x: -r, y: r * r_1}, r_2);
var points_3 = rotate({x: -r, y: r + r * r_1 * golden}, r_2);
var grd = drawboard.createRadialGradient(x + points_0.x, y + points_0.y, 0, x + points_0.x, y + points_0.y, r);
grd.addColorStop(0, "rgba(255, 255, 255, 255)");
grd.addColorStop(1, "rgba(255, 183, 197, 255)");
drawboard.fillStyle = grd;
drawboard.strokeStyle = grd;
drawboard.beginPath();
drawboard.moveTo(x + points_0.x, y + points_0.y);
drawboard.lineTo(x + points_2.x, y + points_2.y);
drawboard.stroke();
drawboard.beginPath();
drawboard.moveTo(x + points_0.x, y + points_0.y);
drawboard.bezierCurveTo(x + points_0.x, y + points_0.y, x + points_1.x, y + points_1.y, x + points_2.x, y + points_2.y);
drawboard.closePath();
drawboard.fill();
drawboard.beginPath();
drawboard.moveTo(x + points_2.x, y + points_2.y);
drawboard.bezierCurveTo(x + points_3.x, y + points_3.y, x + points_0.x, y + points_0.y, x + points_0.x, y + points_0.y);
drawboard.closePath();
drawboard.fill();
}
</script>
</head>

<body>
<canvas id="background" name="background"></canvas>
<canvas id="board" name="board"></canvas>
<script language="javascript">
var imageList = new Array;
imageUrlList.forEach(function(url)
{
loadImage(imageList, url);
});
for(var i = 1; i <= imageUrlAutoLoadMaxNum; ++i)
{
loadImage(imageList, "images/" + i + ".jpg");
loadImage(imageList, "images/" + i + ".png");
}

var background = document.getElementById("background").getContext("2d");
var drawboard = document.getElementById("board").getContext("2d");
var fadeIn = 1;
var imageidx = 0;
var fallobject = new Array;
var wind_s = 0, wind_t = 0;

var timer = setInterval(function()
{
if(imageList.length)
{
clearInterval(timer);
backgroundtimer();
timer = setInterval(function()
{
var check = {width: background.canvas.width != background.canvas.clientWidth,
height: background.canvas.height != background.canvas.clientHeight};
if(fadeIn == 0 && (check.width || check.height))
{
resize(background.canvas);
drawImage(background, imageList[imageidx], backgroundcolor, fullscreen);
}
fallobjecttimer();
}, 1000 / fps);
}
}, 1000 / fps);
function backgroundtimer()
{
resize(background.canvas);
if(fadeIn < 1 && fadein_sec && imageList.length > 1)
{
drawImage(background, imageList[imageidx], backgroundcolor, fullscreen);
background.globalAlpha = fadeIn;
drawImage(background, imageList[(imageidx + 1) % imageList.length], backgroundcolor, fullscreen);
background.globalAlpha = 1;

fadeIn += fps / fadein_sec / 1000;
setTimeout(backgroundtimer, 1000 / fps);
} else if(imageList.length > 1)
{
imageidx = (imageidx + 1) % imageList.length;
drawImage(background, imageList[imageidx], backgroundcolor, fullscreen);

fadeIn = 0;
setTimeout(backgroundtimer, 1000 * display_sec);
}
}
function fallobjecttimer()
{
resize(drawboard.canvas);
if(Math.abs(wind_s - wind_t) < Math.abs(gaussian_rand() / 12))
wind_t = wind_m + gaussian_rand() * wind_sd;
wind_s += erf(wind_t - wind_s) * wind;
if(Math.random() < create_p)
{
var _r = radius + gaussian_rand() * radius_sd;
var new_object = {x: Math.random() * board.width, y: -_r, r: _r};
if(Math.random() < 0.5)
new_object.type = "snow";
else
{
new_object.type = "sakura";
new_object.r_1 = Math.random() * 2 - 1;
new_object.r_2 = Math.random() * 2 * Math.PI;
}
fallobject.push(new_object);
new_object = null;
}
for(var i = 0; i < fallobject.length; ++i)
{
fallobject[i].x += (gaussian_rand() / 12 + wind_s) * (fallobject[i].r / radius) * speed / fps;
fallobject[i].y += Math.abs(gaussian_rand() / 12) * (fallobject[i].r / radius) * speed / fps;
if(fallobject[i].type == "snow")
fillsnow(drawboard, fallobject[i].x, fallobject[i].y, fallobject[i].r)
if(fallobject[i].type == "sakura")
{
fallobject[i].r_1 += (gaussian_rand() / 6) * rotatespeed / fps;
fallobject[i].r_2 += ((gaussian_rand() / 6) * Math.PI) * rotatespeed / fps;
fillsakura(drawboard, fallobject[i].x, fallobject[i].y, fallobject[i].r, fallobject[i].r_1, fallobject[i].r_2)
}
if(fallobject[i].y - fallobject[i].r > board.height)
fallobject.splice(i, 1);
}
}

setTimeout(function(){console.clear()}, 1000);
setInterval(function(){console.log({wind_t: wind_t, wind_s: wind_s})}, 1000);
</script>
</body>
</html>

作者: Susan﹏汪汪   发布时间: 2014-02-20

引用:原帖由 a8d7e8 於 2014-1-29 11:45 AM 发表
imageList = imageList.concat(imageList.shift());.............
直接改左....少左好多copy
引用:原帖由 slight 於 2014-1-29 03:05 PM 发表
你应该学下什么是javascript 的closure和reference.

先看这一段
function loadImage(imageList, url)
{
var img = new Image;
img.onload = function()
{
imageLi ...
呢个没有甚么关系....img.onload造成的memory leak不太有影响

作者: Susan﹏汪汪   发布时间: 2014-02-20

我估和closure相关

作者: kingsizebeast   发布时间: 2014-02-20

引用:原帖由 kingsizebeast 於 2014-1-31 10:07 PM 发表
我估和closure相关
应该系

不过完全唔知点处理

作者: Susan﹏汪汪   发布时间: 2014-02-20

引用:原帖由 Susan﹏汪汪 於 2014-1-31 11:52 PM 发表

应该系

不过完全唔知点处理



要找出正确的原因,可试试逐步把大部份的 code cut 走/ comment out ,只剩下一些与 object creation/memory 相关的东西。
那么应该可以在所有 code 都没有前,找到可以产生最大 memory usage 变化的 code 在什么地方。
写程式时,或许可以考虑 debug / testing 可如何做,写的 code 如何配合最好。
那么 debug / testing ,甚至增加功能时就更易。
以下可能帮到你:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management?redirectlocale=en-US&redirectslug=JavaScript%2FMemory_Management

作者: xianrenb   发布时间: 2014-02-20

function的prototype.constructor会指向自已.......

作者: Susan﹏汪汪   发布时间: 2014-02-20

引用:原帖由 xianrenb 於 2014-2-1 08:05 PM 发表

要找出正确的原因,可试试逐步把大部份的 code cut 走/ comment out ,只剩下一些与 object creation/memory 相关的东西。
那么应该可以在所有 code 都没有前,找到可以产生最大 memory usage 变化的 code 在什么 ...
之前就系试过...所以发现问题好像在setInterval和function内...

作者: Susan﹏汪汪   发布时间: 2014-02-20

引用:原帖由 Susan﹏汪汪 於 2014-2-1 08:30 PM 发表
之前就系试过...所以发现问题好像在setInterval和function内...
或许可以试试在
复制内容到剪贴板代码:var timer = setInterval(function()
处只用一次 setInterval() 的效果。
如果是无问题的(即不用 clearInterval()) ,可以修改程式配合。
又或者以 setTimeout() 代替 setInterval() 。

作者: xianrenb   发布时间: 2014-02-20

引用:原帖由 Susan﹏汪汪 於 2014-1-29 04:17 PM 发表
直接改左....少左好多copy呢个没有甚么关系....img.onload造成的memory leak不太有影响
但可看出你不懂制造object和GC的运作.不太影响的原因是你没有load太多的img.
再看这个
var overlap = document.createElement("canvas").getContext("2d");
overlap.canvas.width = screenWidth;
overlap.canvas.height = screenHeight;
overlap.fillStyle = backgroundcolor;
overlap.fillRect(0, 0, screenWidth, screenHeight);
overlap.drawImage(img, (img.width - showWidth) / 2, (img.height - showHeight) / 2,
showWidth, showHeight, 0, 0, screenWidth, screenHeight);
drawboard.drawImage(overlap.canvas, 0, 0);
overlap = null;
............
overlap=null 也是没用的

var overlap = document.createElement("canvas").getContext("2d");
你每秒都create N 个新的canvas,这个消耗很大,就算它真的可被gc回收,但gc不是即时工作的 ,回收也会是很晚的时候.
况且overlap 在 drawboard.drawImage(overlap.canvas, 0, 0);时, 可能会一直被参考住,因为drawboard一直存在,每一个overlap都回收不到

解决放法是把create一个overlap,放在顶,循环再用

作者: slight   发布时间: 2014-02-20

劲啊.....
引用:原帖由 slight 於 2014-2-4 15:43 发表


但可看出你不懂制造object和GC的运作.不太影响的原因是你没有load太多的img.
再看这个
var overlap = document.createElement("canvas").getContext("2d");
overlap.canvas.w ...

作者: a8d7e8   发布时间: 2014-02-20

var timer = setInterval(function()
{
if(imageList.length)
{
clearInterval(timer);
backgroundtimer();
timer = setInterval(function()
{
var check = {width: background.canvas.width != background.canvas.clientWidth,
height: background.canvas.height != background.canvas.clientHeight};
if(fadeIn == 0 && (check.width || check.height))
{
resize(background.canvas);
drawImage(background, imageList[imageidx], backgroundcolor, fullscreen);
}
fallobjecttimer();
}, 1000 / fps);
}
}, 1000 / fps);

问题不太,但又制造了垃圾.
javascript也有作用域,第一个function 在 clearInterval(timer); 后就没用, 但不会回收,因为第一个function 的作用域被内里的function 参考住,所以第一个function又会永远保存住

作个例子:
var timer = setInterval(function F1(){
clearInterval(timer);
setInterval(function F2(){
alert(F1);
}, 5000);
}, 2000);

F1 没用,但又永远存在

改良:
var a=2;
function F2(){
alert(a);
}

var timer = setInterval(function F1(){
clearInterval(timer);
setInterval(F2, 5000);
}, 2000);

作者: slight   发布时间: 2014-02-20

引用:原帖由 slight 於 2014-2-4 03:43 PM 发表


但可看出你不懂制造object和GC的运作.不太影响的原因是你没有load太多的img.
再看这个
var overlap = document.createElement("canvas").getContext("2d");
overlap.canvas.w ...
我估是因为汪汪他写惯了 C++ ,所以特别会写如 variable1 = null 的东西去 “delete” variable 。
我觉得这没有什么问题,甚至其实是个好处。
当程式写到很长时,有时候程式员就忘了什么 variable 内里有没有 object 在内。
汪汪的写法可以让以后看 code 的人一看就知道那一行 “delete” 了一个 object 。
当然,那不是真正的 delete , GC 在 JavaScript 中无法真正的强制执行。
甚至日后他想 port code 到 C++ ,这种写法也能提醒他做适当的 memory management 。

作者: xianrenb   发布时间: 2014-02-20

引用:原帖由 xianrenb 於 2014-2-4 05:40 PM 发表

我估是因为汪汪他写惯了 C++ ,所以特别会写如 variable1 = null 的东西去 “delete” variable 。
我觉得这没有什么问题,甚至其实是个好处。
当程式写到很长时,有时候程式员就忘了什么 variable 内裏有没有 o ...
系remove reference动作

以免因为function内有variable指向img

作者: Susan﹏汪汪   发布时间: 2014-02-20

引用:原帖由 slight 於 2014-2-4 03:43 PM 发表


但可看出你不懂制造object和GC的运作.不太影响的原因是你没有load太多的img.
再看这个
var overlap = document.createElement("canvas").getContext("2d");
overlap.canvas.w ...
呢堆code系新加上去的、原先(#1)只系直接draw图上去而唔系另创一个canvas

因为要解决原先要系图片背后加黑屏、而图片是半透明的问题

仲未谂到方法改写





[ 本帖最后由 Susan﹏汪汪 於 2014-2-4 06:51 PM 使用 编辑 ]

作者: Susan﹏汪汪   发布时间: 2014-02-20

引用:原帖由 slight 於 2014-2-4 05:12 PM 发表
var timer = setInterval(function()
{
if(imageList.length)
{
clearInterval(timer);
backgroundtimer();
timer = setInterval(function( ...
一个半个垃圾不是问题
不过汪汪用chrome的除错程式
发现不论系咪外部function
setInterval都会重新copy一份新的function黎用
所以内部的setInterval会不停生产垃圾

作者: Susan﹏汪汪   发布时间: 2014-02-20

引用:原帖由 xianrenb 於 2014-2-4 05:40 PM 发表

我估是因为汪汪他写惯了 C++ ,所以特别会写如 variable1 = null 的东西去 “delete” variable 。
我觉得这没有什么问题,甚至其实是个好处。
当程式写到很长时,有时候程式员就忘了什么 variable 内裏有没有 o ...
始终人手release memory方便过GC

作者: Susan﹏汪汪   发布时间: 2014-02-20

用返 string 个 version 呢?

setInterval("f()", ..)
引用:原帖由 Susan﹏汪汪 於 2014-2-4 18:48 发表

一个半个垃圾不是问题
不过汪汪用chrome的除错程式
发现不论系咪外部function
setInterval都会重新copy一份新的function黎用
所以内部的setInterval会不停生产垃圾



http://n2.hk/d/images/r10/ip ...

作者: a8d7e8   发布时间: 2014-02-20

引用:原帖由 a8d7e8 於 2014-2-4 06:51 PM 发表
用返 string 个 version 呢?

setInterval("f()", ..)

用string更加会不断重建新function

因为用string的话
对於setInterval是不存在function object
要自动建立

但问题系
如果它不断建立新的function
Function内的所有object如array、object全部都重建

作者: Susan﹏汪汪   发布时间: 2014-02-20

复制内容到剪贴板代码:function drawImage(drawboard, img, backgroundcolor, fullscreen)
{
var ratio = img.width / img.height;
var showWidth = img.width, showHeight = img.height;
var screenWidth = drawboard.canvas.width, screenHeight = drawboard.canvas.height;
if(xor(ratio > screenWidth / screenHeight, !fullscreen))
showWidth = img.height * screenWidth / screenHeight;
else
showHeight = img.width * screenHeight / screenWidth;

if(fullscreen)
{
drawboard.drawImage(img, (img.width - showWidth) / 2, (img.height - showHeight) / 2,
showWidth, showHeight, 0, 0, screenWidth, screenHeight);
} else
{
var overlap = document.createElement("canvas").getContext("2d");
overlap.canvas.width = screenWidth;
overlap.canvas.height = screenHeight;
overlap.fillStyle = backgroundcolor;
overlap.fillRect(0, 0, screenWidth, screenHeight);
overlap.drawImage(img, (img.width - showWidth) / 2, (img.height - showHeight) / 2,
showWidth, showHeight, 0, 0, screenWidth, screenHeight);
drawboard.drawImage(overlap.canvas, 0, 0);
overlap = null;
}
}
这段code的问题可以迟下先解决...因为汪汪暂时的test code只系set fullscreen为true
所以下面的code不会运行....汪汪测试到的memory leak不是来自这个
复制内容到剪贴板代码:var overlap = document.createElement("canvas").getContext("2d");
overlap.canvas.width = screenWidth;
overlap.canvas.height = screenHeight;
overlap.fillStyle = backgroundcolor;
overlap.fillRect(0, 0, screenWidth, screenHeight);
overlap.drawImage(img, (img.width - showWidth) / 2, (img.height - showHeight) / 2,
showWidth, showHeight, 0, 0, screenWidth, screenHeight);
drawboard.drawImage(overlap.canvas, 0, 0);
overlap = null;

作者: Susan﹏汪汪   发布时间: 2014-02-20

引用:原帖由 Susan﹏汪汪 於 2014-2-4 06:48 PM 发表

一个半个垃圾不是问题
不过汪汪用chrome的除错程式
发现不论系咪外部function
setInterval都会重新copy一份新的function黎用
所以内部的setInterval会不停生产垃圾



http://n2.hk/d/images/r10/ip ...
setInterval() 不断产生新的 function (object) 是合理的,否则若直接 “link” 到某一个 function ,该 function 内里变了的效果就会与原来 call setInterval() 时的不一样。
大可考虑只用一次 setInterval() 来 call 某一 function ,而该 function 内部可再依不同情况 call 其他不同的 function 。
又或者写一种 wrapper function ,使 setInterval() 不直接 call function ,这可避免有不必要的 closure 产生。
那么就不用 clearInterval() ,而 setInterval() 所使用的 function 就从来没有变化过,也就不会再有任何可能的相关 memory leak 问题。

其实包得太多层的 code 没有什么好处,我认为写得好 code 的方法还是使用 OOP 。
每个小功能都写成个别的 method ,不应该有太多层的 code 。
那么若有 setInterval() 、 XHR 一类的 code 有 callback (出问题)时都好易处理。

作者: xianrenb   发布时间: 2014-02-20

function rotate(point, angle)
{
return {x: point.x * Math.cos(angle) - point.y * Math.sin(angle), y: point.x * Math.sin(angle) + point.y * Math.cos(angle)};
}

rotate({x: r, y: r * r_1}, r_2);
呼叫rotate时产生了一个object,
回传时又产生了一个新object
第一个object没有用,会回收,但效能不会好

可以咁改
function rotate(point, angle)
{
var x=point.x,
y=point.y,
cos=Math.cos(angle),
sin=Math.sin(angle);
point.x=x*cos-y*sin;
point.y=x*sin+y*cos;
return point;
}

作者: slight   发布时间: 2014-02-20

引用:原帖由 Susan﹏汪汪 於 2014-2-4 06:48 PM 发表

一个半个垃圾不是问题
不过汪汪用chrome的除错程式
发现不论系咪外部function
setInterval都会重新copy一份新的function黎用
所以内部的setInterval会不停生产垃圾



不会
引用就是引用,不会产生新的function

作者: slight   发布时间: 2014-02-20

引用:原帖由 xianrenb 於 2014-2-5 09:20 AM 发表

setInterval() 不断产生新的 function (object) 是合理的,否则若直接 “link” 到某一个 function ,该 function 内裏变了的效果就会与原来 call setInterval() 时的不一样。
大可考虑只用一次 setInterval() 来 ...
Javascript 的oo太难写

作者: Susan﹏汪汪   发布时间: 2014-02-20

引用:原帖由 slight 於 2014-2-5 12:30 PM 发表


不会
引用就是引用,不会产生新的function
发现原来...
Javascript的运作方法系

例如汪汪系最外写了
复制内容到剪贴板代码:var wind_s = 0, wind_t = 0;
如果要写入data到wind_t
复制内容到剪贴板代码:wind_t = 5;
javascript会先创造一个integer object...里值系5
然后取消了wind_t的参照
再重新指向新的integer object
而旧有参照就等GC

只是方便了javascript的weak type特性

所以越多写入动作...就越多垃圾

作者: Susan﹏汪汪   发布时间: 2014-02-20

JS的memory leak没救了

而家的问题系....点解JS的GC...开始时一到2.6MB就会free memory
但运行得越耐....个数会慢慢上升...
变成到5MB先会free memory

作者: Susan﹏汪汪   发布时间: 2014-02-20

引用:原帖由 Susan﹏汪汪 於 2014-2-5 03:31 PM 发表
发现原来...
Javascript的运作方法系

例如汪汪系最外写了var wind_s = 0, wind_t = 0;如果要写入data到wind_twind_t = 5;javascript会先创造一个integer object...里值系5
然后取消了wind_t的参照
再重新指向新 ...
这与 strong/weak tying 没有关系。
以我的理解,大概所有有 GC 的语言都是这样的。
一个可能的原因是 free 了一个 object 有可能可以同时 free 一连串的相关 object 。
如果次次都要做那么多检查,效能就可能出问题。
所以才有 GC 这个方法。

作者: xianrenb   发布时间: 2014-02-20

引用:原帖由 Susan﹏汪汪 於 2014-2-5 03:38 PM 发表
JS的memory leak没救了

而家的问题系....点解JS的GC...开始时一到2.6MB就会free memory
但运行得越耐....个数会慢慢上升...
变成到5MB先会free memory
或者根本是无问题。
除非 memory 多到几十 MB 以上、会 hang 机等。
既然会有 free memory 的情况,那么 GC 看来还是正常。

作者: xianrenb   发布时间: 2014-02-20

引用:原帖由 xianrenb 於 2014-2-5 06:27 PM 发表

或者根本是无问题。
除非 memory 多到几十 MB 以上、会 hang 机等。
既然会有 free memory 的情况,那么 GC 看来还是正常。
但在手机上看就会有lag情况

作者: Susan﹏汪汪   发布时间: 2014-02-20

根本就无问题,系楼主既幻觉

作者: ceap2003   发布时间: 2014-02-20

热门下载

更多