心得:Javascript的内存释放实验。

lanbor 2002-12-10 01:01:06
我以前也看过关于javascript的内存释放的文章,但我从来也没仔细看过。原因:一来我觉得这个东西可有可无,二来,鬼知道这些理论到底有没有科学根据?

今天我做了一个小小的实验,证实内存释放还是有用的。

比如有如下程序:
var a = new Array();
..........

一般a用完了就完了,谁也不会想到去释放a所占用的内存。设想代码:
var a = new Array();
..........
a = null;

有没有用呢?我做了一个实验:

在editplus中编写如下代码:
<HTML>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
//------ 使用内存段
for (var i = 0; i < 100000; i++)
{
eval("a" + i + "= new Array();");
}
//--------释放内存段
for (var i = 0; i < 100000; i++)
{
eval("a" + i + "= null;");
}

</SCRIPT>
</BODY>
</HTML>

Ctrl+B 运行这个文件以后,我打开win2000的系统监视器,看系统的内存使用情况。结果如下:

在editplus不运行这个网页前,占用的内存大概为8000多K,如果没有加上释放内存段,运行后editplus大概要运行2-3分钟才完成,内存使用数逐步上升,最终占用内存为24000多K时.

而加上了释放内存段的代码后,editplus在开始的2-3分钟内,内存也逐步上升,到了24000多K后,内存占用量开始下降,在接下来的2-3分钟内,内存使用量逐步降到了15000多K.

结论,a = new Array()后, a = null; 释放的确还是有用的,特别是对大型网站。当然,也不是完全释放,比使用前还是要多占一些内存的。 其实,在用完一个数组后,加一个 = null也不会占用多少时间的,但的确是一个好习惯 :)
...全文
1390 72 打赏 收藏 转发到动态 举报
写回复
用AI写文章
72 条回复
切换为时间正序
请发表友善的回复…
发表回复
llrock 2002-12-17
  • 打赏
  • 举报
回复
题外话,楼主的心工作怎么样,呵呵,QQ见不到你了。
希望js工作组在下一代的js中支持某种意义上的重载,这样很多不完善的地方就可以有csdn的朋友们来完善了。:)
常宁 2002-12-16
  • 打赏
  • 举报
回复
搂主打算什么时候结帖呀?
lanbor 2002-12-16
  • 打赏
  • 举报
回复
哈哈.没想到我的一个小帖子招来这么多高手讨论.:)

其实我的帖子可以简化的得出下面的结论:(数据是虚拟和简化了的,旨在说明问题)

1) 假如你的系统开始有100K的可用内存.
2) 用户用IE打开你的页面,执行一段JS脚本.
3) 当执行到 a = new Array();
4) 这时用户的系统只有90K的可用内存了.
5) 当执行到 a = null 后
6) 这时用户的系统有95K的可用内存了.

就是说,假如一个用户打开了你的网页,运行了你的脚本.(正在浏览,没关闭!!)..如果你的脚本没有加a =null; 那么他就只有90K的内存可以做别的事情,比如又打开Photoshop软件绘图.如果你的脚本加了a=null;他就可能就有95K的内存可以用Photoshop了.

我说的都是IE没有关闭的情况.(设想,他可能正照着这个网页在photoshop里绘图).至于关了IE是什么情况,我没做实验.

所以,不管你知不知道原理,如果你的脚本里有大量的Array.不妨用完以后加上=null.这样会给你的用户带来一点点好处.:)....
常宁 2002-12-13
  • 打赏
  • 举报
回复
to andot(雨飞)
其实JScript的内存回收机制是在牺牲性能的情况下换取的,他的性能要比其他的实现慢进一个数量级,其他的解释核心的实现是编译+bit虚拟机,就类似java一样,他的就不是那么简单,他也要编译,但是运行就不同了。因此不能说他的回收机制很好,只不过大家的取舍不一样而已,我更喜欢javascript的方式,而不是jscript的方式。你的实验我没做过,不过我看好像在javascript也不会因为createElement而占用大量内存
andot 2002-12-13
  • 打赏
  • 举报
回复
测试结果虽然没有发现removeNode是否起了作用(因为不论是否加上removeNode,内存的使用都没有增加,看来JScript的垃圾回收机制确实很好!)但是测试结果表明第一种写法要比第二种写法慢好多(看来createElement确实花费很多的时间)。所以我觉得还是改成第二种写法好。
常宁 2002-12-13
  • 打赏
  • 举报
回复
to andot(雨飞)
由于我仅仅对JavaScript核心进行开发,而JScript不是一个开放的标准因此,我无法说明JScript的GC的内部实现原理,至于是否真的会增加数量需要微软的解释,不过M$似乎会控制对象的数量,它一般会将这个创建对象达到一定程度后,进行强制性的内存回收,因此如果打算循环10000000次来看内存是否有很大增长似乎并不现实,当然我指的是JScript,而对于JavaScript这个方法通常应该是有效的
andot 2002-12-13
  • 打赏
  • 举报
回复
to redpower(常宁)
你的意思是不是说,JScript的垃圾收集机制与JavaScript不一样,比如我的那个函数:
function parseColor(color) {
var ColorParser = document.createElement("td");
ColorParser.bgColor = color;
return ColorParser.removeNode().bgColor;
}
在执行完成以后,不会增加文档中的对象数目,是不是啊?(我的意思是,removeNode是否真的把createElement的td给移除了,哪怕是做了标记,下次再调用时createElement时,会利用以标记的这个对象的空间也可以啊。)
哦,对了,我可以做个实验看看。
常宁 2002-12-13
  • 打赏
  • 举报
