javascript memory leak
时间:2014-02-20
来源:互联网

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;
{
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;
<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-02-20
作者: Susan﹏汪汪 发布时间: 2014-02-20
大概系setInterval本身的memory leak问题是十分严重
作者: a8d7e8 发布时间: 2014-02-20
imageList = imageList.concat(imageList.shift());.............
Javascript似乎在任何object上
不论系咪reference都会直接copy一次黎用
作者: Susan﹏汪汪 发布时间: 2014-02-20
先看这一段
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
<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
imageList = imageList.concat(imageList.shift());.............
你应该学下什么是javascript 的closure和reference.
先看这一段
function loadImage(imageList, url)
{
var img = new Image;
img.onload = function()
{
imageLi ...
作者: Susan﹏汪汪 发布时间: 2014-02-20
作者: kingsizebeast 发布时间: 2014-02-20
我估和closure相关
不过完全唔知点处理
作者: Susan﹏汪汪 发布时间: 2014-02-20
应该系
不过完全唔知点处理
那么应该可以在所有 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

作者: Susan﹏汪汪 发布时间: 2014-02-20
要找出正确的原因,可试试逐步把大部份的 code cut 走/ comment out ,只剩下一些与 object creation/memory 相关的东西。
那么应该可以在所有 code 都没有前,找到可以产生最大 memory usage 变化的 code 在什么 ...
作者: Susan﹏汪汪 发布时间: 2014-02-20
之前就系试过...所以发现问题好像在setInterval和function内...
如果是无问题的(即不用 clearInterval()) ,可以修改程式配合。
又或者以 setTimeout() 代替 setInterval() 。
作者: xianrenb 发布时间: 2014-02-20
直接改左....少左好多copy呢个没有甚么关系....img.onload造成的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;
............
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
但可看出你不懂制造object和GC的运作.不太影响的原因是你没有load太多的img.
再看这个
var overlap = document.createElement("canvas").getContext("2d");
overlap.canvas.w ...
作者: a8d7e8 发布时间: 2014-02-20
{
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
但可看出你不懂制造object和GC的运作.不太影响的原因是你没有load太多的img.
再看这个
var overlap = document.createElement("canvas").getContext("2d");
overlap.canvas.w ...
我觉得这没有什么问题,甚至其实是个好处。
当程式写到很长时,有时候程式员就忘了什么 variable 内里有没有 object 在内。
汪汪的写法可以让以后看 code 的人一看就知道那一行 “delete” 了一个 object 。
当然,那不是真正的 delete , GC 在 JavaScript 中无法真正的强制执行。
甚至日后他想 port code 到 C++ ,这种写法也能提醒他做适当的 memory management 。
作者: xianrenb 发布时间: 2014-02-20
我估是因为汪汪他写惯了 C++ ,所以特别会写如 variable1 = null 的东西去 “delete” variable 。
我觉得这没有什么问题,甚至其实是个好处。
当程式写到很长时,有时候程式员就忘了什么 variable 内裏有没有 o ...
以免因为function内有variable指向img
作者: Susan﹏汪汪 发布时间: 2014-02-20
但可看出你不懂制造object和GC的运作.不太影响的原因是你没有load太多的img.
再看这个
var overlap = document.createElement("canvas").getContext("2d");
overlap.canvas.w ...
因为要解决原先要系图片背后加黑屏、而图片是半透明的问题
仲未谂到方法改写
[ 本帖最后由 Susan﹏汪汪 於 2014-2-4 06:51 PM 使用 编辑 ]
作者: Susan﹏汪汪 发布时间: 2014-02-20
var timer = setInterval(function()
{
if(imageList.length)
{
clearInterval(timer);
backgroundtimer();
timer = setInterval(function( ...
不过汪汪用chrome的除错程式
发现不论系咪外部function
setInterval都会重新copy一份新的function黎用
所以内部的setInterval会不停生产垃圾
作者: Susan﹏汪汪 发布时间: 2014-02-20
我估是因为汪汪他写惯了 C++ ,所以特别会写如 variable1 = null 的东西去 “delete” variable 。
我觉得这没有什么问题,甚至其实是个好处。
当程式写到很长时,有时候程式员就忘了什么 variable 内裏有没有 o ...
作者: Susan﹏汪汪 发布时间: 2014-02-20
setInterval("f()", ..)
一个半个垃圾不是问题
不过汪汪用chrome的除错程式
发现不论系咪外部function
setInterval都会重新copy一份新的function黎用
所以内部的setInterval会不停生产垃圾
http://n2.hk/d/images/r10/ip ...
作者: a8d7e8 发布时间: 2014-02-20
用返 string 个 version 呢?
setInterval("f()", ..)
因为用string的话
对於setInterval是不存在function object
要自动建立
但问题系
如果它不断建立新的function
Function内的所有object如array、object全部都重建
作者: Susan﹏汪汪 发布时间: 2014-02-20
{
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不会运行....汪汪测试到的memory leak不是来自这个
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
一个半个垃圾不是问题
不过汪汪用chrome的除错程式
发现不论系咪外部function
setInterval都会重新copy一份新的function黎用
所以内部的setInterval会不停生产垃圾
http://n2.hk/d/images/r10/ip ...
大可考虑只用一次 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
{
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
一个半个垃圾不是问题
不过汪汪用chrome的除错程式
发现不论系咪外部function
setInterval都会重新copy一份新的function黎用
所以内部的setInterval会不停生产垃圾
引用就是引用,不会产生新的function
作者: slight 发布时间: 2014-02-20
setInterval() 不断产生新的 function (object) 是合理的,否则若直接 “link” 到某一个 function ,该 function 内裏变了的效果就会与原来 call setInterval() 时的不一样。
大可考虑只用一次 setInterval() 来 ...
作者: Susan﹏汪汪 发布时间: 2014-02-20
不会
引用就是引用,不会产生新的function
Javascript的运作方法系
例如汪汪系最外写了
然后取消了wind_t的参照
再重新指向新的integer object
而旧有参照就等GC
只是方便了javascript的weak type特性
所以越多写入动作...就越多垃圾
作者: Susan﹏汪汪 发布时间: 2014-02-20

而家的问题系....点解JS的GC...开始时一到2.6MB就会free memory
但运行得越耐....个数会慢慢上升...
变成到5MB先会free memory
作者: Susan﹏汪汪 发布时间: 2014-02-20
发现原来...
Javascript的运作方法系
例如汪汪系最外写了var wind_s = 0, wind_t = 0;如果要写入data到wind_twind_t = 5;javascript会先创造一个integer object...里值系5
然后取消了wind_t的参照
再重新指向新 ...
以我的理解,大概所有有 GC 的语言都是这样的。
一个可能的原因是 free 了一个 object 有可能可以同时 free 一连串的相关 object 。
如果次次都要做那么多检查,效能就可能出问题。
所以才有 GC 这个方法。
作者: xianrenb 发布时间: 2014-02-20
JS的memory leak没救了

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

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

作者: ceap2003 发布时间: 2014-02-20
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28