高手请进,js执行速度随页面元素的增加越来越慢是什么原因?有什么解决方法呢?

时间:2022-03-26 18:52:46
最近在测试一段代码的时候发现的这个问题
很郁闷

以下是对1000个节点进行操作的几次重复测试
结果如下:
共有节点:10000
子节点数据:1000
清除旧数据:31毫秒

EV:BabyMap:0

EP:nodeIndex(0)
EP:haveBaby(1000)
EP:mainLoop:2031
EP:isHavebaby:80
EP:insertHtml:1344

EP:nodeIndex(9)
EP:haveBaby(1000)
EP:mainLoop:2968
EP:isHavebaby:31
EP:insertHtml:1796

EP:nodeIndex(8)
EP:haveBaby(1000)
EP:mainLoop:3578
EP:isHavebaby:15
EP:insertHtml:1813

EP:nodeIndex(7)
EP:haveBaby(1000)
EP:mainLoop:4578
EP:isHavebaby:64
EP:insertHtml:1984

EP:nodeIndex(6)
EP:haveBaby(1000)
EP:mainLoop:5485
EP:isHavebaby:16
EP:insertHtml:1968

EP:nodeIndex(5)
EP:haveBaby(1000)
EP:mainLoop:6453
EP:isHavebaby:64
EP:insertHtml:2047

EP:nodeIndex(4)
EP:haveBaby(1000)
EP:mainLoop:7547
EP:isHavebaby:95
EP:insertHtml:2250

解释一下:
EP:mainLoop:7547-----主循环的执行时间
EP:isHavebaby:95-----主循环中一段代码的执行事件(这里可以忽略)
EP:insertHtml:2250---插入HTML代码的执行时间

因为每次都是对1000个节点进行操作
计算量和需要插入的html代码长度都是基本一致的
但是结果却显示
执行事件从最初的2031+1344=3K,上升到后来的7547+2250=9K
效率下降之快......呜呜,比我花了好长时间调整来的性能优化效果可明显的多了

js的执行速度为什么与页面元素数量关系这么大呢?
我的机器1G内存,还够浏览器吃的
想不通,请高手指点

解决问题后立刻放分

还想到了以前的一个现象
最初有个html和js混合的页面
其中有一段js的循环,空循环,竟然执行的奇慢
把所有的html代码删除后
再运行那个空循环
消耗时间:0

太奇怪了

这个问题困扰了好几天了
一直找不到原因和解决方法

28 个解决方案

#1


你增加的网页的元素都在内存里面的啊,增加的越多,处理时间和显示的速度都会延长,所以会慢啊

#2


加快DHTML 的一组技巧

http://www.knowsky.com/3744.html

#3


已经考虑到DHTML的一些问题了
html代码也是先合成再一次插入的
不过长度比较大
而且在html代码中还存在 onfocus="F()"这中情况
也就是说插入的html中包含时间处理句柄
在关于IE内存泄漏的文章中看到过有这种情形
不知道是不是这个原因

我觉得即使存在内存消耗的问题
也只是内存使用量的问题
不会影响到运行速度啊

目前想到的原因可能有:
1.js虚拟机试图回收内存,所以内存消耗约大,这一部分的cpu消耗也越大
2.如孟子说的.IE要维持各个网页元素的view,元素多了,正确显示所需的时间就越多了

但是没有找到好办法解决

#4


这个原因是很多的, 要具体看你的应用和你的代码而定优化方案, 一千个节点量不算大.

#5


激动ing

to 梅花雪

1000个确实不是个太大的数据量
我是拿他作为一个性能参照的

最初的提问,是1W个节点每次展开1000

也就是说最后一次展开的时候
内存中已经有1W节点的数据和9K节点的DOM元素了

但是这个速度让我无法忍受

梅大侠你的treeview树在展开的时候似乎不允许每次展开1000节点

我用你的treeview1.0做了测试
一下是测试数据的复制

节点 3 有 850 个子节点
加载耗时:4062 毫秒!

节点 4 有 903 个子节点
加载耗时:6250 毫秒!

节点 2 有 929 个子节点
加载耗时:8375 毫秒!

