Javascript ES6 계산 / 시간 복잡성


84

Keyed Collections (Set, Map, WeakSet 및 WeakMap)에 대한 ES6 사양에서 제공하는 시간 복잡성 (big-O 표기법)은 무엇입니까?

내 기대, 나는 대부분의 개발자로, 사양 및 구현을 사용하는 것입니다 것으로 예상 널리 인정 되는 경우에 성능이 좋은 알고리즘 Set.prototype.has, add그리고 delete평균 경우 모든 수 O (1)로한다. MapWeak–등가물에 대해서도 동일합니다 .

예를 들어 ECMAScript 2015 언어 사양-6th Edition — 23.2 Set Objects 에서 구현의 시간 복잡성이 의무화되었는지 여부는 나에게 완전히 분명하지 않습니다 .

내가 그것을 오해하지 않는 한 (그리고 확실히 내가 할 가능성이 매우 높다) ECMA 사양은 구현 (예 : Set.prototype.has선형 시간 ( O (n) )) 알고리즘 을 사용 하도록 요구합니다 . 더 많은 성능의 알고리즘이 사양에 의해 의무화되거나 허용되지 않는다는 것이 놀랍게도 놀라 울 것이며, 이것이 왜 그런지에 대한 설명에 매우 관심이있을 것입니다.


2
모든 O (1) 알고리즘도 O (n) 이므로 사양에서 성능이 떨어지는 구현으로도 해를 끼치 지 않습니다. 성능이 떨어지는 구현은 리소스가 제한된 시스템에서 어느 정도 관심을 가질 수 있습니다. 대부분의 경우 훨씬 적은 코드 / 공간이 필요하기 때문입니다.
artur grzesiak 2015-06-27

@arturgrzesiak 키순 컬렉션의 O (1) 성능은 일반적으로 O (1) 해시와 O (n) 충돌 버킷을 사용하여 달성됩니다. O (n) 최악의 경우는 가장 실용적인 목적을위한 천문학적으로 드뭅니다. 이러한 기술의 공간 복잡성은 일반적으로 O (n)입니다.
Brian M. Hunt

1
"집합 개체는 해시 테이블 또는 평균적으로 컬렉션의 요소 수에 따라 하위 선형 인 액세스 시간을 제공하는 기타 메커니즘을 사용하여 구현되어야합니다."-바로 그 페이지에서.
georg

답변:


59

링크 된 바로 그 단락 에서 바로 :

집합 개체는 평균적으로 컬렉션의 요소 수에 하위 선형 인 액세스 시간을 제공하는 [메커니즘]을 사용하여 구현되어야합니다.

Maps , WeakMapsWeakSets에 대해 동일한 문장을 찾을 수 있습니다.

ECMA 사양은 구현 (예 : Set.prototype.has)이 선형 시간 ( O(n)) 알고리즘 을 사용하도록 요구합니다 .

아니:

Set객체 사양에 사용 된 데이터 구조 는 Set 객체의 필수 관찰 가능한 의미를 설명하기위한 것입니다. 실행 가능한 구현 모델이 아닙니다.

관찰 가능한 의미 체계는 대부분 예측 가능한 반복 순서와 관련이 있습니다 (여전히 효율적이고 빠르게 구현할 수 있음 ). 구현이 해시 테이블 또는 일정한 액세스와 유사한 것을 사용하는 것은 실제로 사양에 의해 예상되지만 트리 (로그 액세스 복잡성 포함)도 허용됩니다.


2
선택해 주셔서 감사합니다. 내가 그 문단에 도달했을 때쯤에는 내 눈이 반짝 거 렸나 봐요. :) 그래서 O (log (n)) 또는 O (1) 중 하나 인 알고리즘이지만 그렇지 않은 경우 (O (n) 아래에있는 경우) 의무화되지 않은 것입니까?
Brian M. Hunt

1
@ BrianM.Hunt : 맞습니다.
Bergi

31

궁금한 사람을 위해 매우 빠른 벤치 마크를 수행했습니다.

const benchmarkMap = size => {
  console.time('benchmarkMap');
  var map = new Map();
  for (var i = 0; i < size; i++) map.set(i, i);
  for (var i = 0; i < size; i++) var x = map.get(i);
  console.timeEnd('benchmarkMap');
}

const benchmarkObj = size => {
  console.time('benchmarkObj');
  var obj = {};
  for (var i = 0; i < size; i++) obj[i] = i;
  for (var i = 0; i < size; i++) var x = obj[i];
  console.timeEnd('benchmarkObj');
}

var size = 1000000;

benchmarkMap(size);
benchmarkObj(size);

나는 이것을 몇 번 실행하고 다음과 같은 결과를 얻었습니다.

(2017 MacBook Pro, 2.5GHz i7 및 16G RAM)

benchmarkMap: 189.120ms
benchmarkObj: 44.214ms

benchmarkMap: 200.817ms
benchmarkObj: 38.963ms

benchmarkMap: 187.968ms
benchmarkObj: 41.633ms

benchmarkMap: 186.533ms
benchmarkObj: 35.850ms

benchmarkMap: 187.339ms
benchmarkObj: 44.515ms

3
@domdambrogia 당신이 얻는 것과 설정을 분리하면 : Map Set = 124, Map Get = 40, Object Set = 26, Object Get = 1 (ms가 아닌 비율)
AJP

@AJP 나는 생각하지 않았고, 그 통계로도 분해했습니다. 귀하의 의견에 감사드립니다. 그것은 좋은 기여입니다. 잠시 시간이있을 때 대답에 추가 할 수 있는지 살펴 보겠습니다. 감사!
domdambrogia 19 년

과제를 읽기와 분리하여 둘 중 어느 것이 읽기에 더 빠른지 배우는 것도 흥미로울 것입니다.
fernandopasik

3
" 2017 MacBook Pro, 2.5GHz i7 (16G RAM 포함) "-어, 멋지네요 .하지만 어떤 자바 스크립트 엔진 을 벤치마킹 했나요?
Bergi

1
흥미롭게도 추가 delete작업과 작업이 혼합되면 Map성능이 훨씬 더 좋아집니다. jsfiddle.net/23hrp0eq
Jorjon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.