JavaScript에서 배열 대 객체 효율성
수천 개의 객체가있는 모델이 있습니다. ID가 있으면 저장하고 단일 객체를 검색하는 가장 효율적인 방법이 무엇인지 궁금합니다. ID는 긴 숫자입니다.
이것이 제가 생각한 두 가지 옵션입니다. 옵션 1에서는 증가하는 인덱스가있는 간단한 배열입니다. 옵션 2에서 그것은 연관 배열이며 아마도 차이가 있다면 객체 일 것입니다. 내 질문은 주로 단일 객체를 검색해야하지만 때로는 반복하여 정렬해야 할 때 어느 것이 더 효율적인지입니다.
비 연관 배열이있는 옵션 1 :
var a = [{id: 29938, name: 'name1'},
{id: 32994, name: 'name1'}];
function getObject(id) {
for (var i=0; i < a.length; i++) {
if (a[i].id == id)
return a[i];
}
}
연관 배열이있는 옵션 2 :
var a = []; // maybe {} makes a difference?
a[29938] = {id: 29938, name: 'name1'};
a[32994] = {id: 32994, name: 'name1'};
function getObject(id) {
return a[id];
}
최신 정보:
좋아, 두 번째 옵션에서 배열을 사용하는 것은 의문의 여지가 없습니다. 따라서 두 번째 옵션의 선언 줄은 실제로 다음 var a = {};
과 같아야합니다. 단지 질문은 주어진 ID를 가진 객체를 검색 할 때 더 나은 성능을 나타내는 것입니다 : 배열 또는 id가 키인 객체.
또한 목록을 여러 번 정렬 해야하는 경우 답변이 변경됩니까?
짧은 버전 : 배열은 대부분 객체보다 빠릅니다. 그러나 100 % 올바른 해결책은 없습니다.
2017 업데이트-테스트 및 결과
var a1 = [{id: 29938, name: 'name1'}, {id: 32994, name: 'name1'}];
var a2 = [];
a2[29938] = {id: 29938, name: 'name1'};
a2[32994] = {id: 32994, name: 'name1'};
var o = {};
o['29938'] = {id: 29938, name: 'name1'};
o['32994'] = {id: 32994, name: 'name1'};
for (var f = 0; f < 2000; f++) {
var newNo = Math.floor(Math.random()*60000+10000);
if (!o[newNo.toString()]) o[newNo.toString()] = {id: newNo, name: 'test'};
if (!a2[newNo]) a2[newNo] = {id: newNo, name: 'test' };
a1.push({id: newNo, name: 'test'});
}
원본 게시물-설명
귀하의 질문에 약간의 오해가 있습니다.
Javascript에는 연관 배열이 없습니다. 배열과 객체 만.
이들은 배열입니다 :
var a1 = [1, 2, 3];
var a2 = ["a", "b", "c"];
var a3 = [];
a3[0] = "a";
a3[1] = "b";
a3[2] = "c";
이것은 또한 배열입니다.
var a3 = [];
a3[29938] = "a";
a3[32994] = "b";
모든 배열에는 지속적인 인덱싱이 있기 때문에 기본적으로 구멍이있는 배열입니다. 구멍이없는 어레이보다 느립니다. 그러나 배열을 수동으로 반복하는 것이 훨씬 느립니다 (대부분).
이것은 객체입니다.
var a3 = {};
a3[29938] = "a";
a3[32994] = "b";
다음은 세 가지 가능성에 대한 성능 테스트입니다.
조회 배열 대 홀리 배열 대 개체 성능 테스트
Smashing Magazine에서 이러한 주제에 대한 훌륭한 자료 : 빠른 메모리 효율적인 JavaScript 작성
배열과 객체는 매우 다르게 작동하거나 (적어도 예상해야 함) 실제로 성능 문제는 아닙니다. 0..n
객체는 임의의 키를 임의의 값으로 매핑하는 반면, 배열에는 연속적인 인덱스가 있습니다. 경우 당신이 특정 키를 제공 할 수있는 유일한 선택은 개체입니다. 키에 신경 쓰지 않으면 배열입니다.
배열에서 임의의 (숫자) 키를 설정하려고하면 실제로 성능 손실이 발생합니다 . 행동 적으로 배열은 그 사이의 모든 인덱스를 채 웁니다.
> foo = [];
[]
> foo[100] = 'a';
"a"
> foo
[undefined, undefined, undefined, ..., "a"]
(배열에는 실제로 99 개의 undefined
값 이 포함되어 있지 않지만 어느 시점에서 배열을 반복 하기 때문에 이런 식으로 작동합니다 .)
두 옵션의 리터럴은 사용 방법을 매우 명확하게해야합니다.
var arr = ['foo', 'bar', 'baz']; // no keys, not even the option for it
var obj = { foo : 'bar', baz : 42 }; // associative by its very nature
ES6에서 가장 성능이 좋은 방법은 맵을 사용하는 것입니다.
var myMap = new Map();
myMap.set(1, 'myVal');
myMap.set(2, { catName: 'Meow', age: 3 });
myMap.get(1);
myMap.get(2);
오늘 shim ( https://github.com/es-shims/es6-shim )을 사용하여 ES6 기능을 사용할 수 있습니다 .
성능은 브라우저 및 시나리오에 따라 다릅니다. 그러나 Map
가장 성능이 좋은 예 는 다음과 같습니다. https://jsperf.com/es6-map-vs-object-properties/2
참조 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map
에서 NodeJS 당신이 알고있는 경우 ID
는 배열을 통해 루프가 매우 느린 비교됩니다 object[ID]
.
const uniqueString = require('unique-string');
const obj = {};
const arr = [];
var seeking;
//create data
for(var i=0;i<1000000;i++){
var getUnique = `${uniqueString()}`;
if(i===888555) seeking = getUnique;
arr.push(getUnique);
obj[getUnique] = true;
}
//retrieve item from array
console.time('arrTimer');
for(var x=0;x<arr.length;x++){
if(arr[x]===seeking){
console.log('Array result:');
console.timeEnd('arrTimer');
break;
}
}
//retrieve item from object
console.time('objTimer');
var hasKey = !!obj[seeking];
console.log('Object result:');
console.timeEnd('objTimer');
그리고 결과 :
Array result:
arrTimer: 12.857ms
Object result:
objTimer: 0.051ms
탐색 ID가 배열 / 객체의 첫 번째 ID 인 경우에도 :
Array result:
arrTimer: 2.975ms
Object result:
objTimer: 0.068ms
나는 이것을 문자 그대로 다음 차원으로 가져 가려고 노력했다.
x 축과 y 축의 길이가 항상 같은 2 차원 배열을 사용하면 다음과 같이하는 것이 더 빠릅니다.
a) 2 차원 배열을 만들고 첫 번째 인덱스를 찾은 다음 두 번째 인덱스를 찾아서 셀을 찾습니다.
var arr=[][]
var cell=[x][y]
또는
b) x 및 y 좌표의 문자열 표현으로 객체를 생성 한 다음 해당 객체에 대해 단일 조회를 수행합니다.
var obj={}
var cell = obj['x,y']
결과 :
객체에서 하나의 속성 조회보다 배열에서 두 개의 숫자 인덱스 조회를 수행하는 것이 훨씬 빠르다는 것이 밝혀졌습니다.
결과는 다음과 같습니다.
http://jsperf.com/arr-vs-obj-lookup-2
사용법에 따라 다릅니다. 케이스가 조회 오브젝트 인 경우 매우 빠릅니다.
다음은 배열 및 객체 조회 성능을 테스트하는 Plunker 예제입니다.
https://plnkr.co/edit/n2expPWVmsdR3zmXvX4C?p=preview
당신은 그것을 볼 것입니다; 5.000 길이 배열 컬렉션 에서 5.000 개의 항목을 찾고 , milisecon 을 인수3000
그러나 대한 찾고 5.000 객체의 항목은이 5.000 속성을 가지고에만 2
또는 3
milisecons을
또한 객체 트리를 만드는 것은 큰 차이를 만들지 않습니다.
I had a similar problem that I am facing where I need to store live candlesticks from an event source limited to x items. I could have them stored in an object where the timestamp of each candle would act as the key and the candle itself would act as the value. Another possibility was that I could store it in an array where each item was the candle itself. One problem about live candles is that they keep sending updates on the same timestamp where the latest update holds the most recent data therefore you either update an existing item or add a new one. So here is a nice benchmark that attempts to combine all 3 possibilities. Arrays in the solution below are atleast 4x faster on average. Feel free to play
"use strict";
const EventEmitter = require("events");
let candleEmitter = new EventEmitter();
//Change this to set how fast the setInterval should run
const frequency = 1;
setInterval(() => {
// Take the current timestamp and round it down to the nearest second
let time = Math.floor(Date.now() / 1000) * 1000;
let open = Math.random();
let high = Math.random();
let low = Math.random();
let close = Math.random();
let baseVolume = Math.random();
let quoteVolume = Math.random();
//Clear the console everytime before printing fresh values
console.clear()
candleEmitter.emit("candle", {
symbol: "ABC:DEF",
time: time,
open: open,
high: high,
low: low,
close: close,
baseVolume: baseVolume,
quoteVolume: quoteVolume
});
}, frequency)
// Test 1 would involve storing the candle in an object
candleEmitter.on('candle', storeAsObject)
// Test 2 would involve storing the candle in an array
candleEmitter.on('candle', storeAsArray)
//Container for the object version of candles
let objectOhlc = {}
//Container for the array version of candles
let arrayOhlc = {}
//Store a max 30 candles and delete older ones
let limit = 30
function storeAsObject(candle) {
//measure the start time in nanoseconds
const hrtime1 = process.hrtime()
const start = hrtime1[0] * 1e9 + hrtime1[1]
const { symbol, time } = candle;
// Create the object structure to store the current symbol
if (typeof objectOhlc[symbol] === 'undefined') objectOhlc[symbol] = {}
// The timestamp of the latest candle is used as key with the pair to store this symbol
objectOhlc[symbol][time] = candle;
// Remove entries if we exceed the limit
const keys = Object.keys(objectOhlc[symbol]);
if (keys.length > limit) {
for (let i = 0; i < (keys.length - limit); i++) {
delete objectOhlc[symbol][keys[i]];
}
}
//measure the end time in nano seocnds
const hrtime2 = process.hrtime()
const end = hrtime2[0] * 1e9 + hrtime2[1]
console.log("Storing as objects", end - start, Object.keys(objectOhlc[symbol]).length)
}
function storeAsArray(candle) {
//measure the start time in nanoseconds
const hrtime1 = process.hrtime()
const start = hrtime1[0] * 1e9 + hrtime1[1]
const { symbol, time } = candle;
if (typeof arrayOhlc[symbol] === 'undefined') arrayOhlc[symbol] = []
//Get the bunch of candles currently stored
const candles = arrayOhlc[symbol];
//Get the last candle if available
const lastCandle = candles[candles.length - 1] || {};
// Add a new entry for the newly arrived candle if it has a different timestamp from the latest one we storeds
if (time !== lastCandle.time) {
candles.push(candle);
}
//If our newly arrived candle has the same timestamp as the last stored candle, update the last stored candle
else {
candles[candles.length - 1] = candle
}
if (candles.length > limit) {
candles.splice(0, candles.length - limit);
}
//measure the end time in nano seocnds
const hrtime2 = process.hrtime()
const end = hrtime2[0] * 1e9 + hrtime2[1]
console.log("Storing as array", end - start, arrayOhlc[symbol].length)
}
Conclusion 10 is the limit here
Storing as objects 4183 nanoseconds 10
Storing as array 373 nanoseconds 10
정렬 된 배열이있는 경우 이진 검색을 수행 할 수 있으며 객체 검색보다 훨씬 빠릅니다. 여기에서 내 대답을 볼 수 있습니다 :
Javascript를 사용하여 정렬 된 배열에서 더 빠르게 검색하는 방법
참고 URL : https://stackoverflow.com/questions/17295056/array-vs-object-efficiency-in-javascript
'Programing' 카테고리의 다른 글
HTML에서 메타 및 링크 태그를 닫아야합니까? (0) | 2020.07.10 |
---|---|
개정을위한 데이터베이스 설계? (0) | 2020.07.10 |
줄 바꿈과 일치-\ n 또는 \ r \ n? (0) | 2020.07.10 |
전자 메일 HTML 코드를 만들기 위해 CSS 스타일을 자동으로 인라인하는 도구는 무엇입니까? (0) | 2020.07.10 |
Visual Studio에서 .NET 4.5.2를 대상 프레임 워크로 선택하는 방법 (0) | 2020.07.10 |