节点 5 有 911 个子节点
加载耗时:10281 毫秒!

节点 6 有 926 个子节点
加载耗时:12141 毫秒!

节点 7 有 932 个子节点
加载耗时:14219 毫秒!

此时IE浏览器反应明显减慢(在原先展开的节点已经收缩的情况下)

第六次展开900节点的时候
加载时间已经是14219毫秒了

而我现在调整的这颗树
第七次加载时的数据是:
EP:mainLoop:7547
EP:isHavebaby:95
EP:insertHtml:2250
所耗时间为:7547+2250=9797毫秒


而且两个树在这个时候将浏览器折磨的已经不成样子了

希望有兴趣的朋友一起探讨优化方案

解决(似乎微软的责任更大一些)或者减轻IE执行效率下降的问题

#6


补充一点
梅花的treeview1.0的测试参数为
总节点数:10240
子节点:900

#7


看来都是高手们讨论的性能问题,只有学习的份了。

呵呵,帮顶。

#8


欢迎大家参与啊,都有分的,不够可以再加
第一次散分,
最少100分
如果问题解决,我一次散900分都没问题

#9


我是不是只能发200分的帖子啊

#10


DOM 的内部实现涉及很多字符串操作 字符串操作是比较耗时的
另外浏览器的实现方法也有一定原因 你用 Firefox 测试的话 肯定比 IE 效率高
不是必要的话 就不要在客户端做太复杂的 DOM 操作
Ajax 的出现也加重了客户端的此类负担  实际应用中若平衡得不好的话 必将弊大于利

#11


同意楼上的
firefox下的字符串效率确实比IE要高很多

firefox下直接使用+=连接字符串 都比 IE下面 使用push 然后数组join来的快

我想字符串连接之所以耗时

是因为这个怎么优化他也要挨着拷贝的,所以时间总是有的

对于ajax,喜欢其基本原理带来的页面局部刷新的效果和数据后台载入

对有关ajax的大型框架,没有用过,暂时不感冒

PS:看了看论坛说明,我现在只能发100分的帖子,晕了,明明有不少分,竟然散不出去

#12


能不能让把循环放在server端呢,这样js就不用去耗费那么多时间了

#13


把循环放到server端,就是在server端生成html代码了,这样传输量会增大很多的

这里就有个js循环和大传输的权衡问题了

谢谢楼上的建议

不过问题是IE的执行效率一直在下降啊
不论你的HTML代码是在客户端生成的,还是在服务端生成后传输来的
插入HTML代码的时候,基本相同的数据量,速度越来越慢
真让人头疼啊

回头我再认真测试一下

刚才登录csdn,验证码是888888,哈哈

#14


自己顶一个

#15


如果不复杂就用.Net的回调实现局部刷新!

我比较迷惑在什么样的需求情况下需要一次加栽这么多内容呢??







-----------------------
没有最好,只有更好!
http://www.crossgo.com

#16


楼上的问题提的好

一般来说,常见的应用也就是导航或者显示分类

用作导航的话,不出200节点吧

用作分类的话,如果是全国县市的话

有2000节点左右,并且是共有节点2000,而不是一次加载2000

但是性能下降问题是确实存在的

在网页元素增加的情况下

所有的DHTML操作,js执行效率都会下降,影响的不仅仅是我的一次加载(数据一次加载,分批展示,并不是一次展开)的树,

即使是回调,局部刷新,网页元素也是在慢慢增加不是?网页元素多了,刷新效率是不是也会降下来?

这才是问题所在

之所以使用1000个节点做测试

只是为了将性能下降问题反映出来

然后大家一起努力看看能否改善这种情况

#17


我顶

#18


希望大家帮帮我

#19


JF

#20


好像是代码问题 我这样测试就好像没问题

