[Javascript] Array์˜ ๊ตฌ์กฐ (V8)

[์›๋ณธ ๋งํฌ]

์—ฌ๊ธฐ์„œ๋Š” V8์˜ ๋™์ž‘๋งŒ ์ •๋ฆฌํ•œ๋‹ค. ๋ธŒ๋ผ์šฐ์ €๋งˆ๋‹ค ๋™์ž‘๋ฐฉ์‹์ด๋‚˜ ๊ตฌ์กฐ๋Š” ํฌ๊ฒŒ ๋‹ค๋ฅด๋‹ค.

Javascript์—์„œ์˜ Array๋Š” ๋‹ค๋ฅธ ์–ธ์–ด๋“ค์˜ Array์™€ ํฌ๊ฒŒ ๋‹ค๋ฅด๋‹ค. ์ˆœ์ˆ˜ํ•œ ๋ฐฐ์—ด์ด ์•„๋‹ˆ๋ผ Object์˜ ํ•œ ์ข…๋ฅ˜๋กœ์„œ ์ทจ๊ธ‰๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์œ„์™€ ๊ฐ™์ด Object๊ฐ€ ๋”•์…”๋„ˆ๋ฆฌ ํ˜•ํƒœ๋ฉด properties์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ , ํ‚ค๊ฐ€ ์ˆซ์ž์ธ ๋ฐฐ์—ด ํ˜•ํƒœ๋ฉด elements์— ๊ฐ’์„ ์ €์žฅํ•œ๋‹ค. elements์— ๊ฐ’์ด ๋“ค์–ด์žˆ์œผ๋ฉด ์ด์ œ ๋ฐฐ์—ด์ด ๋˜๋Š” ๊ฒƒ์ด๋‹ค.




๋ฐฐ์—ด ํƒ€์ž… ์ „ํ™˜

๋ฐฐ์—ด์—๋Š” ์•„๋ฌด ํƒ€์ž…์ด๋‚˜ ๋ง‰ ๋“ค์–ด๊ฐ€๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ, ์‚ฌ์‹ค ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ๊ต‰์žฅํžˆ ๋ณต์žกํ•œ ํƒ€์ž…๊ณผ ์ƒํƒœ๋ฅผ ๋ณ€ํ™”๋ฌด์Œํ•˜๊ฒŒ ์˜ค๊ฐ„๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์ˆ˜๊ฐ’์„ ํฌํ•จํ•˜๋Š” ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•˜๋ฉด PACKED_SMI_ELEMENTS๋ผ๋Š” ๋ชจ๋“œ๋กœ ๋ฐฐ์—ด์ด ๋งŒ๋“ค์–ด์ง„๋‹ค.

const array = [1, 2, 3];
// elements kind: PACKED_SMI_ELEMENTS

SMI๋Š” ์ž‘์€ ์ •์ˆ˜๋ฅผ ๋œปํ•˜๋Š” ๋‹จ์–ด์ธ๋ฐ, ๋ณดํ†ต ์ด๊ฒŒ ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ์ตœ์ ํ™”๊ฐ€ ๋œ๋‹ค.

๋ฌผ๋ก  JS๋Š” ๋™์  ํƒ€์ž… ์–ธ์–ด๊ณ , ์–ธ์ œ๋“  ์‹ค์ˆ˜๋‚˜ ๋ฌธ์ž์—ด ๊ฐ™์€ ๊ดด์ƒ๋ง์ธกํ•œ ๊ฐ’์„ ๋„ฃ์„ ์ˆ˜๋„ ์žˆ๋‹ค.

const array = [1, 2, 3];
// elements kind: PACKED_SMI_ELEMENTS
array.push(4.56);
// elements kind: PACKED_DOUBLE_ELEMENTS
array.push('x');
// elements kind: PACKED_ELEMENTS

ํƒ€์ž…์˜ ์ผ๊ด€์„ฑ์„ ์ง€ํ‚ค์ง€ ๋ชปํ• ๋•Œ๋งˆ๋‹ค ๋” ์ผ๋ฐ˜์ ์ธ ํ˜•ํƒœ์˜ ๋ฐฐ์—ดํƒ€์ž…์œผ๋กœ ๋ณ€๊ฒฝ์ด ๋œ๋‹ค.
๋‹น์—ฐํžˆ ๋ฐ‘์œผ๋กœ ๊ฐˆ์ˆ˜๋ก ๋А๋ ค์ง„๋‹ค.

์—ฌ๊ธฐ์„œ ์œ ์˜ํ•  ์ ์€ PACKED_ELEMENTS์ฒ˜๋Ÿผ ์ผ๋ฐ˜ํ™”๋œ ํƒ€์ž…์œผ๋กœ ๋‚ด๋ ค์˜จ ๋ฐฐ์—ด์€, ๊ทธ๊ฑธ ๋‹ค์‹œ ๋นผ๋”๋ผ๋„ PACKED_SMI_ELEMENTS๋‚˜ PACKED_DOUBLE_ELEMENTS ๊ฐ™์€ ๋ณด๋‹ค ๋น ๋ฅธ ํƒ€์ž…์œผ๋กœ ๋Œ์•„์˜ค์ง€ ๋ชปํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๋˜๋„๋ก์ด๋ฉด ํƒ€์ž…์˜ ์ผ๊ด€์„ฑ์„ ์ง€์ผœ์ฃผ๋Š” ํŽธ์ด ์ข‹๋‹ค.




