- Published on
- ·11 min read
JavaScript - 배열 생성 방법 4가지, 성능 비교
이 글은 이전 블로그에서 2023년 3월 2일 작성한 내용을 옮겨오면서 내용을 추가/수정한 글입니다.
개요
JavaScript에서 범위를 지정하여 배열을 생성이 필요했습니다.
범위가 작으면 어떤 방법을 사용해도 차이가 크지 않지만, 제 경우 50000000(5천만) 이상의 범위를 지정하니 성능 차이가 꽤 났습니다.
그런 이유로 몇 가지 방법을 시도해보고 성능을 비교해보았습니다.
테스트한 방법은 4가지로, 4가지 방법 및 결과
1
~ 50,000,000
범위의 배열 생성 속도 측정 결과입니다.빈 배열 생성 후, push (
2위
, 대략 0.5초 정도)원하는 범위의 배열 생성 후, 인덱스로 접근해 값 변경 (
3위
, 대략 1.7초 정도)Array.from 사용 (
4위
, 대략 3.5초 정도)ArrayBuffer(Uint32Array) 사용 (
1위
, 대략 0.1초 정도)
테스트 방법 4가지는 아래와 같습니다.
1. 빈 배열 생성 후, push
function generateNumberPush(min, max) {
let arr = []
for (let i = min; i <= max; i++) {
arr.push(i)
}
return arr
}
- 속도 2위 (대략 0.5초 정도 소요)
- 아주 큰 범위가 아니면 제일 무난한 방법으로 판단됩니다.
[ ]
대신new Array()
를 사용해도 됩니다. 다만, 테스트해 보니[ ]
이 약간 더 빨랐습니다. (이유는 아직 찾지 못했습니다.ㅠㅠ)
2. 원하는 범위의 배열 생성 후, 인덱스로 접근해 값 변경
function generateNumberIndex(min, max) {
let range = max - min + 1
let arr = new Array(range)
for (let i = 0; i < arr.length; i++) {
arr[i] = i + min
}
return arr
}
- 속도 3위 (대략 1.7초 정도 소요)
- 밀집성이 보장되지 않은 JavaScript 배열에서 인덱스로 위치를 찾는 시간이 소요되는 것으로 파악됩니다.
- 아래에 MDN 문서의 Array 설명을 인용해 봅니다.
JavaScript 배열은 길이도, 각 요소의 자료형도 고정되어 있지 않습니다. 배열의 길이가 언제든지 늘어나거나 줄어들 수 있고 데이터를 연속적이지 않은 곳에 저장할 수 있으므로, JavaScript 배열은 밀집성을 보장하지 않습니다. 보통 이런 성질들은 편리하지만, 사용하려는 목적에 맞지 않으면 형식화 배열(typed array)을 사용하는 것을 고려해보세요.
3. Array.from 사용
function generateNumberFrom(min, max) {
let range = max - min + 1
let arr = Array.from({ length: range }, (v, i) => i + min)
return arr
}
- 속도 4위 (대략 3.5초 정도 소요)
- 작은 범위의 배열을 생성한다면, 코드가 간결해지는 것이 장점이 될 듯합니다.
4. ArrayBuffer(Uint32Array) 사용
function generateNumberBuffer(min, max) {
let range = max - min + 1
let buffer = new ArrayBuffer(range * Uint32Array.BYTES_PER_ELEMENT)
let arr = new Uint32Array(buffer)
for (let i = 0; i < arr.length; i++) {
arr[i] = i + min
}
return arr
}
- 속도 1위 (대략 0.1초 정도 소요)
- 배열 생성 후 배열 접근에서도 압도적 1위
(console.log로 생성된 배열을 표시할 경우, Array를 사용한 다른 방법들은 한참 걸립니다. Array의 경우 밀집성이 보장되지 않은 JavaScript라서 각 인덱스를 찾아 표시하는데도 시간이 걸리는 것으로 파악됩니다.) - ArrayBuffer에 대한 더 자세한 소개는 만화로 소개하는 ArrayBuffer 와 SharedArrayBuffer(번역글로, 원글은 A cartoon intro to ArrayBuffers and SharedArrayBuffers)글을 참고 바랍니다.
- 해당 글 중 ArrayBuffer가 빠른 이유를 설명하는 부분을 아래에 인용하겠습니다.
ArrayBuffer 는 기본적으로 메모리 자체인 것처럼 동작합니다. ArrayBuffer 는 C 같은 랭귀지를 사용할 때처럼 메모리를 직접 다루는 방식과 비슷한 효과를 만들어 냅니다.
성능 테스트 코드
아래는 위 방법들을 테스트한 코드입니다.
- 함수 선언
function generateNumberPush(min, max) {
let startTime = new Date().getTime()
console.log(`1. 빈 배열 생성 후, push -- startTime:${startTime}`)
// logic ----------------------------------
let arr = []
for (let i = min; i <= max; i++) {
arr.push(i)
}
// logic ----------------------------------
let endTime = new Date().getTime()
let duration = (endTime - startTime) / 1000
console.log(`1. 빈 배열 생성 후, push -- endTime:${endTime}`)
console.log(
`1. 빈 배열 생성 후, push 결과 -- duration:${duration}, length:${arr.length}, first:${
arr[0]
}, last:${arr[arr.length - 1]}`
)
console.log('----------------------------------')
return arr
}
function generateNumberIndex(min, max) {
let startTime = new Date().getTime()
console.log(`2. 원하는 범위의 배열 생성 후, 인덱스로 접근해 값 변경 -- startTime:${startTime}`)
// logic ----------------------------------
let range = max - min + 1
let arr = new Array(range)
for (let i = 0; i < arr.length; i++) {
arr[i] = i + min
}
// logic ----------------------------------
let endTime = new Date().getTime()
let duration = (endTime - startTime) / 1000
console.log(`2. 원하는 범위의 배열 생성 후, 인덱스로 접근해 값 변경 -- endTime:${endTime}`)
console.log(
`2. 원하는 범위의 배열 생성 후, 인덱스로 접근해 값 변경 결과 -- duration:${duration}, length:${
arr.length
}, first:${arr[0]}, last:${arr[arr.length - 1]}`
)
console.log('----------------------------------')
return arr
}
function generateNumberFrom(min, max) {
let startTime = new Date().getTime()
console.log(`3. Array.from 사용 -- startTime:${startTime}`)
// logic ----------------------------------
let range = max - min + 1
let arr = Array.from({ length: range }, (v, i) => i + min)
// logic ----------------------------------
let endTime = new Date().getTime()
let duration = (endTime - startTime) / 1000
console.log(`3. Array.from 사용 -- endTime:${endTime}`)
console.log(
`3. Array.from 사용 결과 -- duration:${duration}, length:${arr.length}, first:${arr[0]}, last:${
arr[arr.length - 1]
}`
)
console.log('----------------------------------')
return arr
}
function generateNumberBuffer(min, max) {
let startTime = new Date().getTime()
console.log(`4. ArrayBuffer(Uint32Array) 사용 -- startTime:${startTime}`)
// logic ----------------------------------
let range = max - min + 1
let buffer = new ArrayBuffer(range * Uint32Array.BYTES_PER_ELEMENT)
let arr = new Uint32Array(buffer)
for (let i = 0; i < arr.length; i++) {
arr[i] = i + min
}
// logic ----------------------------------
let endTime = new Date().getTime()
let duration = (endTime - startTime) / 1000
console.log(`4. ArrayBuffer(Uint32Array) 사용 -- endTime:${endTime}`)
console.log(
`4. ArrayBuffer(Uint32Array) 사용 결과 -- duration:${duration}, length:${arr.length}, first:${
arr[0]
}, last:${arr[arr.length - 1]}`
)
return arr
}
function test(min, max) {
generateNumberPush(min, max)
generateNumberIndex(min, max)
generateNumberFrom(min, max)
generateNumberBuffer(min, max)
}
콘솔에 위 함수들을 선언한 코드를 붙여넣고 아래와 같이 실행하면 다음과 유사한 결과를 얻을 수 있습니다.
- 실행
// run ------------------------------
test(1, 50000000)
// run ------------------------------
- 결과
1. 빈 배열 생성 후, push -- startTime:1692335226507
1. 빈 배열 생성 후, push -- endTime:1692335226829
1. 빈 배열 생성 후, push 결과 -- duration:0.322, length:50000000, first:1, last:50000000
----------------------------------
2. 원하는 범위의 배열 생성 후, 인덱스로 접근해 값 변경 -- startTime:1692335226830
2. 원하는 범위의 배열 생성 후, 인덱스로 접근해 값 변경 -- endTime:1692335228118
2. 원하는 범위의 배열 생성 후, 인덱스로 접근해 값 변경 결과 -- duration:1.288, length:50000000, first:1, last:50000000
----------------------------------
3. Array.from 사용 -- startTime:1692335228118
3. Array.from 사용 -- endTime:1692335231499
3. Array.from 사용 결과 -- duration:3.381, length:50000000, first:1, last:50000000
----------------------------------
4. ArrayBuffer(Uint32Array) 사용 -- startTime:1692335231499
4. ArrayBuffer(Uint32Array) 사용 -- endTime:1692335231608
4. ArrayBuffer(Uint32Array) 사용 결과 -- duration:0.109, length:50000000, first:1, last:50000000
태그와 연관된 글
2023. 11. 30.
서버리스 API, Cloudflare Workers로 json 데이터 제공하기2023. 09. 11.
JavaScript - 중복 배열에서 특정 값을 검색하여 첫 번째 일치 값만 제거2023. 09. 05.
JavaScript - 0 채우기 (zero fill), 3가지 방법 정리