<script language="javascript">
function window.onload()
{
var nodes = new Array();
for(var i=0;i<10;i++)
{
var area = document.body;//FF测试时做相应的更改
var aa = document.createElement("div");
area.appendChild(aa);
nodes[i] = aa;
nodes[i].subNodes = new Array();
for(var j=0;j<1000;j++)
{
var aa = document.createElement("div");
nodes[i].appendChild(aa);
nodes[i].subNodes.push(aa);
}
}
var stime = new Date();

for(var i=0,l=nodes.length;i<l;i++)
{
var havebadycount = 0;
var ihavebadycount = 0;
var insertcount = 0;
var maincount = 0;
var maints = new timeSpan();
var ts = new timeSpan();
var tempnode = nodes[i];
ts.start();
for(var j=0,l1=tempnode.subNodes.length;j<l1;j++)
if(tempnode.subNodes[j].children.length>0)ihavebadycount++;//FF测试时改一下这句
havebadycount = ts.timeSpan();
ts.start();
for(var j=0,l1=tempnode.subNodes.length;j<l1;j++)
tempnode.subNodes[j].innerHTML = "this is inserted HTML";
insertcount = ts.timeSpan();
maincount = maints.timeSpan();
var sourceString = "Node:("+i+")\nNodes:"+ tempnode.subNodes.length + "\nmainLoop:" + maincount + "\nisHaveBady:" + havebadycount + "\ninsertHtml:" + insertcount;
alert(sourceString);
}
}

function timeSpan()
{
this.stime = new Date();
this.timeSpan = function(){return (new Date())-this.stime;}
this.start = function(){this.stime = new Date();}
}
</script>

#21


关注中......

#22


正在测试和调整代码。。。。。。

#23


谢谢gzdiablo的测试代码

#24


to gzdiablo
我把代码中的一条语句改了一下
tempnode.subNodes[j].innerHTML = "<div id=" + i + "_" + j + "><img id=" + i + "_" + j + "m0 src='sIL.gif'><img id=" + i + "_" + j + "m1 src='sIL.gif'><img id=" + i + "_" + j + "m2 src='sIS.gif'><a id=" + i + "_" + j + "m1 href='javascript:undefined' >this is inserted HTML" + i + "_" + j +"</a></div>";

一共加了1个div,一个a,三个图片

原程序每加载1000个,耗时约500
加了两个图片,每加载1000个耗时约5000!!!(原来图片这么消耗资源)
又加了一个图片,每加载1000个耗时7700,并且慢慢出现了效率降低的情况,最后一次展开耗时8300(效率降低还不是很明显)

不过加载完成后页面反映还是很迅速的,浏览器没有死掉

准备继续调整

#25


这个效率降低应该是图片加载时的系统消耗 
因为程序加载速度非常的快 不断需要渲染更多图片 所带来的系统损耗会很明显的影响程序运行
你可以尝试去掉图片 应该不会再有性能下降的问题

#26


貌似也就只能尽量减少客户端操作,操作多了,肯定会耗内存。顺便再bs一下ie的字符串操作。

#27


同意gzdiablo的看法
目前为止也没有找到其他的方法来解释和解决这个问题
只能在强调性能的地方尽量少用图片了

IE的字符串操作确实比较慢,优化之后的速度还比FF慢

#28


最近,我也遇到类似问题:
用google api 在地图上画700个点,130条线。然后在点击'确定'按钮的时候在函数composeData中用strData += ...的方式循环组装字符串数据。700次循环啊,速度奇慢无比!只要不是组装字符串,速度就不慢。
我晕啊

#1


你增加的网页的元素都在内存里面的啊,增加的越多,处理时间和显示的速度都会延长,所以会慢啊

#2


加快DHTML 的一组技巧

http://www.knowsky.com/3744.html

#3


已经考虑到DHTML的一些问题了
html代码也是先合成再一次插入的
不过长度比较大
而且在html代码中还存在 onfocus="F()"这中情况
也就是说插入的html中包含时间处理句柄
在关于IE内存泄漏的文章中看到过有这种情形
不知道是不是这个原因

我觉得即使存在内存消耗的问题
也只是内存使用量的问题
不会影响到运行速度啊

目前想到的原因可能有:
1.js虚拟机试图回收内存,所以内存消耗约大,这一部分的cpu消耗也越大
2.如孟子说的.IE要维持各个网页元素的view,元素多了,正确显示所需的时间就越多了