๊ตฌ๋ฉ ๋šซ๋ฆฐ ๋ฐฐ์—ด (HOLEY)

JS์˜ ๋ฐฐ์—ด์€ ์ผ๋ฐ˜์ ์ธ ์–ธ์–ด๋“ค์˜ ๋ฐฐ์—ด ๊ตฌํ˜„๊ณผ ๋‹ค๋ฅด๊ฒŒ, ์ธ๋ฑ์Šค๋ฅผ ๊ฑด๋„ˆ๋›ฐ์–ด์„œ ๊ฐ’์„ ํ• ๋‹นํ•˜๋Š” ์ด์ƒํ•œ ์ง“์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

const array = [1, 2, 3, 4.56, 'x'];
// elements kind: PACKED_ELEMENTS

array.length; // 5
array[9] = 1; // array[5] until array[8] are now holes
// elements kind: HOLEY_ELEMENTS

5 ์ธ๋ฑ์Šค๋ฅผ ๊ฑด๋„ˆ๋›ฐ๊ณ  9 ์ธ๋ฑ์Šค์— ๊ฐ’์„ ๋ฐ•์•˜์Œ์—๋„ ๋†€๋ž๊ฒŒ๋„ ์ž˜ ๋™์ž‘ํ•œ๋‹ค.
์ด๊ฑด ๋‚ด๋ถ€์ ์œผ๋กœ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•ด์„œ


์‹ค์ œ๋กœ ๊ธธ์ด๋„ 10์ด ๋˜์—ˆ๋‹ค. ์ค‘๊ฐ„์˜ ์š”์†Œ๋“ค์€ ๊ตฌ๋ฉ(hole)์ด ๋œ ๊ฒƒ์ด๋‹ค.
๊ตฌ๋ฉ ๋ฐฐ์—ด(holey)๊ณผ ๋น„๊ตํ•ด์„œ ๊ตฌ๋ฉ์ด ์—†๋Š” ๋ฐฐ์—ด์„ PACKED๋ผ๊ณ  ๋ถ€๋ฅด๋Š”๋ฐ, ๋‹น์—ฐํžˆ PACKED ๋ฐฐ์—ด์ด ์ตœ์ ํ™”๊ฐ€ ํ›จ์”ฌ ์ž˜ ๋œ๋‹ค.

์•„๋ž˜๋Š” ๋ฐฐ์—ด ํƒ€์ž…์ด ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋Š” ๋ฃจํŠธ๋ฅผ ๊ทธ๋ฆผ์œผ๋กœ ํ‘œํ˜„ํ•œ ๊ฒƒ์ด๋‹ค.

์ง€๋‚˜์˜จ ๊ธธ์€ ๋Œ์•„์˜ฌ ์ˆ˜ ์—†๋‹ค.




๋ฐฐ์—ด์ฒ˜๋Ÿผ ์ƒ๊ธด ๊ฐ์ฒด

Javascript์—์„œ๋Š” ์• ์ดˆ์— ๋ฐฐ์—ด๊ณผ ๊ฐ์ฒด์˜ ๊ฒฝ๊ณ„๊ฐ€ ํ๋ฆฟํ•˜๋‹ค๋ณด๋‹ˆ ๊ฐ์ฒด๋กœ ์ดˆ๊ธฐํ™”ํ•ด์„œ ๋ฐฐ์—ด์ฒ˜๋Ÿผ ์“ธ ์ˆ˜๋„ ์žˆ๋‹ค.

const arrayLike = {};
arrayLike[0] = 'a';
arrayLike[1] = 'b';
arrayLike[2] = 'c';
arrayLike // { '0': 'a', '1': 'b', '2': 'c' }

์ด๊ฑด ์„ฑ๋Šฅ์ƒ ๋ณ„๋กœ ์ข‹์€ ์‚ฌ์šฉ๋ฒ•์€ ์•„๋‹ˆ๋‹ค. ๋” ๋А๋ฆฐ Object ํ˜•ํƒœ๋กœ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
์ฐจ๋ผ๋ฆฌ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.




์กด์žฌํ•˜์ง€ ์•Š๋Š” ์š”์†Œ ์ ‘๊ทผํ•˜์ง€ ๋ง๊ธฐ

JS๋Š” ์—„.๊ฒฉ.ํ•œ ๋‹ค๋ฅธ ์–ธ์–ด๋“ค๊ณผ ๋‹ค๋ฅด๊ฒŒ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์š”์†Œ์— ์ ‘๊ทผํ•ด๋„ out of range ์˜ค๋ฅ˜๋ฅผ ๋ฑ‰์ง€ ์•Š๋Š”๋‹ค.

