Logo
Hyunsu Blog

๐Ÿ“†Published :Mar 29, 2024 โ€ข

๐Ÿ“†Updated :Mar 29, 2024 โ€ข

โ˜•๏ธ2min

๊ธฐ๋ณธํ˜• ๋ฐ์ดํ„ฐ์™€ ์ฐธ์กฐํ˜• ๋ฐ์ดํ„ฐ๋ฅผ ์•Œ์•„์•ผ ํ•˜๋Š” ์ด์œ  2. ๋ถ€์ œ JS๋Š” ๊ธฐ๋ณธํ˜•,์ฐธ์กฐํ˜• ๋ชจ๋‘ ํž™์— ํ• ๋‹น๋œ๋‹ค.

๋“ค์–ด๊ฐ€๋ฉด์„œ

์ด ๊ธ€์€ 1ํŽธ '๊ธฐ๋ณธํ˜• ๋ฐ์ดํ„ฐ์™€ ์ฐธ์กฐํ˜• ๋ฐ์ดํ„ฐ๋ฅผ ์•Œ์•„์•ผ ํ•˜๋Š” ์ด์œ '์— ๋Œ€ํ•œ ํ›„์†ํŽธ์ž…๋‹ˆ๋‹ค.

Java๋‚˜ C, C++ ์–ธ์–ด์—์„œ๋Š” ๊ธฐ๋ณธํ˜•์€ ์Šคํƒ์—, ์ฐธ์กฐํ˜•์€ ํž™์— ๋“ค์–ด๊ฐ„๋‹ค๊ณ  ์•Œ๊ณ  ์žˆ๊ณ , JS ๋˜ํ•œ ๊ธฐ๋ณธํ˜•์€ ์Šคํƒ, ์ฐธ์กฐํ˜•์€ ํž™์— ํ• ๋‹น๋œ๋‹ค๊ณ  ์ฃผ์žฅํ•˜๋Š” ๊ธ€๋“ค์ด ๋งŽ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ์•Œ๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ JS๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๊ธฐ๋ณธํ˜•, ์ฐธ์กฐํ˜• ๋ชจ๋‘ ํž™์— ํ• ๋‹น๋˜๋Š”๋ฐ, ์ •์žฌํ˜• ๋‹˜์˜ '์ฝ”์–ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ' ์ฑ…์—์„œ๋„ "์—„๋ฐ€ํžˆ ๋”ฐ์ง€๋ฉด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ํƒ€์ž…์€ ์ฐธ์กฐํ˜• ๋ฐ์ดํ„ฐ์ผ ์ˆ˜๋ฐ–์— ์—†๋‹ค."๋ผ๋Š” ๋ถ€๋ถ„์ด ์–ธ๊ธ‰๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” JavaScript์—์„œ ๊ธฐ๋ณธ ๊ฐ’์ด ์Šคํƒ์— ํ• ๋‹น๋˜๊ณ  ๊ฐ์ฒด๋Š” ํž™์— ํ• ๋‹น๋œ๋‹ค๊ณ  ํ•˜๋Š” ์ฃผ์žฅ์ด ์‚ฌ์‹ค์ด ์•„๋‹ˆ๋ฉฐ, ์ด์— ๋Œ€ํ•ด ๋ฆฌ์„œ์น˜ํ•œ ๊ฒƒ๋“ค์„ ์ •๋ฆฌํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

์ด ๊ธ€์˜ ์ƒ๋‹น์ˆ˜๋Š” ๊ฑฐ์˜ https://www.zhenghao.io/posts/javascript-memory ์™€ https://www.youtube.com/watch?v=OG_AZnPokGw&t=510s์„ ์ฐธ๊ณ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์Šคํƒ ๋ฉ”๋ชจ๋ฆฌ์™€ ํž™ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง์ ‘ ํ™•์ธํ•ด๋ณด์ž

  • ์Šคํƒ ๋ฉ”๋ชจ๋ฆฌ ํ™•์ธ

asking_stack_memory

  • v8์˜ ์Šคํƒ ํฌ๊ธฐ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. 864kb๋ฅผ ํ• ๋‹น ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

alt text

  • ์•„๋ž˜์™€ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
function memoryUsed() { const mbUsed = process.memoryUsage().heapUsed / 1024 / 1024 console.log(`Memory used: ${mbUsed} MB`); } console.log('before'); memoryUsed() const bigString = 'x'.repeat(10*1024*1024) console.log(bigString); // need to use the string otherwise the compiler would just optimize it into nothingness console.log('after'); memoryUsed()
  • bitString ์—ฐ์‚ฐ ์ „

alt text

  • bigString ์—ฐ์‚ฐ ํ›„

alt text

