2008年4月30日星期三

内存泄漏的问题

近来项目发现内存泄漏问题严重,花了两天多时间才解决

修改前,实时分析雷达图每 10 秒刷新一次,内存同时增长 2M 左右
问题主要在两个地方,第一个地方占用内存最大,修改完成后,内存的增长速度降到 每分钟增长 2M 左右,第二个地方修改完成后,现在我本机测试已经看不出明显的内存增长了

内存泄漏的原因有多种,但最主要的泄漏就是 DOM 域与 js 域相互引用以及内部函数,现在我们修改的地方也是这种情况,其实如果不是经常刷新,应该问题不大,只要重启 IE 就可以释放,但我们需要不停的刷新,所以问题比较明显.

比如下面的代码:

代码一(内部函数):
function AttachEvents(element)
{
// This structure causes element to ref ClickEventHandler
element.attachEvent("onclick", ClickEventHandler);

function ClickEventHandler()
{
// This closure refs element
}
}
}

//调用此函数就会发生泄漏
function SetupLeak()
{
AttachEvents(document.getElementById("LeakedDiv"));
}


代码二(dom 跟 js 相互引用):
document.createElement("");
或者:
document.createElement("");
fuction a(){...}

1. WEB-INF/pages/sim/analyse/view/sceneEventList.jsp
有两处代码需要修改,这两处代码类似,下面是其中一处的代码及修改后的代码:

原代码:
$("headerContainer").childElements().invoke("remove");
$("headerContainer").innerHTML = headerHTML;
现代码:
$("headerContainer").innerHTML = null;
$("headerContainer").innerHTML = headerHTML;

2. web/common/scrollTable.jsp
在函数 initColumnResizer(...) 中内部建了函数

原代码:
var resizeBar = document.createElement('DIV');
resizeBar.style.backgroundColor = 'transparent';
.......
resizeBar.onmouseout = function() {
this.style.cursor = 'default';
};
.......

问题主要就在类似于 resizeBar.onmouseout = function(){...} 这样的代码上,DOM 对象 resizeBar 直接定义了函数 function,此处类似的函数一共是 6 个

解决方法就是将这些函数单独拿出来,然后再引用

现代码:

在 initColumnResizer 函数外新定义函数 mouseout 等函数,如下:

function mouseout(){
.......
}

然后在 initColumnResizer 函数中原来引用这些函数的地方用下面的代码替换:
rezeBar = null;
resizeBar = document.createElement('DIV');
resizeBar.style.backgroundColor = 'transparent';
.......

resizeBar.onmouseover = mouseover;
resizeBar.onmouseout = mouseout;
resizeBar.onclick = mouseclick;
resizeBar.onmousedown = mousedown;
resizeBar.onmousemove = mousemove;
resizeBar.onmouseup = mouseup;

2008年4月23日星期三

闭包函数导到 IE 内存泄漏



闭包函数是一个内部的函数,可以理解为函数里的函数,如下面代码一中的 ClickEventHandler 函数

如果闭包函数引用了外部变量,那么,闭包函数运行完毕后,可能并不会释放该变量,于是会导致内存泄漏



代码一:



<html>

<head>

<script language="JScript">



function AttachEvents(element)

{

// This structure causes element to ref ClickEventHandler

element.attachEvent("onclick", ClickEventHandler);



function ClickEventHandler()

{

// This closure refs element

}

}



function SetupLeak()

{

// The leak happens all at once

AttachEvents(document.getElementById("LeakedDiv"));

}



function BreakLeak()

{

}

</script>

</head>

<body onload="SetupLeak()" onunload="BreakLeak()">

<div id="LeakedDiv"></div>

</body>

</html>





解决方法就是将闭包函数先放入一个变量,这样,当它执行完成后,它仍然在内存中存在,然后再显式地释放它,如代码二:



<html>

<head>

<script language="JScript">



function AttachEvents(element)

{

// In order to remove this we need to put

// it somewhere. Creates another ref

element.expandoClick = ClickEventHandler;



// This structure causes element to ref ClickEventHandler

element.attachEvent("onclick", element.expandoClick);



function ClickEventHandler()

{

// This closure refs element

}

}



function SetupLeak()

{

// The leak happens all at once

AttachEvents(document.getElementById("LeakedDiv"));

}



//释放内存

function BreakLeak()

{

document.getElementById("LeakedDiv").detachEvent("onclick",

document.getElementById("LeakedDiv").expandoClick);

document.getElementById("LeakedDiv").expandoClick = null;

}

</script>

</head>

<body onload="SetupLeak()" onunload="BreakLeak()">

<div id="LeakedDiv"></div>

</body>

</html>

闭包函数导致 IE 内存泄漏

闭包函数导到 IE 内存泄漏
闭包函数是一个内部的函数,可以理解为函数里的函数,如下面代码一中的 ClickEventHandler 函数如果闭包函数引用了外部变量,那么,闭包函数运行完毕后,可能并不会释放该变量,于是会导致内存泄漏
代码一:


解决方法就是将闭包函数先放入一个变量,这样,当它执行完成后,它仍然在内存中存在,然后再显式地释放它,如代码二:

2008年4月8日星期二

使用开源网格计算平台-GridGain实现网格计算

From: http://blog.csdn.net/danny_xcz/archive/2007/05/24/1623536.aspx

网格计算一般分为两种:数据网格和计算网格,简单的说数据网格就是把数据分布式存储,计算网格就是将任务分解为子认为并行计算。

一个计算网格平台的作用就是将任务分解开来,交给不同的结点机器运行,然后把运行结果汇聚起来。这就是Split and Aggregate。如下图所示,一个job请求分解为三个sub-job,分别被不同的机器执行,然后把结果汇聚,返回给调用的客户。



GridGain是一个开源的java网格平台。它集成了很多现成的框架,例如

JBoss
Spring
Spring AOP
JBoss AOP
AspectJ
JGroups

GridGain有两个方法将应用程序grid化:

第一种是使用AOP

假设有一个应用

01 class BizLogic {
02 public static Result process(String param) {
03 …
04 }
05 }
06
07 class Caller {
08 public static void Main(String[] args) {
09 BizLogic.process(args[0]);
10 }
11 }
如果要把process grid化,只要简单的使用一个@Gridify的annotation即可,在Caller客户端要启动GridFactory

01 class BizLogic {
02 @Gridify(…)Here
03 public static Result process(String param) {
04 …
05 }
06 }
07
08 class Caller {
09 public static void Main(String[] args) {
10 GridFactory.start();Here
11
12 try {
13 BizLogic.process(args[0]);
14 }
15 finally {
16 GridFactory.stop();Here
17 }
18 }
19 }

这是最简单,不破坏原有业务逻辑的方法,还有一种方法如果要实现复杂些的任务分解,扩展GridifyJobAdaptor基类,实现split 和aggregate 接口