Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/465.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript es6映射和设置复杂性,v8实现_Javascript_Ecmascript 6_Set_Complexity Theory_V8 - Fatal编程技术网

Javascript es6映射和设置复杂性,v8实现

Javascript es6映射和设置复杂性,v8实现,javascript,ecmascript-6,set,complexity-theory,v8,Javascript,Ecmascript 6,Set,Complexity Theory,V8,在v8实现中,检索/查找是O(1),这是一个公平的假设吗 (我知道标准并不能保证这一点) 在v8实现中,检索/查找是O(1),这是一个公平的假设吗 对。V8使用哈希表的一个变体,对于这些操作,哈希表通常具有O(1)复杂性 有关详细信息,您可能想看看OrderedHashTable是基于什么实现的。因为人们不想把兔子洞挖得太深: 1:我们可以假设好的哈希表实现实际上具有O(1)时间复杂性。 2:这里有一个由V8团队发布的博客,解释了如何在Map、Set、WeakSet和WeakMap的哈希表实现上

在v8实现中,检索/查找是O(1),这是一个公平的假设吗

(我知道标准并不能保证这一点)

在v8实现中,检索/查找是O(1),这是一个公平的假设吗

对。V8使用哈希表的一个变体,对于这些操作,哈希表通常具有
O(1)
复杂性


有关详细信息,您可能想看看OrderedHashTable是基于什么实现的。

因为人们不想把兔子洞挖得太深:

1:我们可以假设好的哈希表实现实际上具有O(1)时间复杂性。
2:这里有一个由V8团队发布的博客,解释了如何在
Map
Set
WeakSet
WeakMap
哈希表实现上进行一些内存优化:

基于1和2:V8的Set和Map的
get
&
Set
&
add
&
的时间复杂度实际上是O(1)。

让Map=newmap();
设obj={};
常量基准映射集=大小=>{
控制台时间(“基准映射集”);
for(设i=0;i{
console.time(“benchMarkMapGet”);
for(设i=0;i{
控制台时间(“基准测试对象集”);
for(设i=0;i{
控制台时间(“基准对象”);
for(设i=0;i

基准地图集:382.935ms
基准对象集:76.077ms
基准MapGet:125.478ms
基准目标集:2.764ms


基准地图集:373.172ms
基准OBJSET:77.192ms
基准地图获取:123.035ms

benchMarkObjGet:2.638ms

原来的问题已经得到了回答,但是O(1)并没有告诉我们实现的效率有多高

首先,我们需要了解哈希表的哪些变体用于映射。“经典”哈希表不会这样做,因为它们不提供任何迭代顺序保证,而ES6规范要求按迭代顺序插入。所以,V8中的地图是建立在所谓的。该思想与经典算法类似,但bucket还有另一层间接寻址,所有条目都插入并存储在固定大小的连续数组中。确定性哈希表算法确实保证了基本操作的时间复杂性为O(1),如
set
get

接下来,我们需要知道哈希表的初始大小、负载因子以及它如何(以及何时)增长/收缩。简单的回答是:初始大小为4,负载系数为2,表(即映射)在达到其容量时立即增大x2,在删除的条目超过1/2时立即缩小

让我们考虑最坏的情况,当表有N个条目(满)时,所有条目都属于单个桶,所需的条目位于尾部。在这种情况下,查找需要在链元素中移动N次

另一方面,在表已满但每个bucket有2个条目的最佳情况下,查找最多需要2次移动

众所周知,虽然哈希表中的单个操作“便宜”,但重新灰化却不便宜。重新哈希具有O(N)时间复杂度,需要在堆上分配新的哈希表。此外,必要时,作为插入或删除操作的一部分执行重新灰化。因此,例如,
map.set()
调用可能比您预期的更昂贵。幸运的是,再灰化是一种相对少见的操作


除此之外,诸如内存布局或哈希函数之类的细节也很重要,但我不打算在这里讨论这些细节。如果你想知道V8地图在引擎盖下是如何工作的,你可以找到更多细节。不久前,我对这个话题很感兴趣,并试图以可读的方式分享我的发现。

我们为什么不进行测试呢

var size_1=1000,
尺寸2=1000000,
map_sm=新映射(数组.from({length:size_1},(u,i)=>[++i,i]),
map_lg=新映射(数组.from({length:size_2},(u,i)=>[++i,i]),
i=尺寸_1,
j=尺寸_2,
s
s=性能。现在();
而(i)map_sm.get(i--);;
log(`Size${Size_1}map返回平均值为${(performance.now()-s)/Size_1}ms`)的项;
s=性能。现在();
而(j)map_lg.get(j--);

log(`Size${Size_2}map返回一个平均值为${(performance.now()-s)/Size_2}ms`)的项平均值?或者最坏的情况?顺便说一句,@Oriol这两个标准都很想知道。不确定V8使用的是什么,但其中提到了哈希表作为一种可能性。平均时间为常数,最坏情况下为线性。另一个很好的答案是对其进行扩展,V8中的Map和Set最近在JavaScript中重新实现。这在V8中很常见,在JavaScript中实现新功能可以让JIT(曲轴/涡轮风扇)优化运行时代码。@DiegoPino:谢谢。我不知何故认为,
OrderedHashTable
实现仍然是最新的,因为我在……中找到了它,看起来实现已经从
src/collections.js
移动到了
src/builtins/builtins-collections-gen.cc,这是因为Map类是通过插入排序的。
let map = new Map();
let obj = {};

const benchMarkMapSet = size => {
console.time("benchMarkMapSet");
for (let i = 0; i < size; i++) {
    map.set(i, i);
}
console.timeEnd("benchMarkMapSet");
};

const benchMarkMapGet = size => {
console.time("benchMarkMapGet");
for (let i = 0; i < size; i++) {
    let x = map.get(i);
}
console.timeEnd("benchMarkMapGet");
};

const benchMarkObjSet = size => {
console.time("benchMarkObjSet");
for (let i = 0; i < size; i++) {
    obj[i] = i;
}
console.timeEnd("benchMarkObjSet");
};

const benchMarkObjGet = size => {
console.time("benchMarkObjGet");
for (let i = 0; i < size; i++) {
    let x = obj[i];
}
console.timeEnd("benchMarkObjGet");
};

let size = 2e6;

benchMarkMapSet(size);
benchMarkObjSet(size);
benchMarkMapGet(size);
benchMarkObjGet(size);