๋ฌธ์ž์—ด ์—ฐ์‚ฐ์„ ํ†ตํ•ด 10MB์˜ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์‚ฌ์šฉ๋˜์—ˆ๋Š”๋ฐ, ์ด๋Š” ์Šคํƒ์ด ์•„๋‹Œ ํž™์—์„œ ํ• ๋‹น๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์œ„ ์ด๋ฏธ์ง€๋ฅผ ํ†ตํ•ด ํž™ ์‚ฌ์šฉ๋Ÿ‰์ด ์ •ํ™•ํžˆ 10MB๋งŒํผ ์ฆ๊ฐ€ํ•œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(3MB->13MB). ์ด๋ฅผ ํ†ตํ•ด ๊ธฐ๋ณธํ˜• ๋ฐ์ดํ„ฐ์ธ string์ด ํž™์—์„œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ• ๋‹น๋˜์—ˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

bigString ์„ ๋‹ค๋ฅธ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•˜๋ฉด ํž™ ๋ฉ”๋ชจ๋ฆฌ๋กœ ๋ถ€ํ„ฐ ์ด 20mb ๋ฅผ ํ• ๋‹น ๋ฐ›๊ฒŒ ๋˜๋Š” ๊ฑธ๊นŒ?

const copyBigString = bigString

๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋ณ€์ˆ˜๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ์–ด๋–ป๊ฒŒ ๋˜๋Š”์ง€ devtools๋ฅผ ํ†ตํ•ด ํ™•์ธํ•ด ๋ด…๋‹ˆ๋‹ค.

const btn = document.querySelector('#btn'); btn.addEventListener('click', (e) => { const string1 = 'foo' const string2 = 'foo' })

๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ foo๋ผ๋Š” ๋ฌธ์ž์—ด์„ ๋‹ด์€ ๋ณ€์ˆ˜๊ฐ€ 2๊ฐœ ์žˆ์œผ๋‹ˆ (string1, string2) ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜๋Š” ๊ณณ์ด ๋‘ ๊ฐœ์ด์ง€ ์•Š์„๊นŒ ํ•˜์ง€๋งŒ ๊ฐ™์€ ๋ฌธ์ž์—ด ๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•˜๋Š” ๋Œ€์‹  ๋‹จ์ผ ๋ณต์‚ฌ๋ณธ์„ ์ƒ์„ฑํ•˜๊ณ  ์—ฌ๋Ÿฌ ์ฐธ์กฐ๊ฐ€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฌธ์ž์—ด ์ธํ„ด์ด๋ผ๊ณ  ํ•˜๊ณ  v8์—์„œ๋„ ์ด ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜์˜ 'foo' @1169645๋กœ ํ•œ ๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋งŒ ์ €์žฅ๋œ ๊ฒƒ์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

alt text

๊ทธ๋Ÿผ 'foo' @116945๋Š” ๋ฌธ์ž์—ด์ด ๋‹ด๊ธด ์ฃผ์†Œ์ผ๊นŒ?

์•„๋‹™๋‹ˆ๋‹ค. ๊ธ€์“ด์ด์˜ ๋‚ด์šฉ์„ ์ธ์šฉํ•˜์ž๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Chrome DevTools does not show where the pointers reside in memory but rather where they point to. Also the numbers you see e.g. @206637 do not represent raw memory addresses. If you want to inspect the actual memory, you need to use a native debugger.

@116945๊ฐ€ ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ์ ์ด๊ณ , ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ๋ฐ”๋ผ๋ณด๊ณ  ์žˆ๋Š” ํฌ์ธํ„ฐ ์ด๋‹ค. ๋ผ๊ณ  ์ดํ•ด๋ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ๊ธ€์“ด์ด๊ฐ€ ํ‘œํ˜„ํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋ณ€์ˆ˜๋Š” ๋Œ€๋ถ€๋ถ„ ํฌ์ธํ„ฐ

JavaScript variables are (mostly) pointers

๋ผ๊ณ  ํ‘œํ˜„ ํ–ˆ๋Š”๋ฐ ๊ทธ๋„ ๊ทธ๋Ÿด๊ฒƒ์ด ํฌ๋กฌ์—์„œ ์‚ฌ์šฉํ•˜๋Š” JS์—”์ง„์ธ v8์ด c++ ๋กœ ์“ฐ์—ฌ์กŒ์œผ๋ฏ€๋กœ ํฌ์ธํ„ฐ ๊ฐœ๋…์„ ์ฐจ์šฉํ•˜์ง€ ์•Š์•˜์„๊นŒ ๋ผ๋Š” ์ƒ๊ฐ๋„ ๋“ญ๋‹ˆ๋‹ค.

์ด๋Š” v8 ์˜ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์–ด๋Š ์ •๋„๋Š” ์œ ์ถ” ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ,