但是没有找到好办法解决

#4


这个原因是很多的, 要具体看你的应用和你的代码而定优化方案, 一千个节点量不算大.

#5


激动ing

to 梅花雪

1000个确实不是个太大的数据量
我是拿他作为一个性能参照的

最初的提问,是1W个节点每次展开1000

也就是说最后一次展开的时候
内存中已经有1W节点的数据和9K节点的DOM元素了

但是这个速度让我无法忍受

梅大侠你的treeview树在展开的时候似乎不允许每次展开1000节点

我用你的treeview1.0做了测试
一下是测试数据的复制

节点 3 有 850 个子节点
加载耗时:4062 毫秒!

节点 4 有 903 个子节点
加载耗时:6250 毫秒!

节点 2 有 929 个子节点
加载耗时:8375 毫秒!

节点 5 有 911 个子节点
加载耗时:10281 毫秒!

节点 6 有 926 个子节点
加载耗时:12141 毫秒!

节点 7 有 932 个子节点
加载耗时:14219 毫秒!

此时IE浏览器反应明显减慢(在原先展开的节点已经收缩的情况下)

第六次展开900节点的时候
加载时间已经是14219毫秒了

而我现在调整的这颗树
第七次加载时的数据是:
EP:mainLoop:7547
EP:isHavebaby:95
EP:insertHtml:2250
所耗时间为:7547+2250=9797毫秒


而且两个树在这个时候将浏览器折磨的已经不成样子了

希望有兴趣的朋友一起探讨优化方案

解决(似乎微软的责任更大一些)或者减轻IE执行效率下降的问题

#6


补充一点
梅花的treeview1.0的测试参数为
总节点数:10240
子节点:900

#7


看来都是高手们讨论的性能问题,只有学习的份了。

呵呵,帮顶。

#8


欢迎大家参与啊,都有分的,不够可以再加
第一次散分,
最少100分
如果问题解决,我一次散900分都没问题

#9


我是不是只能发200分的帖子啊

#10


DOM 的内部实现涉及很多字符串操作 字符串操作是比较耗时的
另外浏览器的实现方法也有一定原因 你用 Firefox 测试的话 肯定比 IE 效率高
不是必要的话 就不要在客户端做太复杂的 DOM 操作
Ajax 的出现也加重了客户端的此类负担  实际应用中若平衡得不好的话 必将弊大于利

#11


同意楼上的
firefox下的字符串效率确实比IE要高很多

firefox下直接使用+=连接字符串 都比 IE下面 使用push 然后数组join来的快

我想字符串连接之所以耗时

是因为这个怎么优化他也要挨着拷贝的,所以时间总是有的

对于ajax,喜欢其基本原理带来的页面局部刷新的效果和数据后台载入

对有关ajax的大型框架,没有用过,暂时不感冒

PS:看了看论坛说明,我现在只能发100分的帖子,晕了,明明有不少分,竟然散不出去

#12


能不能让把循环放在server端呢,这样js就不用去耗费那么多时间了

#13


把循环放到server端,就是在server端生成html代码了,这样传输量会增大很多的

这里就有个js循环和大传输的权衡问题了

谢谢楼上的建议

不过问题是IE的执行效率一直在下降啊
不论你的HTML代码是在客户端生成的,还是在服务端生成后传输来的
插入HTML代码的时候,基本相同的数据量,速度越来越慢
真让人头疼啊

回头我再认真测试一下

刚才登录csdn,验证码是888888,哈哈

#14


自己顶一个

#15


如果不复杂就用.Net的回调实现局部刷新!

我比较迷惑在什么样的需求情况下需要一次加栽这么多内容呢??







-----------------------
没有最好,只有更好!
http://www.crossgo.com

#16


楼上的问题提的好

一般来说,常见的应用也就是导航或者显示分类

用作导航的话,不出200节点吧

用作分类的话,如果是全国县市的话

有2000节点左右,并且是共有节点2000,而不是一次加载2000

但是性能下降问题是确实存在的

在网页元素增加的情况下