回复
to andot(雨飞)
我前面说过了,Javascript是不会主动在程序没有结束前去执行GC功能的(我不是说其他JavaScript实现肯定会遵循这个,比如JScript就是一个例外,主要原因是这个东西根本就不遵循JavaScript规范)因此,这个地方你无论如何写,如果他真的为这个对象分配内存了,那么就不会释放掉。其实远不止建立对象会这样,比如执行一个字符串转换为整数的函数,他就会建立一个“可变类型对象“而这个对象是不会再函数执行完毕后释放(因为是传值的而不是传址的)所以如下代码如果JavaScript支持,则会占用大量内存:
var a=1234;
for(var i=0;i<10000000;i++)
{
println(a);
}
至少现在大多数的JavaScript实现都会有这个问题,当然JScript不会存在这个问题,因为它不执行JavaScript规范的要求。
下面的就不会有问题
var a=1234;
var b="1234";
for(var i=0;i<10000000;i++)
{
println(b);
}
这个无论什么实现,基本都不会有内存增加的问题
我这样说你应该明白了吧
xjbx 2002-12-13
  • 打赏
  • 举报
回复
学习!
emu 2002-12-13
  • 打赏
  • 举报
回复
楼主说的大概是在js运行过程中动态的强行释放不再引用的对象占用的内存吧,关掉了IE后的内存问题咱们javascript版又能有什么办法?
llrock 2002-12-13
  • 打赏
  • 举报
回复
FAINT
楼主梭说的释放是什么意思?
=========================
产生那么多实例,是要花些时间,占些内存是应该的。
你用EditPlus运行后,不关掉那页,内存怎么释放,如果IE都关掉了,内存还是居高不下,那时释放的问题,好好升级的得IE。如果你的系统还是慢得象蜗牛,你盖重新启动机器了,多半是出现了内存碎片,在堆里创建那么多小东西,再删除,够乱的.

=========================
我现在还是没明白楼主说什么呢?
wgrabob1 2002-12-13
  • 打赏
  • 举报
回复
高手就是高手
saucer 2002-12-13
  • 打赏
  • 举报
回复
>>>>1) 如果你在另一个window中keep了该window中的object的reference,即使关闭该window,内存也没有释放

As you might know, windows opened with window.open() may share a process with its opener (_blank or _new window may not). That is, even if you see those two windows on the desktop, if you look at the process table in the Task Manager, you may only see one IEXPLORE.EXE running. Memory may only be released when the process is terminated

>>>>2)更糟糕的是,如果你keep的是一个DOM object的reference, 关闭该object 所在window, IE会crash, 报内存错误(或者要求,重新启动)

I would say this looks like a bug, you might want to report to Microsoft
nbm0 2002-12-13
  • 打赏
  • 举报
回复

角角多,星星多多!
chenzengxi 2002-12-13
  • 打赏
  • 举报
回复
这么多高手,学习。
常宁 2002-12-12
  • 打赏
  • 举报
回复
to sunmingdong() ( )
这个同解释器没有关系,是否释放关键是在寄主身上,反正不会影响什么,毕竟javascript都是些小程序,而且不会也不应该有频繁的内存申请,当然编成风格不好的程序除外。据我所知好像IE合NS都不会在程序退出前释放。
sunmingdong 2002-12-12
  • 打赏
  • 举报
回复
如果不释放内存,关闭网页或跳到别的网页上,内存不会自动释放吗?

学习
常宁 2002-12-12
  • 打赏
  • 举报
回复
值得说明的是JScript并不是javascript,他们中间有很多显著的不同点,而且很多是本质上的。
常宁 2002-12-12
  • 打赏
  • 举报
回复
to wsj(骆驼)
你说的这个是jscript的,我说过:
>> redpower(常宁) ( ) 信誉:100 2002-12-12 11:08:00 得分:0
>> 这只是一个简单的垃圾回收问题,如果做过编译器和bit解释器的人
>>应该很熟悉这个原理,远离比较复杂,不过有一点是一定的javascript不
>>会主动释放内存!这个主要同性能要求有关,其实javascript是可以做到
>>自动释放内存的。但是现在的解释核心都没有这样去做,jscript的内存
>>释放机制还是可以的,但是仍然不会主动释放所有内存(可能会释放
>>部分内存)
这并不与我的论点相左,而是证明了我的论点
(When 256 variants, or more than 64KB of strings, or more than 4096 array slots have been allocated, the garbage collector sets a flag that says collect soon.)


(When the script engine is shut down, garbage is collected.)这个则是证明了我下面的论述:
>>通常这个函数会在核心推出内存,因就是IE或NS程序结束的时候才会
>>调用.这样才是安全的
你说是不是:)




wsj 2002-12-12
  • 打赏
  • 举报
回复
楼上的,我们这里太需要你这样的人来说几句了。
欢迎以后常来,多和大家唠唠:)

不过,MSDN上说:

When the script engine is shut down, garbage is collected.

When 256 variants, or more than 64KB of strings, or more than 4096 array slots have been allocated, the garbage collector sets a flag that says collect soon.

Whenever a new statement is executed or the script debugger starts, that flag is checked, and if it is set, a collection is done.

为什么说他不会主动调用呢?
加载更多回复(52)

87,910

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