V8_INLINE Local<Primitive> Undefined(Isolate* isolate) { using S = internal::Address; using I = internal::Internals; I::CheckInitialized(isolate); S* slot = I::GetRoot(isolate, I::kUndefinedValueRootIndex); //โœ… return Local<Primitive>(reinterpret_cast<Primitive*>(slot)); }

S(์ฆ‰, internal::Address*) ํƒ€์ž…์˜ slot ํฌ์ธํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. undefined์˜ ์›์‹œ ๊ฐ’์กฐ์ฐจ๋„ ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” C++ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋กœ ๊ตฌํ˜„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ๊ณ ์ˆ˜์ค€์ธ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ๋Š” ๋ณ€์ˆ˜์— ๊ฐ’์„ ํ• ๋‹นํ–ˆ์„ ๋•Œ ๋˜๋Š” ์•„๋ฌด๊ฒƒ๋„ ํ• ๋‹นํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ(undefined)์ผ ๋•Œ, ๋ณ€์ˆ˜๋Š” ๋ฐ์ดํ„ฐ์˜ ์‹ค์ œ ๊ฐ’์ด ์•„๋‹Œ, ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ๋œ ์œ„์น˜(๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ)๋ฅผ ์ฐธ์กฐํ•œ๋‹ค๋Š” ์ ์œผ๋กœ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.(์ด ๋ถ€๋ถ„์€ ์ œ๊ฐ€ ์ดํ•ดํ•œ ๋ฐ”๋ฅผ ํ‘œํ˜„ํ•œ ๊ฒƒ์ธ๋ฐ, ์ž˜๋ชป ์ ‘๊ทผ, ํ‘œํ˜„ํ–ˆ๋‹ค๋ฉด ์•Œ๋ ค์ฃผ์„ธ์š”.)

๊ทธ๋ ‡๋‹ค๋ฉด ์ •๋ง ๋ชจ๋“  Primitive ๋ฐ์ดํ„ฐ ํƒ€์ž…์€ ์ฐธ์กฐํ˜•์ธ๊ฐ€?

๊ทธ๋ ‡์ง€๋Š” ์•Š๋‹ค ์ž…๋‹ˆ๋‹ค. small integer -231์—์„œ 231-1๊นŒ์ง€์˜ ์ •์ˆ˜๋Š” 231์—์„œ ์ตœ์ ํ™”๋˜์–ด ์ถ”๊ฐ€ ์ €์žฅ์†Œ๋ฅผ ํ• ๋‹นํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ด์— ๋Œ€ํ•œ ๋” ์ž์„ธํ•œ ์„ค๋ช…์€ ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”.

๋งˆ๋ฌด๋ฆฌ

  • ์ž๋ฃŒ๋“ค์„ ํ†ตํ•ด ์ฑ…์—์„œ ๋ณด๋˜ "์—„๋ฐ€ํžˆ ๋”ฐ์ง€๋ฉด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ํƒ€์ž…์€ ์ฐธ์กฐํ˜• ๋ฐ์ดํ„ฐ์ผ ์ˆ˜ ๋ฐ–์— ์—†๋‹ค." ์— ๋Œ€ํ•œ ๊ถ๊ธˆ์ฆ์ด ์–ด๋Š์ •๋„ ํ•ด์†Œ๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ์ฐธ์กฐํ˜•, ๊ธฐ๋ณธํ˜• ๋ชจ๋‘ ํž™์—์„œ ํ• ๋‹น ๋œ๋‹ค๋Š” ๊ฒƒ์„ ๋ฌธ์ž์—ด ํ• ๋‹น ์˜ˆ์‹œ์ธ ๋…ธ๋“œ์˜ process.memoryUsage() ๋ฅผ ํ†ตํ•ด ํ™•์ธํ–ˆ์œผ๋ฉฐ, chrome devtool์˜ heap allocation์—์„œ๋„ string ํƒ€์ž…์ด ํž™์—์„œ ํ• ๋‹น๋˜๋Š” ์  ๋„ ์•Œ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

  • ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๊ธฐ๋ณธํ˜•๋„ ๊ฒฐ๊ตญ ์ฐธ์กฐํ˜• ์ด๋‹ค (small integer๋ฅผ ์ œ์™ธํ•˜๊ณ ). ๋ณ€์ˆ˜์— ํ• ๋‹นํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋Š”๊ฐ’์„ ๋ณต์‚ฌํ•˜๋Š”๊ฒƒ์ด ์•„๋‹Œ ์ฃผ์†Œ๊ฐ’์„ ๋ณต์‚ฌํ•˜๋Š” ์ ์„ v8์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ๊ทธ๋ฆฌ๊ณ  ๊ธฐ๋ณธ๊ฐ’์ธ undefined๋„ ํฌ์ธํ„ฐ๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ๋ถ€๋ถ„์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.


์ฐธ๊ณ  ์ž๋ฃŒ

Hi, I'm Hyunsu ๐Ÿ‘‹

Profile Image

์•ˆ๋…•ํ•˜์„ธ์š”. ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž ์ฃผํ˜„์ˆ˜์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ํ’๋ถ€ํ•˜๊ณ  ๊ฐ€์น˜ ์žˆ๋Š” ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๋Š” ์ผ์— ๋ฟŒ๋“ฏํ•จ์„ ๋Š๋‚๋‹ˆ๋‹ค.

์˜ต์‹œ๋””์–ธ(Obsidian)์—์„œ ํ˜„์žฌ ๋ธ”๋กœ๊ทธ๋กœ ํ•˜๋‚˜์”ฉ ๊ธ€์„ ์˜ฎ๊ธฐ๋Š” ๊ณผ์ •์— ์žˆ์–ด์š”. โ˜•๏ธ ๐Ÿ‘ฉโ€๐Ÿ’ป โ›ท

Github on ViewReach Me Out