javascript-内部如何调整JS数组的大小?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了javascript-内部如何调整JS数组的大小?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4496字,纯文字阅读大概需要7分钟。
内容图文
![javascript-内部如何调整JS数组的大小?](/upload/InfoBanner/zyjiaocheng/694/a027180652164ef789b636cbfada7bd4.jpg)
因此,我一直试图在JS中实现具有某些自定义功能的类的集合类型(类似于C#中的List).我还希望对其进行某种程度的优化(我已经阅读了一些有关如何正确使用JS数组的文章).
因此,我对自己想:“如果我们不为数组定义初始大小,而是继续向其添加对象,则内部必须为每次插入分配新的大小,这必须很慢.我可以通过分配来避免这种情况我自己更改了一个新大小(改变了数组的长度),有点类似于在CSharp中完成的操作,每当达到最大容量时,大小都会加倍(我知道这不是小事,但这只是一个开始)”
我试图实现这个想法,发现它慢得多(慢了10倍):
//This simplified approach of my implementation is faster...
var array = [];
var counter = 0;
function addItem(newItem) {
array[++counter] = newItem;
}
//..than this version that resizes the array when a limit is reached
var array = [];
array.length = INITIAL_SIZE;
/*
Alternatively
var array = new Array(INITIAL_SIZE);
*/
var counter = 0;
function addItem(newItem) {
if( CheckCapacity(counter + 1) ) { //Function that checks if the maximum size is reached and if it is, change the array.length to the new size
array[++counter] = newItem;
}
}
在测试之前,我心想:“由于在调用CheckCapacity(counter 1)时具有新的数组大小,因此在内部(JS Array)与第一个函数相比,无需进行太多操作我确保有足够的可用空间”,即第二个函数上的array [counter] = newItem行应比第一个函数中的相同更快.
我什至使用了不同的数组,这些数组包含用于保存项目的预先计算的大小;它仍然较慢.
回到我的问题,JS Array的实现如何分配必要的大小?我是否可以正确地假设不能做太多事情来加快此过程?在我看来,每次添加新项时动态地分配更多内存的对象(JS数组)的弊端就是速度的损失(除非它实现了相当好的算法,但是我没有不知道,因此是我的问题).
解决方法:
在Javascript中,数组是一种抽象.它的实现方式(以及执行分配和调整大小的时间)留给Javascript引擎-ECMAScript规范并不指示如何实现.因此,基本上没有确切的方法知道.
实际上,Javascript引擎非常聪明地了解如何分配内存,并确保不要分配太多.在我看来,它们比C#的List更复杂-因为Javascript引擎可以根据情况动态更改基础数据结构.算法各不相同,但是大多数算法会考虑您的阵列中是否存在“空洞”:
var array = [];
array[0] = "foo" // is a resizable array
array[1] = "bar" // is a resizable array
array[2] = "baz" // is a resizable array
array[1000000] = "hello"; // is now a hash table
console.log(array[1000000]) // "hello"
如果您正常使用数组并使用从零开始的连续键,那么就没有“空洞”,大多数Javascript引擎将通过使用可调整大小的数组数据结构来表示Javascript数组.现在考虑第四项任务,我创建了一个所谓的“孔”,其大小大约为一百万(该孔跨越插槽3-999999).事实证明,JavaScript引擎足够聪明,不会为这个巨大的漏洞分配约100万个内存插槽.它检测到我们现在有一个空洞,它将使用字典/哈希表之类的数据结构表示Javascript数组(它使用二进制搜索树,其中的键被散列)以节省空间.它不会存储该孔的空间,仅存储四个映射:(0,“ foo”),(1,“ bar”),(2,“ baz”),(1000000,“ hello”).
不幸的是,对于引擎而言,访问数组现在变得更慢,因为它现在必须计算散列并遍历树.如果没有孔,则使用可调整大小的数组,访问时间更快,但是,如果有孔,则阵列的性能会降低.通用术语是说Array是密集数组,如果没有任何孔(使用可调整大小的数组=更好的性能),而Array是稀疏数组,则有一个或多个孔(使用哈希)表=性能降低).通常,为了获得最佳性能,请尝试使用密集阵列.
现在结束,让我告诉您以下是一个坏主意:
var array = new Array(1000000);
array[0] = "foo"; // is a hash table
上面的数组有一个大小约为100万的孔(就像这样:[“ foo”,undefined,undefined,… undefined]),因此,它使用哈希表作为基础数据结构.因此,自己实施调整大小是一个坏主意-这会造成漏洞,并导致性能下降.您只是在混淆Javascript引擎.
这就是您的代码正在做的事情,您的数组中始终有一个洞,因此使用哈希表作为基础数据结构;与没有任何孔的阵列(又称代码的第一个版本)相比,性能会降低.
Am I correct to assume that not much can be done to speed this process up?
是的,关于空间的预分配,在用户方面几乎没有什么可做的.通常,要加快Javascript数组的速度,您要避免创建稀疏数组(避免创建空洞):
>不要使用新的Array(size)进行预分配.而是“随您成长”.引擎将计算出可调整大小的基础数组本身的大小.
>使用从0开始的连续整数键.不要从大整数开始.请勿添加非整数的键(例如,请勿使用字符串作为键).
>尽量不要删除数组中间的键(不要从填充了索引0-9的数组中删除索引5的元素).
>不要在密集和稀疏的数组之间来回转换(即不要重复添加和删除孔).引擎与可调整大小的数组与哈希表表示形式之间来回转换会产生开销.
The disadvantage of [JS Arrays over C# Lists is that they] dynamically allocate more memory each time a new item is added
不,不一定.当Javascript数组没有空洞时,C#列表和Javascipt数组基本相同.两者都是可调整大小的数组.区别在于:
> C#列表使用户可以更好地控制可调整大小数组的行为.在Javascript中,您无法控制它-它在引擎内部.
> C#列表允许用户预分配内存以获得更好的性能,而在Javascript中,您应该让引擎自动确定如何在底层可调整大小的数组中预分配内存以获得更好的性能.
内容总结
以上是互联网集市为您收集整理的javascript-内部如何调整JS数组的大小?全部内容,希望文章能够帮你解决javascript-内部如何调整JS数组的大小?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。