undefined๊ฐ€ ๋–จ์–ด์งˆ ๋ฟ์ด๋‹ค.

์ด๊ฒƒ๋„ ์˜์™ธ๋กœ ์„ฑ๋Šฅ์ƒ ์•…์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์ด๋‹ค.
๋‚ด๋ถ€์ ์œผ๋กœ properties๊นŒ์ง€ ์ฐธ์กฐํ•ด์„œ ์ €๊ฒŒ ์žˆ๋Š”์ง€ ์—†๋Š”์ง€๋ฅผ ๊ฒ€์‚ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋ผ๊ณ  ํ•œ๋‹ค. ์‹ฌ์ง€์–ด ์ € ์˜ํ–ฅ์€ ํœ˜๋ฐœ์ ์ธ๊ฒƒ๋„ ์•„๋‹ˆ๋‹ค.
V8์€ ์ € ๋ฐฐ์—ด์— ๋Œ€ํ•ด์„œ ํŠน์ˆ˜ํ•œ ์ ‘๊ทผ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜๊ณ  ๋ญ”๊ฐ€ ๋” ๋А๋ฆฐ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์ € ๋ฐฐ์—ด ์ž์ฒด์— ๋Œ€ํ•œ ์ ‘๊ทผ ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง„๋‹ค.

๋Œ€ํ‘œ์ ์œผ๋กœ ์ œ์ด์ฟผ๋ฆฌ๊ฐ€ ์ด๋Ÿฐ ์•ˆํ‹ฐํŒจํ„ด์„ ์จ์„œ

// Donโ€™t do this!
for (let i = 0, item; (item = items[i]) != null; i++) {
  doSomething(item);
}

์„ฑ๋Šฅ์ด ๋А๋ฆฐ ๋ถ€๋ถ„์ด ์žˆ์—ˆ๋‹ค๊ณ  ํ•œ๋‹ค. ์ €๋Ÿฌ์ง€๋Š” ๋ง์ž.




Array() ํ•จ์ˆ˜๋กœ ๋ฐฐ์—ด ์ƒ์„ฑ

์ด๊ฑด ์ด๊ฒฌ์ด ์ข€ ๊ฐˆ๋ฆด ์ˆ˜๋„ ์žˆ๋Š” ๋ถ€๋ถ„์ด๋‹ค.
Array ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋Š” ๋ฐฐ์—ด์˜ ๊ธธ์ด๋ฅผ ๋ฐ›์•„์„œ ํ•ด๋‹น ๊ธธ์ด์˜ ๋นˆ ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๊ฑด push๋ฅผ ๋ฐ˜๋ณตํ• ๋•Œ ์ƒ๊ธฐ๋Š” ์ƒ๊ธฐ๋Š” growing ์ž‘์—…์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ํ• ๋‹น ์„ฑ๋Šฅ์ด ์ข€๋” ๋‚ซ๊ณ  ์‚ฌ์ด์ฆˆ๋„ ๋”ฑ ์Šฌ๋ฆผํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ง„๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.
ํ•˜์ง€๋งŒ ์ด ์ƒ์„ฑ ๋ฐฉ์‹์€ ๋ฐฐ์—ด์„ PACKED๊ฐ€ ์•„๋‹ˆ๋ผ HOLEY ๋ฐฐ์—ด๋กœ ์ƒ์„ฑํ•œ๋‹ค๋Š” ๋‹จ์ ๋„ ๋™์‹œ์— ์กด์žฌํ•œ๋‹ค. ๊ณต๊ฐ„์„ ์•„๋ผ๊ธฐ ์œ„ํ•ด์„œ์ธ ๊ฒƒ ๊ฐ™๋‹ค.

ํ•˜์ง€๋งŒ V8 ๊ฐœ๋ฐœ์ž์ธ jmrk์˜ ์˜๊ฒฌ์— ๋”ฐ๋ฅด๋ฉด ์–ด์ฐจํ”ผ packed์™€ holey์˜ ์„ฑ๋Šฅ ์ฐจ์ด๋Š” ๊ฑฐ์˜ ๋А๋ผ๊ธฐ๊ฐ€ ์–ด๋ ต๊ณ , push๋ฅผ ๋ฐ˜๋ณตํ•˜๋ฉด์„œ ์ฆ๊ฐ€์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์„ฑ๋Šฅ ๋ถ€ํ•˜๊ฐ€ ํ›จ์”ฌ ์ปค์„œ ๊ทธ๋ƒฅ ์ƒ์„ฑ ํ•จ์ˆ˜๋ฅผ ์“ฐ๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.



์ฐธ์กฐ
https://v8.dev/blog/fast-properties?m=1
https://v8.dev/blog/elements-kinds
https://stackoverflow.com/questions/54481918/how-does-v8-optimise-the-creation-of-very-large-arrays