所有的DHTML操作,js执行效率都会下降,影响的不仅仅是我的一次加载(数据一次加载,分批展示,并不是一次展开)的树,

即使是回调,局部刷新,网页元素也是在慢慢增加不是?网页元素多了,刷新效率是不是也会降下来?

这才是问题所在

之所以使用1000个节点做测试

只是为了将性能下降问题反映出来

然后大家一起努力看看能否改善这种情况

#17


我顶

#18


希望大家帮帮我

#19


JF

#20


好像是代码问题 我这样测试就好像没问题

<script language="javascript">
function window.onload()
{
var nodes = new Array();
for(var i=0;i<10;i++)
{
var area = document.body;//FF测试时做相应的更改
var aa = document.createElement("div");
area.appendChild(aa);
nodes[i] = aa;
nodes[i].subNodes = new Array();
for(var j=0;j<1000;j++)
{
var aa = document.createElement("div");
nodes[i].appendChild(aa);
nodes[i].subNodes.push(aa);
}
}
var stime = new Date();

for(var i=0,l=nodes.length;i<l;i++)
{
var havebadycount = 0;
var ihavebadycount = 0;
var insertcount = 0;
var maincount = 0;
var maints = new timeSpan();
var ts = new timeSpan();
var tempnode = nodes[i];
ts.start();
for(var j=0,l1=tempnode.subNodes.length;j<l1;j++)
if(tempnode.subNodes[j].children.length>0)ihavebadycount++;//FF测试时改一下这句
havebadycount = ts.timeSpan();
ts.start();
for(var j=0,l1=tempnode.subNodes.length;j<l1;j++)
tempnode.subNodes[j].innerHTML = "this is inserted HTML";
insertcount = ts.timeSpan();
maincount = maints.timeSpan();
var sourceString = "Node:("+i+")\nNodes:"+ tempnode.subNodes.length + "\nmainLoop:" + maincount + "\nisHaveBady:" + havebadycount + "\ninsertHtml:" + insertcount;
alert(sourceString);
}
}

function timeSpan()
{
this.stime = new Date();
this.timeSpan = function(){return (new Date())-this.stime;}
this.start = function(){this.stime = new Date();}
}
</script>

#21


关注中......

#22


正在测试和调整代码。。。。。。

#23


谢谢gzdiablo的测试代码

#24


to gzdiablo
我把代码中的一条语句改了一下
tempnode.subNodes[j].innerHTML = "<div id=" + i + "_" + j + "><img id=" + i + "_" + j + "m0 src='sIL.gif'><img id=" + i + "_" + j + "m1 src='sIL.gif'><img id=" + i + "_" + j + "m2 src='sIS.gif'><a id=" + i + "_" + j + "m1 href='javascript:undefined' >this is inserted HTML" + i + "_" + j +"</a></div>";

一共加了1个div,一个a,三个图片

原程序每加载1000个,耗时约500
加了两个图片,每加载1000个耗时约5000!!!(原来图片这么消耗资源)
又加了一个图片,每加载1000个耗时7700,并且慢慢出现了效率降低的情况,最后一次展开耗时8300(效率降低还不是很明显)

不过加载完成后页面反映还是很迅速的,浏览器没有死掉

准备继续调整

#25


这个效率降低应该是图片加载时的系统消耗 
因为程序加载速度非常的快 不断需要渲染更多图片 所带来的系统损耗会很明显的影响程序运行
你可以尝试去掉图片 应该不会再有性能下降的问题

#26


貌似也就只能尽量减少客户端操作,操作多了,肯定会耗内存。顺便再bs一下ie的字符串操作。

#27


同意gzdiablo的看法
目前为止也没有找到其他的方法来解释和解决这个问题
只能在强调性能的地方尽量少用图片了

IE的字符串操作确实比较慢,优化之后的速度还比FF慢

#28


最近,我也遇到类似问题:
用google api 在地图上画700个点,130条线。然后在点击'确定'按钮的时候在函数composeData中用strData += ...的方式循环组装字符串数据。700次循环啊,速度奇慢无比!只要不是组装字符串,速度就不慢。
我晕啊