Observability

๋ฉ”๋ชจ๋ฆฌ ๋คํ”„ ๋ถ„์„์„ ํ†ตํ•œ ์Šคํฌ๋ž˜ํ•‘ ์„œ๋ฒ„ ๋…ผ๋ฆฌ์  ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ 99% ๊ฐœ์„ 

ํ”„๋กœ๊ทธ๋ž˜๋จธ ์˜ค์›” 2026. 10. 10.

์ €ํฌ ํŒ€์€ ๊ธˆ์œต์‚ฌ·์‡ผํ•‘๋ชฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๋Š” ์Šคํฌ๋ž˜ํ•‘ ์„œ๋ฒ„๋ฅผ ์šด์˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋А ๋‚  ์—ฌ๋Ÿฌ ๋Œ€์˜ ์Šคํฌ๋ž˜ํ•‘ ์„œ๋ฒ„ ์ค‘ 3๋ฒˆ ์„œ๋ฒ„ ํ•œ ๋Œ€๋งŒ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ 1GiB ๊ฐ€๊นŒ์ด ์ฅ” ์ฑ„ 21์‹œ๊ฐ„ ๋™์•ˆ ๋Œ๋ ค์ฃผ์ง€ ์•Š๋Š” ์ผ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์žฌ๊ธฐ๋™ํ•˜๊ณ  ๋‚˜์„œ์•ผ ๋‹ค๋ฅธ ์„œ๋ฒ„์™€ ๊ฐ™์€ ์ˆ˜์ค€์œผ๋กœ ๋Œ์•„์™”์Šต๋‹ˆ๋‹ค.

 

 

GC ๊ฐ€ ์žˆ๋Š” ๋Ÿฐํƒ€์ž„์—์„œ "๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋Œ์•„์˜ค์ง€ ์•Š๋Š”๋‹ค"๋Š” ๋ง์€ ๋ณดํ†ต ๋‘ ๊ฐ€์ง€ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ๋ˆ„๊ตฐ๊ฐ€ ์•„์ง ๊ทธ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๊ฑฐ๋‚˜, ์ฐธ์กฐ๋Š” ๋Š๊ฒผ๋Š”๋ฐ ๋Ÿฐํƒ€์ž„์ด OS ์— ๋ฐ˜๋‚ฉํ•˜์ง€ ์•Š๊ณ  ์žˆ๊ฑฐ๋‚˜. ์ด๋ฒˆ ๊ธ€์€ ์ง€ํ‘œ์™€ ๋ฉ”๋ชจ๋ฆฌ ๋คํ”„๋กœ ์ด ๋‘˜์„ ๊ฐ€๋ฅด๊ณ , ๊ฒฐ๊ตญ ๋ฌธ์ž์—ด์„ str[i] ๋กœ ํ•œ ๊ธ€์ž์”ฉ ์ฝ๋Š” ํ‰๋ฒ”ํ•œ ์ฝ”๋“œ ํ•œ ์ค„์ด static ์บ์‹œ์— ์ •์ˆ˜ ํ‚ค๋ฅผ 967๋งŒ ๊ฐœ ์Œ“์•„ ๋‘” ๋…ผ๋ฆฌ์  ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์˜€๋‹ค๋Š” ๊ฒƒ์„ ๋ฐํ˜€๋‚ธ ๊ธฐ๋ก์ž…๋‹ˆ๋‹ค.

 

๋…ผ๋ฆฌ์  ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜(logical memory leak) : GC ๊ฐ€ ์žˆ๋Š” ์–ธ์–ด์—์„œ, ๋” ์ด์ƒ ์“ฐ์ง€ ์•Š๋Š” ๊ฐ์ฒด๊ฐ€ GC ๋ฃจํŠธ์—์„œ ์—ฌ์ „ํžˆ ๋‹ฟ์„ ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ๋กœ ๋‚จ์•„ ํšŒ์ˆ˜๋˜์ง€ ๋ชปํ•˜๋Š” ๊ฒƒ. ๋ฉ”๋ชจ๋ฆฌ๋ฅผ "์žƒ์–ด๋ฒ„๋ฆฐ" ๊ฒƒ์ด ์•„๋‹ˆ๋ผ "๋†“์ง€ ๋ชปํ•œ" ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

๊ธ€์€ ๋ฐฐ๊ฒฝ ๋ฐ ๋ฌธ์ œ ์ƒํ™ฉ → ์ž‘์—… ๋ฐ ํ–‰๋™ → ๊ฒฐ๊ณผ ๋ฐ ์„ฑ๊ณผ ์ˆœ์„œ๋กœ ์ •๋ฆฌํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

 

๐Ÿšฉ๋ฐฐ๊ฒฝ ๋ฐ ๋ฌธ์ œ ์ƒํ™ฉ

 

1๏ธโƒฃ๋“ค์–ด๊ฐ€๊ธฐ ์ „์—: JS ๋ฅผ ์‹คํ–‰ํ•˜๋Š” C# ์—”์ง„

์ด ๊ธ€์—๋Š” "JS ์—”์ง„", "์†์„ฑ ํ‚ค", "์บ์‹œ" ๊ฐ™์€ ๋ง์ด ๊ณ„์† ๋‚˜์˜ต๋‹ˆ๋‹ค. ์‚ฌ๋‚ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ TypeScript ๋กœ ์ž‘์„ฑํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ JavaScript ๋กœ ๋นŒ๋“œํ•ด ๋‘๊ณ , ๊ธฐ๋™ํ•  ๋•Œ ๊ทธ JS ๋ฅผ ์ฝ์–ด ๋‘์—ˆ๋‹ค๊ฐ€ ์š”์ฒญ์ด ์˜ค๋ฉด ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

 

[๊ทธ๋ฆผ 1] C#(.NET 10)์œผ๋กœ ๋งŒ๋“  ์ž์ฒด JS ์—”์ง„์œผ๋กœ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ์กด์žฌํ•˜๋Š” JS ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰

 

 

Chrome ์ด๋‚˜ Node.js ๊ฐ€ V8 ์—”์ง„์œผ๋กœ JS ๋ฅผ ์‹คํ–‰ํ•˜๋“ฏ, ์ €ํฌ๋Š” C#(.NET 10)์œผ๋กœ ๋งŒ๋“  ์ž์ฒด JS ์—”์ง„์œผ๋กœ JS ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ JS ์ฝ”๋“œ๊ฐ€ ๋งŒ๋“œ๋Š” ๊ฐ์ฒด๋„, ์—”์ง„ ๋‚ด๋ถ€์˜ ์บ์‹œ๋„ ๋ชจ๋‘ .NET ๊ด€๋ฆฌ ํž™(managed heap)์— ์ƒ๊ธฐ๊ณ  .NET GC ๊ฐ€ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฒˆ ์‚ฌ๊ณ ๋ฅผ dotnet-dump ๊ฐ™์€ .NET ์ง„๋‹จ ๋„๊ตฌ๋กœ ์ถ”์ ํ•  ์ˆ˜ ์žˆ์—ˆ๋˜ ์ด์œ ์ž…๋‹ˆ๋‹ค.

 

2๏ธโƒฃ3๋ฒˆ ์„œ๋ฒ„๋งŒ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋Œ์•„์˜ค์ง€ ์•Š์•˜๋‹ค

10์›” 1์ผ 19์‹œ 25๋ถ„๊ฒฝ 3๋ฒˆ ์„œ๋ฒ„์˜ ๊ฐ€์šฉ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ 1.4GiB ์—์„œ 0.48GiB ๋กœ ์•ฝ 1GiB ๋–จ์–ด์ง„ ๋’ค ํšŒ๋ณต๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์—…๋ฌด๊ฐ€ ๊ฑฐ์˜ ์—†๋Š” ์•ผ๊ฐ„๊ณผ ์ƒˆ๋ฒฝ์—๋„, ๋‹ค์Œ ๋‚  ์—…๋ฌด ์‹œ๊ฐ„์—๋„ 0.5GiB ์•ˆํŒŽ์— ๋จธ๋ฌผ๋ €๊ณ , ๋‹ค๋ฅธ ์Šคํฌ๋ž˜ํ•‘ ์„œ๋ฒ„๋“ค์€ ํ‰์†Œ์™€ ๊ฐ™์•˜์Šต๋‹ˆ๋‹ค. ์ด ์ƒํƒœ๋Š” ์•ฝ 21์‹œ๊ฐ„ ์ด์–ด์ง€๋‹ค๊ฐ€ 10์›” 2์ผ 17์‹œ๊ฒฝ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์žฌ๊ธฐ๋™ํ•˜๊ณ  ๋‚˜์„œ์•ผ ํ’€๋ ธ์Šต๋‹ˆ๋‹ค.

 

[๊ทธ๋ฆผ 2] 10/01 ~ 10/02 ๋Œ€์‹œ๋ณด๋“œ. ์˜ค๋ฅธ์ชฝ ์•„๋ž˜ Free Memory ์—์„œ ๋…ธ๋ž€ ์„ (3๋ฒˆ)๋งŒ 10/01 ์ €๋…์— ๋–จ์–ด์ ธ ์žฌ๊ธฐ๋™ ์ „๊นŒ์ง€ ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค

 

ํ•ญ๋ชฉ ๊ฐ’
3๋ฒˆ ์„œ๋ฒ„ ๊ฐ€์šฉ ๋ฉ”๋ชจ๋ฆฌ (10-01 19:25) 1.4 GiB → 0.48 GiB (์•ฝ 1 GiB ๊ฐ์†Œ)
ํšŒ๋ณต๋˜์ง€ ์•Š๊ณ  ์œ ์ง€๋œ ์‹œ๊ฐ„ ์•ฝ 21์‹œ๊ฐ„ (10-02 17์‹œ ์žฌ๊ธฐ๋™๊นŒ์ง€)
์„œ๋ฒ„ ์‚ฌ์–‘ 4์ฝ”์–ด / 8GB
๊ฐ™์€ ์—ญํ•  ์„œ๋ฒ„ ์ค‘ ์ฆ์ƒ์ด ๋‚œ ์„œ๋ฒ„ 3๋ฒˆ 1๋Œ€

 

3๏ธโƒฃGrafana ์ง€ํ‘œ๋กœ ๋ฒ”์œ„ ์ขํžˆ๊ธฐ

๊ฐ€์šฉ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋–จ์–ด์ง„ 19์‹œ 25๋ถ„ ์•ž๋’ค 5๋ถ„์„ ํ™•๋Œ€ํ•ด ๋ดค์Šต๋‹ˆ๋‹ค.

 

[๊ทธ๋ฆผ 3] 19:23 ~ 19:28 ํ™•๋Œ€

  • ๋ฉ”๋ชจ๋ฆฌ : 19์‹œ 25๋ถ„ 26์ดˆ๋ถ€ํ„ฐ 3๋ฒˆ๋งŒ ๊ฐ€์šฉ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ 1.5GiB → 0.5GiB ๋กœ ๋–จ์–ด์กŒ์Šต๋‹ˆ๋‹ค.
  • CPU : ๊ฐ™์€ ์‹œ๊ฐ ์•ฝ 20%p ์˜ฌ๋ผ 55 ~ 58% ๊ตฌ๊ฐ„์—์„œ ์•ฝ 40์ดˆ ๋จธ๋ฌผ๋ €์Šต๋‹ˆ๋‹ค(์ตœ๊ณ  58.4%).
  • Paging File : ์•ฝ 8% → 12% ๋กœ ์˜ฌ๋ž์Šต๋‹ˆ๋‹ค.
  • Processor Queue Length : 7๋ฒˆ ์„œ๋ฒ„์™€ ๋น„์Šทํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ† ํ”ฝ ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ๋™์‹œ์— ์†Œ๋น„ํ•ด์„œ ์ผ์ด ๋งŽ์•„์ง„ ๊ฒƒ์ด๋ผ๋ฉด ๋Œ€๊ธฐ ํ ๊ธธ์ด๋„ ํ•จ๊ป˜ ๋Š˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๊ทธ๋ ‡์ง€ ์•Š์•˜์œผ๋‹ˆ "ํ† ํ”ฝ ๋ฉ”์„ธ์ง€ ์—ฌ๋Ÿฌ ๊ฐœ"๊ฐ€ ์•„๋‹ˆ๋ผ ํ† ํ”ฝ ๋ฉ”์„ธ์ง€ ํ•˜๋‚˜์—์„œ ๋ฌด๊ฑฐ์šด ์—ฐ์‚ฐ์ด ์ผ์–ด๋‚ฌ๋‹ค๊ณ  ์ถ”์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

[๊ทธ๋ฆผ 4] ๊ฐ™์€ 5๋ถ„์˜ ๋„คํŠธ์›Œํฌ. 19:25:30 ์— 3๋ฒˆ ์„œ๋ฒ„ ์ˆ˜์‹  26.3Mb/s, ์•ฝ 50์ดˆ ๋’ค ์†ก์‹  ์ŠคํŒŒ์ดํฌ

 

๋„คํŠธ์›Œํฌ์—์„œ๋„ ๊ฐ™์€ ๊ทธ๋ฆผ์ด ๋‚˜์™”์Šต๋‹ˆ๋‹ค. 19์‹œ 25๋ถ„ 30์ดˆ์— 3๋ฒˆ ์„œ๋ฒ„๋กœ 26.3Mb/s ์ˆ˜์‹  ์ŠคํŒŒ์ดํฌ(๊ฐ™์€ ์‹œ๊ฐ 7๋ฒˆ์€ 12.5kb/s)๊ฐ€ ์žˆ์—ˆ๊ณ , ์•ฝ 50์ดˆ ๋’ค 3๋ฒˆ๋งŒ ์•ฝ 17Mb/s ์†ก์‹  ์ŠคํŒŒ์ดํฌ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

 

์ˆ˜์‹ ์€ ์™ธ๋ถ€ ์ˆ˜์ง‘์ฒ˜์—์„œ ๋งค์šฐ ํฐ ์‘๋‹ต์„ ๋ฐ›์•˜๋‹ค๋Š” ๋œป์ด๊ณ , ์†ก์‹ ์€ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์›Œ์ปค ์„œ๋ฒ„์— ๋„˜๊ธฐ๋ ค๊ณ  ๋ฉ”์‹œ์ง€ ํ ํ…Œ์ด๋ธ”์— ํฐ ์“ฐ๊ธฐ๋ฅผ ํ–ˆ๋‹ค๋Š” ๋œป์œผ๋กœ ํ•ด์„ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

4๏ธโƒฃ์‹œ์ž‘์ ์€ ๊ณ ๋„๋ชฐ ์ฃผ๋ฌธ ์ˆ˜์ง‘ ํ•œ ๊ฑด

์™ธ๋ถ€ ์‘๋‹ต ํฌ๊ธฐ๋ฅผ ์ง์ ‘ ๋‚จ๊ธฐ๋Š” ์ง€ํ‘œ๋Š” ์—†์–ด์„œ, ๊ทธ ์‹œ๊ฐ์— ์กด(Zone: ์‚ฌ๋‚ด์—์„œ ์“ฐ๋Š” ์šด์˜ ๊ตฌ์—ญ)๋ณ„๋กœ ๋ฉ”์‹œ์ง€ ํ๋กœ ๋ฐœํ–‰๋œ ํ† ํ”ฝ์„ ๋ชจ๋‹ˆํ„ฐ๋ง ํ•˜๋Š” ๋ฉ”๋‰ด๋กœ ์กฐํšŒํ•ด ๋ดค์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์กด์€ 10๊ฐœ ๋ฏธ๋งŒ์ด์—ˆ๋Š”๋ฐ, ํ•œ ํšŒ์‚ฌ์—์„œ๋งŒ 19์‹œ 26๋ถ„ 22์ดˆ์— ํ† ํ”ฝ 385๊ฐœ๊ฐ€ ํ•œ๊บผ๋ฒˆ์— ๋ฐœํ–‰๋์Šต๋‹ˆ๋‹ค. ๋ฐœํ–‰ํ•œ ์„œ๋ฒ„๋Š” ์—ญ์‹œ 3๋ฒˆ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

[๊ทธ๋ฆผ 5] ์›Œ์ปค์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ํ† ํ”ฝ์˜ ๋ฐœํ–‰ ์„œ๋ฒ„๊ฐ€ ๋ชจ๋‘ ์Šคํฌ๋ž˜ํ•‘ 3๋ฒˆ์„œ๋ฒ„

 

 

ํ† ํ”ฝ ๋ฉ”์„ธ์ง€๋ฅผ ํ™•์ธํ•ด ๋ณด๋‹ˆ ์‡ผํ•‘๋ชฐ ์ค‘์— ์ œ๊ณตํ•˜๋Š” ์™ธ๋ถ€์ˆ˜์ง‘์ฒ˜์ธ ๊ณ ๋„๋ชฐ ์ฃผ๋ฌธ ์ˆ˜์ง‘ 1๊ฑด์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์กฐํšŒ๋ฅผ ํ†ตํ•ด ์–ป์€ ์ˆ˜์ง‘ ๋ฐ์ดํ„ฐ ๊ฒฐ๊ณผ๋Š” 10๊ฑด์”ฉ ์ž˜๋ผ ํ† ํ”ฝ ํ•˜๋‚˜๋กœ ๋ฐœํ–‰ํ•˜๋ฏ€๋กœ, 385๊ฐœ ํ† ํ”ฝ ๋ฉ”์„ธ์ง€๋ฉด ํ•œ ๋ฒˆ์— ์ตœ๋Œ€ 3,850๊ฑด์„ ์ˆ˜์ง‘ํ–ˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ ๊ณ ๋„๋ชฐ์€ ์‘๋‹ต์„ JSON ์ด ์•„๋‹ˆ๋ผ XML ๋กœ ์ค˜์„œ ํƒœ๊ทธ ๋•Œ๋ฌธ์— ์‘๋‹ต์ด ํ›จ์”ฌ ํฝ๋‹ˆ๋‹ค.

์ˆ˜์‹  ํŠธ๋ž˜ํ”ฝ์ด ๊ทธ๋ ‡๊ฒŒ ์ปธ๋˜ ์ด์œ ๊ฐ€ ์—ฌ๊ธฐ์„œ ์„ค๋ช…๋ฉ๋‹ˆ๋‹ค.

 

 

ํ•˜์ง€๋งŒ ์ด๊ฒƒ์œผ๋กœ ์„ค๋ช…๋˜๋Š” ๊ฑด "์ˆ˜์ง‘ํ•˜๋Š” ๋™์•ˆ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋งŽ์ด ์ผ๋‹ค"๊นŒ์ง€์ž…๋‹ˆ๋‹ค. ์ˆ˜์‹ญ MB ์‘๋‹ต์ด UTF-16 ๋ฌธ์ž์—ด๋กœ ๋‘ ๋ฐฐ๊ฐ€ ๋˜๊ณ , ํ•„ํ„ฐ๋ฅผ ๊ฑฐ์นœ ๋ณต์‚ฌ๋ณธ๊ณผ XML DOM ๊นŒ์ง€ ํ•œ๊บผ๋ฒˆ์— ์ƒ๊ธฐ๋‹ˆ ์ˆœ๊ฐ„์ ์œผ๋กœ ์ปค์ง€๋Š” ๊ฑด ์ž์—ฐ์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค. ์ž‘์—…์ด ๋๋‚œ ๋’ค์—๋„ 21์‹œ๊ฐ„ ๋™์•ˆ ๋Œ๋ ค์ฃผ์ง€ ์•Š์€ ๊ฒƒ์€ ์ „ํ˜€ ๋‹ค๋ฅธ ๋ฌธ์ œ์˜€์Šต๋‹ˆ๋‹ค.

 

 

 

5๏ธโƒฃ ๋คํ”„๋ฅผ ๋œจ๊ธฐ ์ „์— ์„ธ์šด ๊ฐ€์„ค

๊ณ ๋„๋ชฐ ์ˆ˜์ง‘ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง(TS)๊ณผ ์‡ผํ•‘๋ชฐ ๊ณตํ†ต ๋กœ์ง์„ ์ฝ์–ด ๋ดค์ง€๋งŒ, ์ˆ˜์ง‘ ๋ฐ์ดํ„ฐ๋ฅผ static ์ด๋‚˜ ๋ชจ๋“ˆ ์ „์—ญ์— ๋“ค๊ณ  ์žˆ๋Š” ์ฝ”๋“œ๋Š” ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ€์„ค์„ ์„ธ ๊ฐœ ์„ธ์› ์Šต๋‹ˆ๋‹ค.

๊ฐ€์„ค ๋‚ด์šฉ ๋‹น์‹œ ํŒ๋‹จ
โ‘  ์‚ด์•„ ์žˆ๋Š” ์ฐธ์กฐ ์–ด๋”˜๊ฐ€์—์„œ ํฐ ์‘๋‹ต ๋ฌธ์ž์—ด์ด๋‚˜ XML DOM ์„ ๊ณ„์† ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋‹ค ๋น„์ฆˆ๋‹ˆ์Šค ์ฝ”๋“œ์—์„œ๋Š” ๋ชป ์ฐพ์Œ. ํ”„๋ ˆ์ž„์›Œํฌ·์—”์ง„ ์ชฝ์€ ๋ฏธํ™•์ธ
โ‘ก LOH ์กฐ๊ฐํ™” / ํž™ ๋ฏธ๋ฐ˜๋‚ฉ ์ฐธ์กฐ๋Š” ๋Š๊ฒผ์ง€๋งŒ ์ˆ˜์‹ญ MB ๋ฌธ์ž์—ด์ด LOH ์— ์˜ฌ๋ผ๊ฐ”๋‹ค ๋น ์ง€๋ฉฐ ์กฐ๊ฐ๋‚˜, ๋นˆ ๊ณต๊ฐ„์„ OS ์— ๋Œ๋ ค์ฃผ์ง€ ๋ชปํ•œ๋‹ค ์ฒ˜์Œ์—๋Š” ๊ฐ€์žฅ ์œ ๋ ฅ
โ‘ข ๋„ค์ดํ‹ฐ๋ธŒ ๋ฉ”๋ชจ๋ฆฌ GC ๊ฐ€ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ๋ฒ„ํผ๊ฐ€ ๋‚จ์•„ ์žˆ๋‹ค ๋คํ”„ ์—†์ด๋Š” ๊ฐ€๋ฆด ์ˆ˜ ์—†์Œ

 

๊ทธ๋Ÿฐ๋ฐ ์„œ๋ฒ„์˜ runtimeconfig.json ์„ ๋ณด๋‹ˆ GC ์„ค์ •์ด ์—†์–ด Workstation GC ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋Œ๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. "ํšŒ์ˆ˜๋Š” ํ–ˆ๋Š”๋ฐ OS ์— ๋ฐ”๋กœ ๋Œ๋ ค์ฃผ์ง€ ์•Š๋Š”" ์„ฑํ–ฅ์€ ์ฝ”์–ด๋งˆ๋‹ค ํž™์„ ํฌ๊ฒŒ ์žก๋Š” Server GC ์ชฝ ์ด์•ผ๊ธฐ์ด๊ณ , ๊ฒŒ๋‹ค๊ฐ€ 21์‹œ๊ฐ„ ๋™์•ˆ ๊ฐ€์šฉ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋ฐ”๋‹ฅ์ด์—ˆ์œผ๋‹ˆ GC ๋Š” ๊ทธ์‚ฌ์ด ์—ฌ๋Ÿฌ ๋ฒˆ ๋Œ์•˜์„ ๊ฒ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ๋„ 1GiB ๊ฐ€ ๊ทธ๋Œ€๋กœ์˜€๋‹ค๋ฉด โ‘ก ๋ณด๋‹ค๋Š” โ‘  ์‚ด์•„ ์žˆ๋Š” ์ฐธ์กฐ ์ชฝ์— ๋ฌด๊ฒŒ๊ฐ€ ์‹ค๋ ธ์Šต๋‹ˆ๋‹ค.

 

 

๋‹ค๋งŒ ๋ˆ„๊ฐ€ ์ฅ๊ณ  ์žˆ๋Š”์ง€๋Š” ์ฝ”๋“œ๋ฅผ ๋ˆˆ์œผ๋กœ ์ซ“์•„์„œ๋Š” ๊ฐ€๋ฆด ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ™์€ ํ˜„์ƒ์„ ์ผ๋ถ€๋Ÿฌ ์žฌํ˜„ํ•˜๊ณ , ๊ทธ ์ˆœ๊ฐ„์˜ ํž™์„ ๋คํ”„๋กœ ๋– ์„œ ์ง์ ‘ ๋ณด๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

 

 

๐Ÿ”์ž‘์—… ๋ฐ ํ–‰๋™

 

1๏ธโƒฃ์ธก์ • ๋„๊ตฌ: ์ถ”์ด 2๊ฐœ + ๋คํ”„

๋คํ”„๋Š” ํ•œ ์ˆœ๊ฐ„์˜ ์‚ฌ์ง„์ด๋ผ, ๊ทธ๊ฒƒ๋งŒ์œผ๋กœ๋Š” "์žฌํ˜„์ด ๋๋Š”์ง€"์กฐ์ฐจ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์‹œ๊ฐ„ ํ๋ฆ„์„ ๋‚จ๊ธฐ๋Š” ๋„๊ตฌ ๋‘ ๊ฐœ๋ฅผ ํ•จ๊ป˜ ์ผœ ๋‘๊ณ , ์ •ํ•ด์ง„ ์‹œ์ ์— ๋คํ”„๋ฅผ ๋–ด์Šต๋‹ˆ๋‹ค.

๋„๊ตฌ ๋‚จ๊ธฐ๋Š” ๊ฒƒ ๋‹ตํ•˜๋Š” ์งˆ๋ฌธ
typeperf ํ”„๋กœ์„ธ์Šค Private Bytes, Working Set, ์„œ๋ฒ„ ๊ฐ€์šฉ ๋ฉ”๋ชจ๋ฆฌ, CPU ๋ฅผ 5์ดˆ๋งˆ๋‹ค OS ๊ด€์ . ์–ธ์ œ, ์–ผ๋งˆ๋‚˜ ๋Š˜๊ณ  ์ค„์—ˆ๋‚˜
dotnet-counters ์„ธ๋Œ€๋ณ„ GC ํž™ ํฌ๊ธฐ, GC ํšŸ์ˆ˜, ๋ฉˆ์ถค ์‹œ๊ฐ„, ํ• ๋‹น๋Ÿ‰์„ 5์ดˆ๋งˆ๋‹ค ๋Ÿฐํƒ€์ž„ ๊ด€์ . ๊ด€๋ฆฌ ํž™์ด ๋Š˜์—ˆ๋‚˜, GC ๋Š” ๋Œ์•˜๋‚˜
dotnet-dump ๊ทธ ์ˆœ๊ฐ„์˜ ํ”„๋กœ์„ธ์Šค ๋ฉ”๋ชจ๋ฆฌ ์ „์ฒด(.dmp) ํž™ ์•ˆ. ๋ฌด์Šจ ๊ฐ์ฒด๊ฐ€ ๋ช‡ ๊ฐœ ์žˆ๊ณ  ๋ˆ„๊ฐ€ ์ฐธ์กฐํ•˜๋‚˜
typeperf "\Process(<ํ”„๋กœ์„ธ์Šค๋ช…>)\Private Bytes" "\Process(<ํ”„๋กœ์„ธ์Šค๋ช…>)\Working Set" "\Memory\Available MBytes" "\Processor(_Total)\% Processor Time" -si 5 -o mem.csv
dotnet-counters collect -p <PID> --counters System.Runtime --refresh-interval 5 --format csv -o counters.csv
dotnet-dump collect -p <PID> -o dump2_after.dmp

 

Private Bytes ์™€ GC ํž™์„ ๊ฐ™์ด ๋ณด๋ฉด ๋ฐฉํ–ฅ์ด ์ •ํ•ด์ง‘๋‹ˆ๋‹ค. Private Bytes ๋งŒ ์˜ค๋ฅด๊ณ  GC ํž™์ด ๊ทธ๋Œ€๋กœ๋ฉด ๋„ค์ดํ‹ฐ๋ธŒ ๋ฉ”๋ชจ๋ฆฌ, ๋‘˜์ด ๊ฐ™์ด ์˜ค๋ฅด๋ฉด ๊ด€๋ฆฌ ํž™์— ์‚ด์•„ ์žˆ๋Š” ์ฐธ์กฐ๊ฐ€ ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.

์ž‘์—… ๊ด€๋ฆฌ์ž๋‚˜ tasklist ์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ฐ’(Working Set)์€ ์“ฐ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋ถ€์กฑํ•œ ์„œ๋ฒ„์—์„œ๋Š” ๋””์Šคํฌ๋กœ ๋ฐ€๋ ค๋‚˜ ์ค„์–ด๋“  ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

2๏ธโƒฃ์žฌํ˜„ ํ™˜๊ฒฝ: ๋ชฉ์„œ๋ฒ„์™€ ํฐ ์‘๋‹ต

์šด์˜ ์„œ๋ฒ„์—์„œ ์ผ๋ถ€๋Ÿฌ ์‚ฌ๊ณ ๋ฅผ ๋‚ผ ์ˆ˜๋Š” ์—†์œผ๋‹ˆ ํ…Œ์ŠคํŠธ ์Šคํฌ๋ž˜ํ•‘ ์„œ๋ฒ„์—์„œ ๊ฐ™์€ ์ƒํ™ฉ์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

  1. ์‘๋‹ต ํŒŒ์ผ : ์‹ค์ œ ๊ณ ๋„๋ชฐ ์ฃผ๋ฌธ ๋ฐ์ดํ„ฐ ์กฐํšŒ HTTP Response ํ•˜๋‚˜๋ฅผ ๊บผ๋‚ด, ํ—ค๋”์™€ ๋ฉ”ํƒ€ ์ •๋ณด๋Š” ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ์ฃผ๋ฌธ ๋ชฉ๋ก๋งŒ ์‚ฌ๊ณ  ๋‹น์‹œ ์ˆ˜์ค€(3,850ํ–‰)์œผ๋กœ ๋Š˜๋ ธ์Šต๋‹ˆ๋‹ค.
  2. ๋ชฉ์„œ๋ฒ„ : ์ œ PC ์— ์ž‘์€ Node.js ์„œ๋ฒ„๋ฅผ ๋„์›Œ, ์š”์ฒญ์ด ์˜ค๋ฉด ๊ทธ ํŒŒ์ผ์„ XML ๋กœ ์‘๋‹ตํ•˜๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ์„œ๋ฒ„๊ฐ€ ๋„คํŠธ์›Œํฌ๋ฅผ ํƒ€๊ณ  ์ œ PC ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ํ•ด์„œ ์‹ค์ œ ํ†ต์‹ ๊ณผ ์ตœ๋Œ€ํ•œ ๋น„์Šทํ•˜๊ฒŒ ๋งž์ท„์Šต๋‹ˆ๋‹ค.
  3. ์ž„์‹œ ๋นŒ๋“œ : ๊ณ ๋„๋ชฐ ์‹ ๊ทœ ์ฃผ๋ฌธ ์กฐํšŒ URL ๋งŒ ๋ชฉ์„œ๋ฒ„ ์ฃผ์†Œ๋กœ ๋ฐ”๊ฟ” ํ…Œ์ŠคํŠธ ์„œ๋ฒ„์— ๋ฐฐํฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์‘๋‹ต์„ ๋ฐ›์€ ๋’ค์˜ ์ฒ˜๋ฆฌ ๊ฒฝ๋กœ๋Š” ์šด์˜๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

[๊ทธ๋ฆผ 6] ์žฌํ˜„ ํ™˜๊ฒฝ. ๋ฐ”๊พผ ๊ฒƒ์€ "์š”์ฒญ์ด ๊ฐ€๋Š” ์ฃผ์†Œ" ํ•˜๋‚˜

3๏ธโƒฃํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค

  1. ๊ธฐ๋ก ์‹œ์ž‘ + ์›Œ๋ฐ์—… : typeperf, dotnet-counters ๋ฅผ ์ผœ ๋‘๊ณ  ์นด๋“œ·์€ํ–‰·์‡ผํ•‘๋ชฐ ์กฐํšŒ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ๋Œ๋ ค ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ‰ํ‰ํ•ด์งˆ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. ๊ธฐ๋™ ์งํ›„์˜ ์ž์—ฐ์Šค๋Ÿฌ์šด ์ฆ๊ฐ€๋ฅผ ์ˆ˜์ง‘ ๋•Œ๋ฌธ์œผ๋กœ ์˜คํ•ดํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•ด์„œ์ž…๋‹ˆ๋‹ค.

  2. ์ˆ˜์ง‘ ์ „ ๋คํ”„ : ์ž‘์—…์ด ์—†๋Š” ์ˆœ๊ฐ„์— ๋œน๋‹ˆ๋‹ค. "์›๋ž˜ ์žˆ๋˜ ๊ฒƒ"๊ณผ "์ƒˆ๋กœ ์ƒ๊ธด ๊ฒƒ"์„ ๊ฐ€๋ฅด๋Š” ๊ธฐ์ค€์ž…๋‹ˆ๋‹ค.

  3. ๊ณ ๋„๋ชฐ ์ˆ˜์ง‘ 1ํšŒ : ๋ชฉ์„œ๋ฒ„ ์ฝ˜์†”์— ์š”์ฒญ๊ณผ ์‘๋‹ต ํฌ๊ธฐ๊ฐ€ ์ฐํžˆ๋Š”์ง€ ๋ด…๋‹ˆ๋‹ค.

  4. +10๋ถ„ ๋คํ”„ : ๊ทธ์‚ฌ์ด ๋‹ค๋ฅธ ์กฐํšŒ๋ฅผ ๋ช‡ ๋ฒˆ ๋Œ๋ ค GC ๊ฐ€ ๋Œ ๊ธฐํšŒ๋ฅผ ์ค๋‹ˆ๋‹ค. GC ๋Š” ์‹œ๊ฐ„์ด ์ง€๋‚œ๋‹ค๊ณ  ๋„๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ํ• ๋‹น์ด ์Œ“์—ฌ์•ผ ๋Œ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. "์•„์ง GC ๊ฐ€ ์•ˆ ๋Œ์•„์„œ ๋‚จ์€ ๊ฒƒ"๊ณผ "GC ๊ฐ€ ๋Œ์•„๋„ ๋‚จ๋Š” ๊ฒƒ"์„ ๊ฐ€๋ฅด๊ธฐ ์œ„ํ•œ ๋คํ”„์ž…๋‹ˆ๋‹ค.

  5. +30๋ถ„ ๋คํ”„ : ๋‹ค์‹œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ๋งˆ์ง€๋ง‰ ๋คํ”„๋ฅผ ๋œน๋‹ˆ๋‹ค. "์ž ์‹œ ๋‚จ์€ ๊ฒƒ"์ธ์ง€ "์˜๊ตฌํžˆ ๋‚จ๋Š” ๊ฒƒ"์ธ์ง€๋ฅผ ํŒ๋‹จํ•ฉ๋‹ˆ๋‹ค.

ํŒ์ • ๊ธฐ์ค€์€ ์‹คํ—˜ ์ „์— ์ •ํ•ด ๋’€์Šต๋‹ˆ๋‹ค. ์ˆ˜์ง‘ 10๋ถ„ ๋’ค ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๊ธฐ์ค€์„ ์œผ๋กœ ๋Œ์•„์˜ค๋ฉด ์žฌํ˜„ ์‹คํŒจ, ์˜ฌ๋ผ๊ฐ„ ์ฑ„ ์œ ์ง€๋˜๋ฉด ์žฌํ˜„ ์„ฑ๊ณต์ž…๋‹ˆ๋‹ค.

 

4๏ธโƒฃ1์ฐจ ์žฌํ˜„(30MB): ํ…Œ์ŠคํŠธ ์„œ๋ฒ„๊ฐ€ ์“ฐ๋Ÿฌ์กŒ๋‹ค

์šด์˜๊ณผ ์ตœ๋Œ€ํ•œ ๊ฐ™๊ฒŒ ํ•˜๋ ค๊ณ  30MB ์‘๋‹ต์œผ๋กœ ์‹œ์ž‘ํ–ˆ๋Š”๋ฐ, ํ…Œ์ŠคํŠธ ์Šคํฌ๋ž˜ํ•‘ ์„œ๋ฒ„๊ฐ€ ๋ฒ„ํ‹ฐ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์šด์˜ ์„œ๋ฒ„๋Š” 4์ฝ”์–ด / 8GB ์ธ๋ฐ ํ…Œ์ŠคํŠธ ์„œ๋ฒ„๋Š” 4์ฝ”์–ด / 4GB ์˜€๊ณ , ์ˆ˜์ง‘ ์ „๋ถ€ํ„ฐ ๊ฐ€์šฉ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์•ฝ 0.9GB ๋ฟ์ด์—ˆ์Šต๋‹ˆ๋‹ค. (์ด ์ผ ๋’ค๋กœ ์ธํ”„๋ผ ํŒ€์—์„œ ์• ์ดˆ์— ๊ฐ€์šฉ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋„ˆ๋ฌด ์ ์€ ๊ฒƒ ๊ฐ™๋‹ค๊ณ  ํ…Œ์ŠคํŠธ ์„œ๋ฒ„๋„ 8GB ๋กœ ๋Š˜๋ ค ์ฃผ์…จ์Šต๋‹ˆ๋‹ค.)

 

 

์—„๋ฐ€ํžˆ๋Š” .NET ์˜ OutOfMemoryException ์ด ์•„๋‹ˆ๋ผ ์„œ๋ฒ„ ์ „์ฒด ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๊ณ ๊ฐˆ๋˜์–ด ์›๊ฒฉ ์„ธ์…˜๊นŒ์ง€ ๋ฌด๋„ˆ์ง„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. .NET ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํž™ ์ƒํ•œ์ด ์—†์–ด์„œ ํ”„๋กœ์„ธ์Šค๋Š” ์กฐ์šฉํžˆ ๊ณ„์† ์ปค์ง€๊ณ , ์„œ๋ฒ„์˜ ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋จผ์ € ์ฃฝ์Šต๋‹ˆ๋‹ค.

 

 

๊ทธ๋Ÿฐ๋ฐ ์ด ์‹คํŒจํ•œ ์‹คํ—˜์ด ์˜คํžˆ๋ ค ๊ฒฐ์ •์ ์ธ ์ž๋ฃŒ๋ฅผ ๋‚จ๊ฒผ์Šต๋‹ˆ๋‹ค. "์•„์ง๋„ ์•ˆ ๋๋‚˜๋„ค?" ์‹ถ์–ด ์ˆ˜์ง‘ ๋„์ค‘์— ๋–  ๋‘” ์ค‘๊ฐ„ ๋คํ”„(5.85GB)์—, ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ถ™์žก๊ณ  ์žˆ๋Š” ๊ฐ์ฒด์™€ ๊ทธ ์ˆœ๊ฐ„ ์‹คํ–‰ ์ค‘์ด๋˜ ํ•จ์ˆ˜๊ฐ€ ๊ทธ๋Œ€๋กœ ์ฐํ˜€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋คํ”„์—์„œ ์บ์‹œ ๋…ธ๋“œ๋Š” ์ด๋ฏธ ์•ฝ 2,039๋งŒ ๊ฐœ์˜€์Šต๋‹ˆ๋‹ค. ๋’ค์—์„œ ๋‹ค์‹œ ์ด์•ผ๊ธฐํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

5๏ธโƒฃ2์ฐจ ์žฌํ˜„(10MB): ์žฌํ˜„ ์„ฑ๊ณต

์‘๋‹ต์„ 10MB ๋กœ ์ค„์ด์ž ์ˆ˜์ง‘์€ ์ •์ƒ ์™„๋ฃŒ๋๊ณ (ํ† ํ”ฝ 134๊ฑด ๋ฐœํ–‰), 10๋ถ„ ๋’ค์™€ 30๋ถ„ ๋’ค ๋คํ”„๋„ ์˜จ์ „ํžˆ ๋–ด์Šต๋‹ˆ๋‹ค.

์‹œ์  Private Bytes GC 2์„ธ๋Œ€ ํž™ ์„œ๋ฒ„ ๊ฐ€์šฉ ๋ฉ”๋ชจ๋ฆฌ
21:16 ์›Œ๋ฐ์—… ์ค‘ 1,715 MB 1,627 MB 1,126 MB
21:20 ์ˆ˜์ง‘ ์‹œ์ž‘ 1,780 MB 1,638 MB 564 MB
21:23 ์ˆ˜์ง‘ ์ค‘ ์ตœ๊ณ ์  3,721 MB 3,355 MB 74 ~ 400 MB
21:38 +10๋ถ„ ๋คํ”„ ์ง์ „ 3,420 MB 3,087 MB 927 MB
21:43 72์ดˆ์งœ๋ฆฌ ์ „์ฒด GC ๋’ค 3,305 MB 3,034 MB 940 MB
22:11 ๊ธฐ๋ก ์ข…๋ฃŒ 3,306 MB 3,050 MB 297 MB

์ˆ˜์ง‘์ด ๋๋‚œ ๋’ค ์ „์ฒด GC ๊ฐ€ 21:41, 21:43, 22:02 ์„ธ ๋ฒˆ ๋Œ์•˜๊ณ , 21:43 ์˜ ๊ฒƒ์€ 72์ดˆ ๋™์•ˆ ์›Œ์ปค๋ฅผ ๋ฉˆ์ถ˜ blocking GC ์˜€์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ๋„ 2์„ธ๋Œ€ ํž™์€ ์•ฝ 3,034MB ์— ๊ณ ์ •๋์Šต๋‹ˆ๋‹ค. ๊ธฐ์ค€ ๋Œ€๋น„ ์•ฝ 1,407MB ๊ฐ€ GC ๋ฅผ ์„ธ ๋ฒˆ ๊ฑฐ์น˜๊ณ ๋„ ๋‚จ์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Private Bytes ์ฆ๊ฐ€ 1,585MB ์ค‘ GC ํž™ ์ปค๋ฐ‹ ์ฆ๊ฐ€๊ฐ€ 1,521MB ์˜€์œผ๋‹ˆ ๋„ค์ดํ‹ฐ๋ธŒ ๋ฉ”๋ชจ๋ฆฌ(๊ฐ€์„ค โ‘ข)๋Š” ์ฃผ ์›์ธ์ด ์•„๋‹ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ด€๋ฆฌ ํž™ ์•ˆ์— ๋ฌด์–ธ๊ฐ€๊ฐ€ ์‚ด์•„ ์žˆ๋‹ค๋Š” ๋œป์ด๊ณ , ์ด์ œ ๋คํ”„์—์„œ ์ฐพ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

6๏ธโƒฃ๋คํ”„ ๋ถ„์„: ํฐ ๊ฒƒ์—์„œ ์ž‘์€ ๊ฒƒ์œผ๋กœ

์•„๋ž˜๋Š” ์ˆ˜์ • ์ „ ์žฌํ˜„์˜ 30๋ถ„ ๋’ค ๋คํ”„๋ฅผ ๋ถ„์„ํ•œ ๊ณผ์ •์ž…๋‹ˆ๋‹ค. ๋ณด๋‹ค๊ฐ€ ์ž์„ธํ•˜๊ฒŒ ๋ฉ”๋ชจ๋ฆฌ ๋คํ”„๋ฅผ ๋ถ„์„ํ–ˆ๋˜ ๋‚ด์šฉ์€ ๋”ฐ๋กœ ๊ธ€๋กœ ์ž‘์„ฑํ•ด๋’€์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ๊ธ€์—์„œ ๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

https://programmer-may.tistory.com/286

 

๋ฉ”๋ชจ๋ฆฌ ๋คํ”„ ์ง์ ‘ ์—ด์–ด ๋ณด๊ธฐ : dotnet-dump analyze์™€ WinDbg ๋กœ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์ถ”์ ํ•˜๊ธฐ

10์›” 2์ผ ์šด์˜ ์ค‘์ธ ์Šคํฌ๋ž˜ํ•‘ ์„œ๋ฒ„์˜ ๊ฐ€์šฉ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๊ฐ‘์ž๊ธฐ ๋š ๋–จ์–ด์ง„ ๋’ค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์žฌ๊ธฐ๋™ํ•  ๋•Œ๊นŒ์ง€ ๋–จ์–ด์ง„ ์ƒํƒœ๋กœ ์œ ์ง€๊ฐ€ ๋˜๋Š” ์ผ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์›์ธ์€ ์ฝ”๋“œ ํ•œ ์ค„๊ณผ ์‚ฌ๋‚ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์—”

programmer-may.tistory.com

 

 

โ‘  ํž™์ด ์–ผ๋งˆ๋‚˜ ํฐ๊ฐ€ — eeheap -gc

๊ด€๋ฆฌ ํž™์˜ ์ „์ฒด ํฌ๊ธฐ, ์„ธ๋Œ€๋ณ„ ์˜์—ญ, GC ๋ชจ๋“œ๋ฅผ ํ•œ ๋ฒˆ์— ๋ณด์—ฌ ์ฃผ๋Š” ๋ช…๋ น์ž…๋‹ˆ๋‹ค. ์ด ๋คํ”„๊ฐ€ ์ •๋ง ๋ฌธ์ œ ์ƒํƒœ๋ฅผ ์ฐ์€ ๊ฒƒ์ธ์ง€๋ถ€ํ„ฐ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

[๊ทธ๋ฆผ 7] eeheap -gc ์•„๋ž˜์ชฝ. GC Allocated Heap Size 3,360,537,568 bytes(3.3GB)

  • Number of GC Heaps: 1 → ํž™์ด ํ•˜๋‚˜์ด๋‹ˆ Workstation GC ๊ฐ€ ๋งž์Šต๋‹ˆ๋‹ค(Server GC ๋ฉด ์ฝ”์–ด ์ˆ˜๋งŒํผ ๋‚˜์˜ต๋‹ˆ๋‹ค).
  • 2์„ธ๋Œ€(generation 2) ์˜์—ญ ์ค„์ด ํ™”๋ฉด์„ ๊ฐ€๋“ ์ฑ„์›๋‹ˆ๋‹ค. ์˜ค๋ž˜ ์‚ด์•„๋‚จ์€ ๊ฐ์ฒด๊ฐ€ ์Œ“์—ฌ ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.
  • GC Allocated Heap Size 3,360,537,568 B (์•ฝ 3.36 GB). ์ˆ˜์ง‘ ์ „ ์•ฝ 1.7GB ์˜ ๋‘ ๋ฐฐ์ž…๋‹ˆ๋‹ค.
  • Large object heap ์˜์—ญ ์ค‘ ํ•˜๋‚˜๊ฐ€ 95,991,648 B(์•ฝ 96 MB)์ธ๋ฐ, ์ด๊ฒŒ ๋’ค์—์„œ ๋‚˜์˜ฌ ๋ฒ„ํ‚ท ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค.

 

โ‘ก ๋ฌด์Šจ ํƒ€์ž…์ด ์ฐจ์ง€ํ•˜๊ณ  ์žˆ๋‚˜ — dumpheap -stat

ํž™ ์ „์ฒด๋ฅผ ํ›‘์–ด ํƒ€์ž…๋ณ„ ๊ฐœ์ˆ˜์™€ ์ด ๋ฐ”์ดํŠธ๋ฅผ ์ง‘๊ณ„ํ•ฉ๋‹ˆ๋‹ค. ํฌ๊ธฐ ์˜ค๋ฆ„์ฐจ์ˆœ์ด๋ผ ๋งจ ์•„๋ž˜๊ฐ€ ๊ฐ€์žฅ ํฐ ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

[๊ทธ๋ฆผ 8] dumpheap -stat ๋งจ ์•„๋ž˜ ๋„ค ์ค„

 

ํƒ€์ž… ๊ฐœ์ˆ˜ ์ด ํฌ๊ธฐ
System.Int32 ์•ฝ 968๋งŒ ๊ฐœ (9,677,949) 232,270,776 B (์•ฝ 232 MB)
JSKey ์•ฝ 978๋งŒ ๊ฐœ (9,778,329) 391,133,160 B (์•ฝ 391 MB)
System.String ์•ฝ 1,006๋งŒ ๊ฐœ (10,062,683) 392,637,270 B (์•ฝ 393 MB)
ConcurrentDictionary<Object, JSKey>+Node ์•ฝ 978๋งŒ ๊ฐœ (9,777,304) 469,310,592 B (์•ฝ 469 MB)
ํž™ ์ „์ฒด ์•ฝ 5,847๋งŒ ๊ฐœ (58,470,268) 3,317,109,799 B (์•ฝ 3.32 GB)

์—ฌ๊ธฐ์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ด€์ฐฐ์€ ์„œ๋กœ ๋‹ค๋ฅธ ๋„ค ํƒ€์ž…์˜ ๊ฐœ์ˆ˜๊ฐ€ ์ „๋ถ€ 970๋งŒ ~ 1,000๋งŒ์œผ๋กœ ๋น„์Šทํ•˜๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ๊ฐœ์ˆ˜๊ฐ€ ๋งž์•„๋–จ์–ด์ง€๋ฉด "ํ•˜๋‚˜๋ฅผ ๋งŒ๋“ค ๋•Œ๋งˆ๋‹ค ๋‚˜๋จธ์ง€๋„ ํ•˜๋‚˜์”ฉ ๋”ฐ๋ผ ์ƒ๊ธฐ๋Š” ๋ฌถ์Œ"์ด๋ผ๋Š” ์‹ ํ˜ธ์ž…๋‹ˆ๋‹ค. ๋„ค ์ค„๋งŒ ๋”ํ•ด๋„ ์•ฝ 1,485MB ์ž…๋‹ˆ๋‹ค.

๊ฒŒ๋‹ค๊ฐ€ System.Int32 ๊ฐ€ ํž™์— 968๋งŒ ๊ฐœ ์žˆ๋‹ค๋Š” ๊ฒƒ ์ž์ฒด๊ฐ€ ์ด์ƒํ•ฉ๋‹ˆ๋‹ค. ์ •์ˆ˜๋Š” ์›๋ž˜ ํž™ ๊ฐ์ฒด๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. object ์ž๋ฆฌ์— ๋“ค์–ด๊ฐ€๋А๋ผ ๋ฐ•์‹ฑ(boxing)๋œ ์ •์ˆ˜๋ผ๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ์ด ๋ฐ”์ดํŠธ๋ฅผ ๊ฐœ์ˆ˜๋กœ ๋‚˜๋ˆ„๋ฉด Node 48B, JSKey 40B, Int32 24B ์ž…๋‹ˆ๋‹ค.

 

โ‘ข Node ํ•˜๋‚˜๋ฅผ ์—ด์–ด ๋ณธ๋‹ค — dumpheap -mt → dumpobj

ํƒ€์ž… ์ด๋ฆ„๋งŒ์œผ๋กœ๋Š” ์•ˆ์— ๋ฌด์—‡์ด ๋“ค์—ˆ๋Š”์ง€ ๋ชจ๋ฆ…๋‹ˆ๋‹ค. Node ์ค„์˜ ์ฒซ ์—ด์ด ํƒ€์ž… ์‹๋ณ„์ž์ธ MT(MethodTable) ์ž…๋‹ˆ๋‹ค. ์ด MT ๋กœ ๊ฐ์ฒด ์ฃผ์†Œ ๋ชฉ๋ก์„ ๋ฝ‘๊ณ , ๊ทธ์ค‘ ํ•˜๋‚˜๋ฅผ ์—ด์–ด ๋ดค์Šต๋‹ˆ๋‹ค.

> dumpheap -mt 7ffe38582198 -short
> dumpobj 02c2319c4008

 

[๊ทธ๋ฆผ 9] Node ํ•˜๋‚˜. Size 48 bytes, ํ•„๋“œ๋Š” _key, _value, _next, _hashcode

 

Size 48 bytes ๋กœ ์•ž์—์„œ ๋‚˜๋ˆ  ๋ณธ ๊ฐ’๊ณผ ๊ฐ™๊ณ , ํ•„๋“œ๋Š” _key(object), _value(JSKey), _next(๋‹ค์Œ Node), _hashcode(Int32) ๋„ค ๊ฐœ์ž…๋‹ˆ๋‹ค. ๋ชฉ๋ก ์ค‘๊ฐ„์—์„œ ๊ณ ๋ฅด๊ฒŒ 22๊ฐœ๋ฅผ ๋ฝ‘์•„ ์—ด์–ด ๋ณด๋‹ˆ 21๊ฐœ์˜ ํ‚ค๊ฐ€ ์ •์ˆ˜์˜€๊ณ , ๊ฐ’์€ 1,025 ~ 9,568,797 ์‚ฌ์ด์˜€์Šต๋‹ˆ๋‹ค.

 

โ‘ฃ ๋ˆ„๊ฐ€ ๋ถ™์žก๊ณ  ์žˆ๋‚˜ — gcroot

GC ๋Š” ๋ฃจํŠธ(static ํ•„๋“œ, ์Šค๋ ˆ๋“œ ์Šคํƒ, ํ•ธ๋“ค)์—์„œ ์ฐธ์กฐ๋ฅผ ๋”ฐ๋ผ๊ฐ€ ๋‹ฟ๋Š” ๊ฐ์ฒด๋งŒ ์‚ด๋ ค ๋‘ก๋‹ˆ๋‹ค. ์–ด๋–ค ๊ฐ์ฒด๊ฐ€ ์•ˆ ์ง€์›Œ์ง„๋‹ค๋ฉด ๋ฃจํŠธ์—์„œ ๊ทธ ๊ฐ์ฒด๊นŒ์ง€ ๊ฒฝ๋กœ๊ฐ€ ์žˆ๋‹ค๋Š” ๋œป์ด๊ณ , gcroot ๊ฐ€ ๊ทธ ๊ฒฝ๋กœ๋ฅผ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค. "๋ˆ„๊ฐ€ ์ฅ๊ณ  ์žˆ๋Š”๊ฐ€"์— ์ง์ ‘ ๋‹ตํ•˜๋Š” ๋ช…๋ น์ž…๋‹ˆ๋‹ค.

> gcroot 02c2319c4008

 

[๊ทธ๋ฆผ 10] gcroot ๊ฒฐ๊ณผ. Found 1 unique roots

 

HandleTable (strong handle)
  → System.Object[]
    → ConcurrentDictionary<Object, JSKey>        (02c15e8de438)
      → ConcurrentDictionary+Tables              (02c1fa6e6b98)
        → ConcurrentDictionary+VolatileNode[]    (02c207400048)
          → ConcurrentDictionary+Node            (02c2319c4008)

์œ„์—์„œ ์•„๋ž˜๊ฐ€ ์ฐธ์กฐ ๋ฐฉํ–ฅ์ž…๋‹ˆ๋‹ค. strong handle → Object[] ๋Š” ๋Ÿฐํƒ€์ž„์ด static ํ•„๋“œ๋ฅผ ๋ณด๊ด€ํ•˜๋Š” ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค. ๋ฃจํŠธ๊ฐ€ ์ด๊ฒƒ์ด๋ฉด "static ์ด ๋ถ™์žก๊ณ  ์žˆ๋‹ค"๋Š” ๋œป์ด๊ณ , ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ ํ’€๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฒฝ๋กœ๋„ ํ•˜๋‚˜๋ฟ์ด๋‹ˆ ๋ณด์œ ์ž๋Š” ์‚ฌ์ „ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.

ConcurrentDictionary ํด๋ž˜์Šค ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์†Œ์Šค์ฝ”๋“œ๋ฅผ ์ „์ฒด ๊ฒ€์ƒ‰ ํ•ด๋ณด๋‹ˆ ์—”์ง„ ์†Œ์Šค์˜ JSKey._cache ํ•„๋“œ ์ž๋ฃŒํ˜•์ด ConcurrentDictionary ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋”•์…”๋„ˆ๋ฆฌ๊ฐ€  JSKey._cache ๋ผ๊ณ  ์ถ”์ธก ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

โ‘ค .NET 10 ConcurrentDictionary ๋Š” ์–ด๋–ป๊ฒŒ ์ƒ๊ฒผ๋‚˜

๋‹ค์Œ ๋‹จ๊ณ„๋กœ ๊ฐ€๊ธฐ ์ „์— ์‚ฌ์ „์˜ ๋‚ด๋ถ€ ๊ตฌ์กฐ๋ฅผ ์ž ๊น ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. .NET 10 ์˜ ConcurrentDictionary<TKey, TValue> ์†Œ์Šค๋ฅผ ๋ณด๋ฉด ๊ฐ์ฒด๊ฐ€ ์„ธ ๊ฒน์œผ๋กœ ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋ณธ์ฒด : _tables, _budget, _growLockArray, _comparerIsDefaultForClasses, _initialCapacity. ์‹ค์ œ ๋ฐ์ดํ„ฐ๋Š” _tables ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” Tables ์— ์žˆ์Šต๋‹ˆ๋‹ค.
  • Tables : _buckets(๋ฒ„ํ‚ท ๋ฐฐ์—ด VolatileNode[]), _locks(์ž ๊ธˆ ๊ฐ์ฒด ๋ฐฐ์—ด), _countPerLock(์ž ๊ธˆ ๊ตฌ๊ฐ„๋ณ„ ํ•ญ๋ชฉ ์ˆ˜), _comparer, _fastModBucketsMultiplier.
  • Node : ํ•ญ๋ชฉ ํ•˜๋‚˜. _key, _value, ๊ฐ™์€ ๋ฒ„ํ‚ท์— ๊ฑธ๋ฆฐ ๋‹ค์Œ ํ•ญ๋ชฉ _next, _hashcode.

๋ฒ„ํ‚ท ๋ฐฐ์—ด ์ „์ฒด๋ฅผ ์ž ๊ธˆ ๋ช‡ ๊ฐœ๋กœ ๋‚˜๋ˆ  ๋งก๊ธฐ๊ณ , ๊ฐ ์ž ๊ธˆ์ด ์ž๊ธฐ ๊ตฌ๊ฐ„์˜ ํ•ญ๋ชฉ ์ˆ˜๋ฅผ _countPerLock ์— ๋”ฐ๋กœ ์…‰๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ Count ๋Š” _countPerLock ์˜ ๊ฐ’์„ ์ „๋ถ€ ๋”ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•œ ๊ตฌ๊ฐ„์˜ ํ•ญ๋ชฉ ์ˆ˜๊ฐ€ _budget(๋ฒ„ํ‚ท ์ˆ˜ ÷ ์ž ๊ธˆ ์ˆ˜)์„ ๋„˜์œผ๋ฉด ๋ฒ„ํ‚ท ๋ฐฐ์—ด์„ ์•ฝ ๋‘ ๋ฐฐ๋กœ ํ‚ค์šฐ๊ณ , ์Šค์Šค๋กœ ์ค„์–ด๋“ค์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

 

[๊ทธ๋ฆผ 11] ๋คํ”„์—์„œ ๋”ฐ๋ผ๊ฐ„ ๊ฒฝ๋กœ๋ฅผ ๊ทธ๋ฆผ์œผ๋กœ ์˜ฎ๊ธด ๊ฒƒ. ํ‚ค ํ•˜๋‚˜๋งˆ๋‹ค Node + ๋ฐ•์‹ฑ Int32 + JSKey + String ๋ฌถ์Œ์ด ์ƒ๊น๋‹ˆ๋‹ค

 

โ‘ฅ ์‚ฌ์ „์ด ์Šค์Šค๋กœ ์„ผ ๊ฐœ์ˆ˜์™€ ๋งž์ถฐ ๋ณธ๋‹ค — dumpobj → dumparray

ํž™์—์„œ ์„ผ Node 978๋งŒ ๊ฐœ๊ฐ€ ์ •๋ง ์ „๋ถ€ ์ด ์‚ฌ์ „ ํ•˜๋‚˜์— ๋“ค์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋ ค๋ฉด, ์‚ฌ์ „์ด ์ง์ ‘ ์„ธ์–ด ๋‘” _countPerLock ์„ ์—ด์–ด ๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

> dumpobj 02c15e8de438               # ์‚ฌ์ „ ๋ณธ์ฒด → _tables ์ฃผ์†Œ
> dumpobj 000002c1fa6e6b98           # Tables → _buckets, _locks, _countPerLock ์ฃผ์†Œ
> dumparray -details 000002c1fa6e6b70

 

[๊ทธ๋ฆผ 12] ์‚ฌ์ „ ๋ณธ์ฒด์™€ Tables. _initialCapacity 1931, _budget 2,999,737

 

๋ณธ์ฒด์˜ _initialCapacity ๊ฐ€ 1931 ์ž…๋‹ˆ๋‹ค. ์—”์ง„ ์†Œ์Šค์˜ new ConcurrentDictionary<object, JSKey>(ProcessorCount(), 1931) ์™€ ๊ฐ™์•„์„œ, ์†Œ์Šค ์ชฝ์—์„œ๋„ ์ด ์‚ฌ์ „์ด _cache ์ž„์„ ํ•œ ๋ฒˆ ๋” ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค. _budget 2,999,737 ์€ ๋ฒ„ํ‚ท 11,998,949์นธ ÷ ์ž ๊ธˆ 4๊ฐœ์™€ ๋งž์Šต๋‹ˆ๋‹ค.

 

[๊ทธ๋ฆผ 13] _countPerLock ๋„ค ๊ฐ’

2,444,090 + 2,443,997 + 2,444,692 + 2,444,525 = 9,777,304

์‚ฌ์ „์ด ์Šค์Šค๋กœ ์„ผ ํ•ญ๋ชฉ ์ˆ˜๊ฐ€ dumpheap -stat ์—์„œ ์„ผ Node ์ˆ˜(9,777,304)์™€ ์ •ํ™•ํžˆ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค. 978๋งŒ ๊ฐœ Node ๋Š” ์ „๋ถ€ ์ด ์‚ฌ์ „ ํ•˜๋‚˜์— ๋“ค์–ด ์žˆ๊ณ , ๋‹ค๋ฅธ ๊ณณ์œผ๋กœ ์ƒˆ์–ด ๋‚˜๊ฐ„ ๊ฒƒ์€ ์—†์Šต๋‹ˆ๋‹ค.

 

โ‘ฆ ๋‹ค๋ฅธ ์šฉ์˜์ž๋ฅผ ์ง€์šด๋‹ค — dumpheap -stat -min 1000000

๋‚จ์€ ๊ฐ€์„ค โ‘ (ํฐ ์‘๋‹ต ๋ฌธ์ž์—ด์ด ๋ถ™์žกํ˜€ ์žˆ๋‹ค)๊ณผ โ‘ก(LOH ์กฐ๊ฐํ™”)๋ฅผ ์ง์ ‘ ํ™•์ธํ•˜๋ ค๊ณ  1MB ์ด์ƒ์ธ ๊ฐ์ฒด๋งŒ ๋ดค์Šต๋‹ˆ๋‹ค. ํฐ ๋ฌธ์ž์—ด์ด ๋‚จ์•„ ์žˆ๋‹ค๋ฉด ์—ฌ๊ธฐ ๋‚˜์˜ค๊ณ , ์กฐ๊ฐํ™”๊ฐ€ ์‹ฌํ•˜๋ฉด Free(๋นˆ ๊ณต๊ฐ„)๊ฐ€ ํฌ๊ฒŒ ๋‚˜์˜ต๋‹ˆ๋‹ค.

 

[๊ทธ๋ฆผ 14] 1MB ์ด์ƒ ๊ฐ์ฒด๋Š” 13๊ฐœ๋ฟ

  • System.String ์ค„์ด ์—†์Šต๋‹ˆ๋‹ค. 10MB ์‘๋‹ต ๋ฌธ์ž์—ด(UTF-16 ์œผ๋กœ ์•ฝ 19MB)์€ ์ด๋ฏธ ํšŒ์ˆ˜๋์Šต๋‹ˆ๋‹ค. ๊ฐ€์„ค โ‘  ์ค‘ "์‘๋‹ต ๋ฌธ์ž์—ด์„ ๋ถ™์žก๊ณ  ์žˆ๋‹ค"๋Š” ๊ธฐ๊ฐ์ž…๋‹ˆ๋‹ค.
  • Free ๋Š” 9,453,840 B(์•ฝ 9.45 MB). LOH ์•ฝ 152MB ์ค‘ ๋นˆ ๊ณต๊ฐ„์ด 10MB ๋„ ์•ˆ ๋˜๋‹ˆ ์กฐ๊ฐํ™”๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๊ฐ€์„ค โ‘ก ๋„ ๊ธฐ๊ฐ์ž…๋‹ˆ๋‹ค.
  • ๊ฐ€์žฅ ํฐ ๊ฐ์ฒด๋Š” VolatileNode[] 1๊ฐœ, 95,991,616 B(์•ฝ 96 MB). ํ•ญ๋ชฉ์ด 978๋งŒ ๊ฐœ๋ผ ์•ฝ 1,200๋งŒ ์นธ๊นŒ์ง€ ์ž๋ž€ ์‚ฌ์ „์˜ ๋ฒ„ํ‚ท ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค.

์ •๋ฆฌํ•˜๋ฉด, ํž™์— ๋‚จ์€ 1.4GB ์˜ ์ •์ฒด๋Š” static ํ•„๋“œ JSKey._cache ๊ฐ€ ๋ถ™์žก๊ณ  ์žˆ๋Š” ์ •์ˆ˜ ํ‚ค ์•ฝ 978๋งŒ ๊ฐœ์˜€์Šต๋‹ˆ๋‹ค. ์ฒ˜์Œ์— ๊ฐ€์žฅ ์œ ๋ ฅํ•˜๋‹ค๊ณ  ๋ดค๋˜ LOH ์กฐ๊ฐํ™”๋Š” ํ‹€๋ ธ์Šต๋‹ˆ๋‹ค.

 

7๏ธโƒฃ์—”์ง„ ์†Œ์Šค์—์„œ JSKey ์บ์‹œ ์ฐพ๊ธฐ

๋คํ”„๊ฐ€ ์•Œ๋ ค ์ฃผ๋Š” ๊ฒƒ์€ "์ง€๊ธˆ ๋ฌด์—‡์ด ์žˆ๊ณ  ๋ˆ„๊ฐ€ ๋ถ™์žก๊ณ  ์žˆ๋Š”๊ฐ€"๊นŒ์ง€์ž…๋‹ˆ๋‹ค. "๋ˆ„๊ฐ€ ๋งŒ๋“ค์—ˆ๋Š”๊ฐ€"๋Š” ๋‹ด๊ธฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์—”์ง„ ์†Œ์Šค์—์„œ JSKey._cache ์— ๋ฌด์—‡์ด ๋“ค์–ด๊ฐ€๋Š”์ง€ ์ฐพ์•„๋ดค์Šต๋‹ˆ๋‹ค.

JavaScript ์—์„œ a[b] ๋Š” "a ๋ผ๋Š” ๊ฐ์ฒด์—์„œ b ๋ผ๋Š” ์ด๋ฆ„์˜ ์†์„ฑ์„ ์ฝ์–ด๋ผ"์ž…๋‹ˆ๋‹ค. a ๊ฐ€ ๊ฐ์ฒด๋“  ๋ฐฐ์—ด์ด๋“  ๋ฌธ์ž์—ด์ด๋“  ๋ฌธ๋ฒ•์€ ํ•˜๋‚˜์ด๊ณ , arr[3] ๋„ ๊ทœ๊ฒฉ์ƒ์œผ๋กœ๋Š” ์ด๋ฆ„์ด "3" ์ธ ์†์„ฑ์„ ์ฝ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—”์ง„์€ ์†์„ฑ์„ ์ฐพ๊ธฐ ์ „์— ๊ทธ ์ด๋ฆ„์„ ๋‚ด๋ถ€ ํ‚ค ๊ฐ์ฒด๋กœ ๋ฐ”๊พธ๋Š”๋ฐ, ์ €ํฌ ์—”์ง„์—์„œ๋Š” ๊ทธ๊ฒŒ JSKey ์ž…๋‹ˆ๋‹ค.

// JSKey.cs - ์ œ๊ฑฐ ๋กœ์ง์ด ์—†๋Š” static ์‚ฌ์ „
private static ConcurrentDictionary<object, JSKey> _cache = new ConcurrentDictionary<object, JSKey>(ProcessorCount(), 1931);
private static JSKey[] _indexCache = new JSKey[1025];

public static JSKey Intern(int key)
{
    if (key >= 0 && key <= 1024) {
        return _indexCache[key];                                   // ์ž‘์€ ์ •์ˆ˜: ๋ฏธ๋ฆฌ ๋งŒ๋“  ๊ฒƒ ์žฌ์‚ฌ์šฉ
    }
    return _cache.GetOrAdd(key, static (o) => new JSKey((int)o));  // 1025 ์ด์ƒ: ์‚ฌ์ „์— ์˜๊ตฌ ๋“ฑ๋ก
}

 

์†์„ฑ ์ด๋ฆ„ ํ‚ค("orderNo" ๊ฐ™์€ ๊ฒƒ)๋Š” ์†Œ์Šค์— ์ ํžŒ ๋งŒํผ๋งŒ ์žˆ์–ด์„œ ์บ์‹œํ•ด ๋‘๋ฉด ์ด๋“์ด๊ณ , ์‹ค์ œ๋กœ ์•ฝ 10๋งŒ ๊ฐœ์—์„œ ๋ฉˆ์ถฅ๋‹ˆ๋‹ค. ๋ฌธ์ œ๋Š” ์ด ์ „์ œ๋ฅผ ๊นจ๋Š” ํ‚ค, ์ฆ‰ ์ž…๋ ฅ ๋ฐ์ดํ„ฐ์˜ ๊ธธ์ด๋งŒํผ ์ข…๋ฅ˜๊ฐ€ ๋Š˜์–ด๋‚˜๋Š” ์ •์ˆ˜ ํ‚ค๊ฐ€ ๊ฐ™์€ ์บ์‹œ์— ๋“ค์–ด์˜ฌ ๋•Œ์ž…๋‹ˆ๋‹ค. 0 ~ 1024 ๋Š” ๊ณ ์ • ๋ฐฐ์—ด์ด ์ฒ˜๋ฆฌํ•˜์ง€๋งŒ 1,025 ์ด์ƒ์€ ์ „๋ถ€ _cache ์— ์˜๊ตฌ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค. ์‚ฌ์ „์˜ ํ‚ค ํƒ€์ž…์ด object ๋ผ์„œ ์ •์ˆ˜๋Š” ๋ฐ•์‹ฑ๋˜๊ณ , JSKey ๋Š” ์ •์ˆ˜๋ฅผ ๋ฌธ์ž์—ด๋กœ๋„ ๋“ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋คํ”„์—์„œ ๋ณธ Node · Int32 · JSKey · String ๋„ค ๋ฌถ์Œ์ด ์ •ํ™•ํžˆ ์ด๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

[๊ทธ๋ฆผ 15] ์†์„ฑ์ด๋ฆ„ํ‚ค๋Š” ๋ฏธ๋ฆฌ ์บ์‹ฑ, ์ •์ˆ˜ ์ธ๋ฑ์Šค ํ‚ค๋Š” ๋งค๋ฒˆ ์บ์‹ฑ. ์‹ฌ์ง€์–ด ์บ์‹ฑ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋‹ค๋ฉด ๋งค๋ฒˆ ์ƒ์„ฑ ํ›„ ์บ์‹ฑ

 

๊ธ€์ž ํ•˜๋‚˜์— ์ƒ๊ธฐ๋Š” ๊ฐ์ฒด ํฌ๊ธฐ ์™œ ์ƒ๊ธฐ๋‚˜
Node 48 B ์‚ฌ์ „์˜ ํ•ญ๋ชฉ ํ•˜๋‚˜
๋ฐ•์‹ฑ๋œ Int32 24 B ํ‚ค ํƒ€์ž…์ด object ๋ผ์„œ ์ •์ˆ˜๋ฅผ ํฌ์žฅ
JSKey 40 B ์บ์‹œ์˜ ๊ฐ’
String ์•ฝ 36 B ์ •์ˆ˜๋ฅผ "2954227" ๊ฐ™์€ ๋ฌธ์ž์—ด๋กœ๋„ ๋ณด๊ด€
๋ฒ„ํ‚ท ๋ฐฐ์—ด ์ง€๋ถ„ ์•ฝ 10 B ์•ฝ 96MB ๋ฐฐ์—ด์„ ํ•ญ๋ชฉ ์ˆ˜๋กœ ๋‚˜๋ˆˆ ๋ชซ
ํ•ฉ๊ณ„ ์•ฝ 158 B ์‘๋‹ต 100๋งŒ ๊ธ€์ž๋‹น ์•ฝ 150MB ๊ฐ€ ์˜๊ตฌ ์ ์œ 

 

 

8๏ธโƒฃ๊ณ ๋„๋ชฐ ์ˆ˜์ง‘ ๋กœ์ง์—์„œ str[i] ์ฐพ๊ธฐ

์ด์ œ ๊ณ ๋„๋ชฐ ์ˆ˜์ง‘ ๊ฒฝ๋กœ์—์„œ 1,025 ์ด์ƒ ์ •์ˆ˜๋กœ ๋ฌด์–ธ๊ฐ€[i] ์— ์ ‘๊ทผํ•˜๋Š” ๊ณณ์„ ์ฐพ์•„์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋กœ์ง์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ ํ›‘์–ด ๋ณด๋Š” ์™€์ค‘ ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ ์ค‘์—  ์‘๋‹ต ์ „์ฒด๋ฅผ ๊ธ€์ž ๋‹จ์œ„๋กœ ๋„๋Š” ์ฝ”๋“œ๋Š” XML ์˜ ์ž˜๋ชป๋œ ๋ฌธ์ž๋ฅผ ๊ฑธ๋Ÿฌ ๋‚ด๋Š” filterBadXMLCharactors ํ•จ์ˆ˜ ํ•˜๋‚˜๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. 1์ฐจ ์žฌํ˜„์˜ ์ค‘๊ฐ„ ๋คํ”„๋ฅผ clrstack -all ๋กœ ๋ณด๋‹ˆ ์ˆ˜์ง‘ ์Šค๋ ˆ๋“œ๋„ ์ •ํ™•ํžˆ ์ด ํ•จ์ˆ˜ ์•ˆ์— ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

// ์ˆ˜์ • ์ „
for (let i = 0; i < xml_string.length; i++) {
    current = xml_string.charCodeAt(i);          // ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ. i ๋Š” ์ธ์ž์ผ ๋ฟ → ํ‚ค๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์Œ
    if (_.vIsEquals(current, [0x9, 0xa, 0xd]) || (current >= 0x20 && current <= 0xd7ff) || ...) {
        filtered_string.append(xml_string[i]);   // ์†์„ฑ ์ ‘๊ทผ. i ๊ฐ€ ์†์„ฑ ํ‚ค๊ฐ€ ๋จ → 1,025 ์ด์ƒ์ด๋ฉด ์˜๊ตฌ ๋“ฑ๋ก
    }
}

 

[๊ทธ๋ฆผ 16] ๋Œ€๊ด„ํ˜ธ ์ ‘๊ทผ ํ•œ ๋ฒˆ์ด ์ง€๋‚˜๋Š” ๊ธธ. charCodeAt(i) ๋Š” ๋ฉ”์„œ๋“œ ์ธ์ž๋ผ ์ด ๊ธธ์„ ํƒ€์ง€ ์•Š์Šต๋‹ˆ๋‹ค

 

10MB ์งœ๋ฆฌ XML ์‘๋‹ต ๋ฌธ์ž์—ด์„ ํ•œ ๊ธ€์ž์”ฉ xml_string[i] ๋กœ ์ฝ์œผ๋ฉด์„œ, ๊ธ€์ž ๋ฒˆํ˜ธ๋งˆ๋‹ค JSKey ๋ฅผ ํ•˜๋‚˜์”ฉ ๋งŒ๋“ค์–ด static ์‚ฌ์ „์— ๋„ฃ๊ณ  ์žˆ๋˜ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์ถ”๋ก ์„ ์ˆซ์ž๋กœ ๊ฒ€์ฆํ•ด ๋ดค์Šต๋‹ˆ๋‹ค.

 

 

๋‹ค๋งŒ ํž™ ๋คํ”„์—๋Š” ํ‚ค๊ฐ€ ์–ธ์ œ ๋“ค์–ด์™”๋Š”์ง€ ๊ธฐ๋ก๋˜์ง€ ์•Š๊ณ , ๊ฐ™์€ ์‚ฌ์ „์— ์†์„ฑ ์ด๋ฆ„ ํ‚ค๊นŒ์ง€ ์„ž์—ฌ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ 10MB ์žฌํ˜„ ๋•Œ๋Š” ์ˆ˜์ง‘ ์ „ ๋คํ”„๋ฅผ ๋น ๋œจ๋ ค์„œ, Node ์ˆ˜๋ฅผ ๋นผ์„œ ๋น„๊ตํ•˜๋ฉด ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์˜ ๊ธฐ์ค€๊ฐ’์„ ์จ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ •์ˆ˜ ํ‚ค์—๋งŒ ์ƒ๊ธฐ๋Š” ๋ฐ•์‹ฑ๋œ Int32 ๊ฐœ์ˆ˜๋กœ ๋งž์ถฐ ๋ดค์Šต๋‹ˆ๋‹ค. ์‚ฌ์ „์˜ ํ‚ค ํƒ€์ž…์ด object ๋ผ์„œ ์ •์ˆ˜ ํ‚ค๋งˆ๋‹ค ๋ฐ•์‹ฑ ๊ฐ์ฒด๊ฐ€ ํ•˜๋‚˜์”ฉ ์ƒ๊ธฐ๊ณ , ๋ฌธ์ž์—ด ํ‚ค์—๋Š” ์ƒ๊ธฐ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

ํ•ญ๋ชฉ ๊ฐ’
10MB ์‘๋‹ต์˜ ๊ธ€์ž ์ˆ˜ ์•ฝ 967๋งŒ ๊ฐœ (9,673,214)
์˜ˆ์ธกํ•œ ์ •์ˆ˜ ํ‚ค ์ˆ˜ : ๊ธ€์ž ์ˆ˜ − 1,025 (๊ณ ์ • ๋ฐฐ์—ด ๋ชซ) ์•ฝ 967๋งŒ ๊ฐœ (9,672,189)
์‹ค์ธก : ์ˆ˜์ • ์ „ 30๋ถ„ ๋’ค ๋คํ”„์˜ ๋ฐ•์‹ฑ Int32 ์•ฝ 968๋งŒ ๊ฐœ (9,677,949)
์‹ค์ธก − ์˜ˆ์ธก 5,760๊ฐœ
์ฐธ๊ณ  : ์ˆ˜์ • ํ›„ ๋คํ”„ 3์žฅ์˜ ๋ฐ•์‹ฑ Int32 (์ •์ˆ˜ ํ‚ค๊ฐ€ ์Œ“์ด์ง€ ์•Š์€ ํ‰์†Œ ๊ฐ’) 5,420 ~ 6,201๊ฐœ

์‹ค์ธก์ด ์˜ˆ์ธก๋ณด๋‹ค 5,760๊ฐœ ๋งŽ์€๋ฐ, ์ด ์ฐจ์ด๊ฐ€ ํ‰์†Œ ๋ฐ•์‹ฑ Int32 ๊ฐœ์ˆ˜ ๋ฒ”์œ„ ์•ˆ์— ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. ์ฆ‰ "์ •์ˆ˜ ํ‚ค ์•ฝ 967๋งŒ ๊ฐœ + ํ‰์†Œ์— ์žˆ๋˜ Int32 ์•ฝ 5,800๊ฐœ"๋กœ ์„ค๋ช…๋ฉ๋‹ˆ๋‹ค. ํ‰์†Œ ๊ฐ’์€ ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์—์„œ ๋นŒ๋ ค ์˜จ ๊ฒƒ์ด๋ผ ํ‚ค๋ฅผ ํ•˜๋‚˜ํ•˜๋‚˜ ์„ผ ์ฆ๋ช…์€ ์•„๋‹ˆ์ง€๋งŒ, ์•ฝ 967๋งŒ์ด๋ผ๋Š” ๊ทœ๋ชจ๊ฐ€ ์‘๋‹ต ๊ธ€์ž ์ˆ˜์™€ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค. "์‘๋‹ต ๋ฌธ์ž์—ด ์ „์ฒด๋ฅผ 0 ๋ถ€ํ„ฐ ๋๊นŒ์ง€ [i] ๋กœ ์ฝ์€ ๋ฃจํ”„"๋กœ ๋ฒ”์œ„๋ฅผ ์ขํžˆ๊ธฐ์—๋Š” ์ถฉ๋ถ„ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

 

์ด ๋ˆ„์ˆ˜๋Š” ํšŸ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ผ "์ง€๊ธˆ๊นŒ์ง€ ์ฒ˜๋ฆฌํ•œ ๊ฐ€์žฅ ๊ธด ๋ฌธ์ž์—ด"์— ๋น„๋ก€ํ•œ๋‹ค๋Š” ์ ๋„ ํŠน์ดํ•ฉ๋‹ˆ๋‹ค. ํ‚ค๊ฐ€ ๊ธ€์ž ๋ฒˆํ˜ธ๋ผ์„œ ๊ฐ™์€ ๊ธธ์ด๋ฅผ ๋‹ค์‹œ ์ฒ˜๋ฆฌํ•˜๋ฉด ์ด๋ฏธ ์žˆ๋Š” ํ‚ค๋ฅผ ์”๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ํ‰์†Œ ์ž‘์—…์œผ๋กœ๋Š” ์ „ํ˜€ ๋Š˜์ง€ ์•Š๋‹ค๊ฐ€, ์œ ๋‚œํžˆ ๊ธด ์‘๋‹ต์ด ํ•œ ๋ฒˆ ๋“ค์–ด์˜ฌ ๋•Œ๋งŒ ๊ณ„๋‹จ์ฒ˜๋Ÿผ ์˜ค๋ฆ…๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๋Œ€ ์ค‘ 3๋ฒˆ ์„œ๋ฒ„๋งŒ ๊ทธ๋žฌ๋˜ ๊ฒƒ๋„ ๊ทธ ๋Œ€๋Ÿ‰ ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•œ ์„œ๋ฒ„๊ฐ€ 3๋ฒˆ๋ฟ์ด์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

9๏ธโƒฃ์ˆ˜์ •: ๋ฌธ์ž์—ด์„ ์ธ๋ฑ์Šค ํ‚ค๋กœ ์ฝ์ง€ ์•Š๊ฒŒ ๋ฐ”๊พธ๊ธฐ

"์ด๊ฒŒ ๋ฌธ์ œ๋‹ˆ ๋นผ์ž"๋กœ ๋๋‚ด๊ธฐ ์ „์—, ์ด ํ•„ํ„ฐ๊ฐ€ ์™œ ๋“ค์–ด์™”๋Š”์ง€๋ถ€ํ„ฐ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์ „์— ๊ณ ๊ฐ์ด ์ฃผ๋ฌธ ์ƒํ’ˆ๋ช…์— XML ์— ์˜ฌ ์ˆ˜ ์—†๋Š” ์ œ์–ด ๋ฌธ์ž(0x08 ๋“ฑ)๋ฅผ ๋„ฃ์–ด XML ํŒŒ์‹ฑ ์˜ˆ์™ธ๊ฐ€ ๋‚œ ์ผ์ด ์žˆ์—ˆ๊ณ , ๊ทธ๋Ÿฐ ๋ฌธ์ž๋ฅผ ๋ฏธ๋ฆฌ ๊ฑธ๋Ÿฌ ๋‚ด๋ ค๊ณ  ๋„ฃ์€ ํ•จ์ˆ˜์˜€์Šต๋‹ˆ๋‹ค. ๋ชฉ์ ์€ ํ•„์š”ํ–ˆ๊ณ , ๋ฌธ์ œ๋Š” ๊ตฌํ˜„ ๋ฐฉ์‹๊ณผ "ํ•ญ์ƒ ํ˜ธ์ถœ"ํ•˜๋Š” ์กฐ๊ฑด์ด์—ˆ์Šต๋‹ˆ๋‹ค.

์•ˆ ํŒ๋‹จ
xml_string[i] → charAt(i) ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์ด๋ผ ํ‚ค๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์•„ ๋ˆ„์ˆ˜๋Š” ๋ง‰ํž™๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ธ€์ž ๋‹จ์œ„ ๋ฐ˜๋ณต๋ฌธ๊ณผ "ํ•ญ์ƒ ํ˜ธ์ถœ"์€ ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค.
์ฑ„ํƒ ๋จผ์ € ํŒŒ์‹ฑํ•˜๊ณ , ์‹คํŒจํ–ˆ์„ ๋•Œ๋งŒ ์ •๊ทœ์‹์œผ๋กœ ๊ธˆ์ง€ ๋ฌธ์ž๋ฅผ ์ง€์šด ๋’ค ํ•œ ๋ฒˆ ๋” ํŒŒ์‹ฑํ•ฉ๋‹ˆ๋‹ค. ์ •์ƒ ์‘๋‹ต์€ ๋ฐ˜๋ณต๋ฌธ๋„ ์น˜ํ™˜๋„ ๊ฑฐ์น˜์ง€ ์•Š๊ณ , ์ •๊ทœ์‹ ์น˜ํ™˜์€ ์—”์ง„์˜ C# ์ชฝ์—์„œ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌ๋˜์–ด JS ํ‚ค๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
// ์ˆ˜์ • ํ›„ (์š”์ง€)
private static readonly INVALID_XML_CHARS = /[\x00-\x08\x0B\x0C\x0E-\x1F๏ฟพ๏ฟฟ]/g;

static parseXml(response_body: string): XmlDocument {
    try {
        return ShoppingUtil.loadXml(xml_string);                                    // โ‘  ์ •์ƒ ์‘๋‹ต์€ ์—ฌ๊ธฐ์„œ ๋
    } catch {
        const stripped = xml_string.replace(ShoppingUtil.INVALID_XML_CHARS, '');   // โ‘ก ์‹คํŒจํ–ˆ์„ ๋•Œ๋งŒ ๊ธˆ์ง€ ๋ฌธ์ž ์ œ๊ฑฐ
        return ShoppingUtil.loadXml(stripped);
    }
}

 

์‡ผํ•‘๋ชฐ๋งˆ๋‹ค ๊ฐ์ž ๊ฐ–๊ณ  ์žˆ๋˜ XML ํŒŒ์‹ฑ ์œ ํ‹ธ๋„ ์ด ๊ณตํ†ต parseXml ํ•˜๋‚˜๋กœ ๋ชจ์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด ์ˆ˜์ •์„ ๋‹ค์‹œ ํ…Œ์ŠคํŠธ ์„œ๋ฒ„์— ๋ฐฐํฌํ•ด์„œ, ์œ ์ถ”ํ•œ ์›์ธ์ด ์ง„์งœ ์›์ธ์ด ๋งž๋Š”์ง€ ๊ฐ™์€ ์‹œ๋‚˜๋ฆฌ์˜ค๋กœ ๋˜‘๊ฐ™์ด ๊ฒ€์ฆํ–ˆ์Šต๋‹ˆ๋‹ค.

 

 

 

๐Ÿ“Š๊ฒฐ๊ณผ ๋ฐ ์„ฑ๊ณผ

 

1๏ธโƒฃ๊ฐ™์€ ์กฐ๊ฑด ์žฌ๊ฒ€์ฆ: ๋…ผ๋ฆฌ์  ๋ˆ„์ˆ˜ 99% ์ œ๊ฑฐ

์กฐ๊ฑด์€ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ฐ™์€ ํ…Œ์ŠคํŠธ ์„œ๋ฒ„, ๋ชฉ์„œ๋ฒ„์˜ ๊ฐ™์€ 10MB ์‘๋‹ต(์ฃผ๋ฌธ 670๊ฐœ, ์ˆ˜์ง‘ 1,340ํ–‰)์ž…๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์‘๋‹ต ์•ˆ์— 0x08 ์„ ์ผ๋ถ€๋Ÿฌ ๋„ฃ์–ด์„œ ์ฒซ ํŒŒ์‹ฑ์ด ์‹คํŒจํ•˜๊ณ  ์ •๊ทœ์‹ ๊ฒฝ๋กœ๋ฅผ ํƒ€๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰ ๊ณ ์นœ ์ฝ”๋“œ๊ฐ€ ์‹ค์ œ๋กœ ์‹คํ–‰๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์Ÿ€์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ์—๋Š” ์ˆ˜์ง‘ ์ „, 10๋ถ„ ๋’ค, 30๋ถ„ ๋’ค ๋คํ”„ ์„ธ ๊ฐœ๋ฅผ ๋ชจ๋‘ ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค์—์„œ ๋–ด์Šต๋‹ˆ๋‹ค.

 

[๊ทธ๋ฆผ 17] ์ˆ˜์ง‘ ์‹œ์ž‘์„ 0๋ถ„์œผ๋กœ ๋งž์ถฐ ๊ฒน์นœ Private Bytes. ๋นจ๊ฐ•์ด ์ˆ˜์ • ์ „, ์ดˆ๋ก์ด ์ˆ˜์ • ํ›„์ž…๋‹ˆ๋‹ค

 

์ˆ˜์ • ์ „์€ 2๋ถ„ ๋งŒ์— 3,722MB ๊นŒ์ง€ ์˜ฌ๋ผ 30๋ถ„ ๋’ค์—๋„ 3,300MB ์— ๋จธ๋ฌผ๋ €๊ณ , ์ˆ˜์ • ํ›„๋Š” 1,915MB ๊นŒ์ง€ ์ž ๊น ์˜ฌ๋ž๋‹ค๊ฐ€ 30์ดˆ ์•ˆ์— ์ œ์ž๋ฆฌ๋กœ ๋Œ์•„์™”์Šต๋‹ˆ๋‹ค.

์ง€ํ‘œ ์ˆ˜์ • ์ „ ์ˆ˜์ • ํ›„ ๋ณ€ํ™”
์บ์‹œ Node ์ฆ๊ฐ€ (์›์ธ) +์•ฝ 967๋งŒ ๊ฐœ (+9,671,798) +548๊ฐœ 99.99% ๊ฐ์†Œ
์บ์‹œ ๋ฒ„ํ‚ท ๋ฐฐ์—ด 95,991,616 B (์•ฝ 96 MB) 1,251,520 B (์•ฝ 1.25 MB, ๊ธฐ๋™ ๋•Œ ๊ทธ๋Œ€๋กœ) 98.7% ๊ฐ์†Œ
GC ํž™ ์ฆ๊ฐ€ (์ˆ˜์ง‘ ์ „ → 30๋ถ„ ๋’ค) +1,480 MB +11 MB 99.3% ๊ฐ์†Œ
Private Bytes ์ฆ๊ฐ€ (์ˆ˜์ง‘ ์ „ → 30๋ถ„ ๋’ค) +1,520 MB +39 MB 97.4% ๊ฐ์†Œ
Private Bytes ์ตœ๊ณ ์  3,721 MB 1,915 MB 48.5% ๊ฐ์†Œ
์ˆ˜์ง‘ ๊ตฌ๊ฐ„ 2์„ธ๋Œ€ GC ๋ฉˆ์ถค ํ•ฉ๊ณ„ 40.6์ดˆ (์ตœ์žฅ 19.6์ดˆ) 5.7์ดˆ (์ตœ์žฅ 3.2์ดˆ) 86.0% ๊ฐ์†Œ
์ˆ˜์ง‘ ๋’ค ์ „์ฒด GC 72์ดˆ์งœ๋ฆฌ 1ํšŒ ์—†์Œ –
์ˆ˜์ง‘ ๊ตฌ๊ฐ„ ํ• ๋‹น๋Ÿ‰ 6.86 GB 0.31 GB 95.5% ๊ฐ์†Œ
์ €์žฅ๋œ ์ˆ˜์ง‘ ํ–‰ 1,340 1,340 (ํŠน์ˆ˜ ๋ฌธ์ž 11๊ฑด ๊ธฐ๋Œ€๊ฐ’๊ณผ ์ผ์น˜) ๊ธฐ๋Šฅ ๋™์ผ

์ˆ˜์ง‘์ด ๋๋‚œ ๋’ค์—๋„ ๋‚จ๋˜ GC ํž™ 1,480MB ๊ฐ€ 11MB ๋กœ ์ค„์—ˆ์œผ๋‹ˆ ๋…ผ๋ฆฌ์  ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์˜ 99.3% ๋ฅผ ์—†์•ค ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚จ์€ 11MB ๋„ ์บ์‹œ์™€๋Š” ๊ด€๊ณ„๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์บ์‹œ Node ๋Š” 548๊ฐœ ๋Š˜์—ˆ๊ณ  10๋ถ„ ๋’ค์™€ 30๋ถ„ ๋’ค๊ฐ€ ๊ฐ™์•˜์Šต๋‹ˆ๋‹ค. ์‘๋‹ต ๊ธ€์ž ์ˆ˜ 967๋งŒ๊ณผ ๋ฌด๊ด€ํ•œ ์ˆ˜๋ผ์„œ, ๊ณ ๋„๋ชฐ ํ”Œ๋Ÿฌ๊ทธ์ธ ์ฝ”๋“œ๊ฐ€ ์ด ์›Œ์ปค์—์„œ ์ฒ˜์Œ ์‹คํ–‰๋˜๋ฉฐ ๋“ฑ๋ก๋œ ์†์„ฑ ์ด๋ฆ„์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

๊ธฐ๋Šฅ๋„ ๊นจ์ง€์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์‘๋‹ต์— ์‹ฌ์–ด ๋‘” ํŠน์ˆ˜ ๋ฌธ์ž ์ผ€์ด์Šค 11๊ฑด(0x08, 0x01·0x0B·0x0C·0x1F, CDATA ์•ˆ์˜ &, ๊ฒฐํ•ฉ ์ด๋ชจ์ง€, ํƒญ·์ค„๋ฐ”๊ฟˆ, U+200B·U+FEFF ๋“ฑ)์„ DB ์—์„œ ๊บผ๋‚ด ์ฝ”๋“œํฌ์ธํŠธ ๋‹จ์œ„๋กœ ๋Œ€์กฐํ–ˆ๊ณ , ๊ธˆ์ง€ ๋ฌธ์ž๋งŒ ์ง€์›Œ์ง€๊ณ  ๋‚˜๋จธ์ง€๋Š” ๊ทธ๋Œ€๋กœ ๋“ค์–ด์™”์Šต๋‹ˆ๋‹ค.

 

2๏ธโƒฃ๋คํ”„๋กœ ๋‹ค์‹œ ํ™•์ธ: ์ฆ์ƒ์ด ์•„๋‹ˆ๋ผ ์›์ธ์ด ์‚ฌ๋ผ์กŒ๋‹ค

"๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์•ˆ ๋Š˜์—ˆ๋‹ค"๋งŒ ๋ณด๊ณ  ๋๋‚ผ ์ˆ˜๋„ ์žˆ์—ˆ์ง€๋งŒ, ๋ฉ”๋ชจ๋ฆฌ๋Š” ์—ฌ๋Ÿฌ ์ด์œ ๋กœ ์•ˆ ๋Š˜ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ˆ˜์ • ์ „๊ณผ ์ˆ˜์ • ํ›„์˜ 30๋ถ„ ๋’ค ๋คํ”„๋ฅผ ์ฐฝ ๋‘ ๊ฐœ์— ๋‚˜๋ž€ํžˆ ์—ด๊ณ  ๊ฐ™์€ ๋ช…๋ น์„ ์ณค์Šต๋‹ˆ๋‹ค.

[๊ทธ๋ฆผ 18] dumpheap -stat ๋น„๊ต. ์™ผ์ชฝ์ด ์ˆ˜์ • ์ „, ์˜ค๋ฅธ์ชฝ์ด ์ˆ˜์ • ํ›„์ž…๋‹ˆ๋‹ค

 

ํ•ญ๋ชฉ ์ˆ˜์ • ์ „ ์ˆ˜์ • ํ›„ ๋ณ€ํ™”
ํž™ ๊ฐ์ฒด ์ˆ˜ ์•ฝ 5,847๋งŒ ๊ฐœ (58,470,268) ์•ฝ 1,951๋งŒ ๊ฐœ (19,513,305) 66.6% ๊ฐ์†Œ
ํž™ ํฌ๊ธฐ 3,317,109,799 B (์•ฝ 3.32 GB) 1,808,771,066 B (์•ฝ 1.81 GB) 45.5% ๊ฐ์†Œ
JSKey ์•ฝ 978๋งŒ ๊ฐœ (9,778,329) ์•ฝ 10๋งŒ ๊ฐœ (106,631) 98.9% ๊ฐ์†Œ
์บ์‹œ Node ์•ฝ 978๋งŒ ๊ฐœ (9,777,304) ์•ฝ 10๋งŒ ๊ฐœ (105,606) 98.9% ๊ฐ์†Œ

์˜ค๋ฅธ์ชฝ์—๋Š” Int32·JSKey·String·Node ๋„ค ์ค„์ด ๋งจ ์•„๋ž˜์—์„œ ์‚ฌ๋ผ์ง€๊ณ , ๊ธฐ๋™ ๋•Œ ์ฝ์€ JS ๋ชจ๋“ˆ์˜ ๊ตฌ๋ฌธ ํŠธ๋ฆฌ(AST) ํƒ€์ž…์ด ๋งจ ์•„๋ž˜๋ฅผ ์ฐจ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒŒ ์ด ์›Œ์ปค์˜ ์ •์ƒ ์ƒํƒœ์ž…๋‹ˆ๋‹ค. ์–‘์ชฝ์—์„œ ๋ณ€ํ•˜์ง€ ์•Š์•„์•ผ ํ•  AST ๋ฆฌํ„ฐ๋Ÿด ๊ฐ์ฒด ์ˆ˜(์•ฝ 144๋งŒ ๊ฐœ)๊ฐ€ ๊ฑฐ์˜ ๊ฐ™๋‹ค๋Š” ์ ์ด, ๋‘ ๋คํ”„๋ฅผ ๋‚˜๋ž€ํžˆ ๋น„๊ตํ•ด๋„ ๋œ๋‹ค๋Š” ๊ทผ๊ฑฐ์ž…๋‹ˆ๋‹ค.

[๊ทธ๋ฆผ 19] dumpheap -stat -min 1000000 ๋น„๊ต. ๋ฒ„ํ‚ท ๋ฐฐ์—ด์ด ๊ธฐ๋™ ๋•Œ ํฌ๊ธฐ ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค

์›์ธ์ด๋ผ๊ณ  ์ง€๋ชฉํ•œ ๋ฐ”๋กœ ๊ทธ ๊ฐ์ฒด(์บ์‹œ Node)์˜ ์ฆ๊ฐ€๊ฐ€ ์•ฝ 967๋งŒ ๊ฐœ → 548๊ฐœ๋กœ ๋ฐ”๋€ ๊ฒƒ์„ ํ™•์ธํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, "์›์ธ์ด ์‚ฌ๋ผ์ ธ์„œ ์ฆ์ƒ์ด ์‚ฌ๋ผ์กŒ๋‹ค"๊ณ  ๋งํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

3๏ธโƒฃ์šด์˜ ๋ฐฐํฌ ํ›„ 3๋ฒˆ ์„œ๋ฒ„ ๊ฐ€์šฉ ๋ฉ”๋ชจ๋ฆฌ

์ˆ˜์ •์„ ์šด์˜ ์Šคํฌ๋ž˜ํ•‘ ์„œ๋ฒ„์— ๋ฐฐํฌํ•œ ๋’ค, ๋ฐฐํฌ ์ „(10์›” 13์ผ 15์‹œ)๊ณผ ๋ฐฐํฌ ํ›„(10์›” 14์ผ 15์‹œ) ๊ฐ™์€ ์‹œ๊ฐ์˜ Free Memory ๋ฅผ ๋น„๊ตํ•ด ๋ณด๋ฉด 3๋ฒˆ ์„œ๋ฒ„์˜ ๊ฐ€์šฉ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ 584 MiB → 1.20 GiB(์•ฝ 1,229 MiB), ์•ฝ 2.1๋ฐฐ๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

[๊ทธ๋ฆผ 20] ๋ฐฐํฌ ์ „(10/13 15์‹œ)๊ณผ ๋ฐฐํฌ ํ›„(10/14 15์‹œ)์˜ Free Memory

 

๋‹ค๋งŒ ๊ฐ™์€ ์‹œ๊ฐ ๋‹ค๋ฅธ ์„œ๋ฒ„๋“ค์˜ ๊ฐ’๋„ ํ•จ๊ป˜ ์˜ฌ๋ผ์„œ, ์ด ๊ทธ๋ฆผ ํ•œ ์žฅ์„ ์ˆ˜์ • ํšจ๊ณผ์˜ ์ฆ๊ฑฐ๋กœ ์‚ผ์ง€๋Š” ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํšจ๊ณผ์˜ ๊ทผ๊ฑฐ๋Š” ์•ž์˜ ๊ฐ™์€ ์กฐ๊ฑด ์žฌ๊ฒ€์ฆ๊ณผ ๋คํ”„ ๋น„๊ต์ด๊ณ , ์šด์˜์—์„œ๋Š” 3๋ฒˆ ์„œ๋ฒ„๊ฐ€ ๋‹ค๋ฅธ ์„œ๋ฒ„๋“ค๊ณผ ๋น„์Šทํ•œ ๋ฒ”์œ„(1.20 / 1.37 / 1.44 GiB)๋กœ ๋Œ์•„์˜จ ๊ฒƒ์„ ํ™•์ธํ•œ ์ •๋„๋กœ ๋ด ์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

4๏ธโƒฃ์—”์ง„ ํŒ€์— ๊ฑด์˜: 1,024 ๋ฅผ ๋„˜๋Š” ์ •์ˆ˜ ํ‚ค๋Š” ์บ์‹ฑํ•˜์ง€ ์•Š๊ธฐ๋กœ

๋น„์ฆˆ๋‹ˆ์Šค ์ฝ”๋“œ๋ฅผ ๊ณ ์นœ ๊ฒƒ์€ ๊ธ‰ํ•œ ๋ถˆ์„ ๋ˆ ๊ฒƒ์ด๊ณ , ๊ทผ๋ณธ ์›์ธ์€ ์—”์ง„์— ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. str[i] ๋Š” ES5 ๋ถ€ํ„ฐ ํ‘œ์ค€์ธ ๊ฐ€์žฅ ํ”ํ•œ ํ‘œ๊ธฐ์ด๊ณ , Node.js ๋‚˜ ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” 10MB ๋ฌธ์ž์—ด์„ str[i] ๋กœ ๋Œ์•„๋„ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์Œ“์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. V8 ์€ ์ •์ˆ˜ ์ธ๋ฑ์Šค ์†์„ฑ์„ ์ด๋ฆ„ ์žˆ๋Š” ์†์„ฑ(named properties)๊ณผ ๋”ฐ๋กœ "elements" ๋กœ ๋‹ค๋ฃจ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ €ํฌ ์ชฝ์€ ๋ˆ„๊ตฌ๋“  ํ‰๋ฒ”ํ•˜๊ฒŒ str[i] ๋‚˜ arr[i] ๋กœ ํฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋„๋Š” ์ˆœ๊ฐ„ ๊ฐ™์€ ์ผ์ด ์žฌ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ์˜€์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์—”์ง„์„ ๋‹ด๋‹นํ•˜๋Š” ํŒ€์— ์กฐ์‚ฌ ๋‚ด์šฉ๊ณผ ํ•จ๊ป˜ ์ด๋ ‡๊ฒŒ ๊ฑด์˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

์†์„ฑ ์ด๋ฆ„ ํ‚ค๋ฅผ ์ธํ„ฐ๋‹ํ•˜๋Š” ๊ฑด ๊ฐ™์€ ์ด๋ฆ„์ด ์š”์ฒญ๋งˆ๋‹ค ๋ฐ˜๋ณต๋˜๋‹ˆ ์ด๋“์ด์ง€๋งŒ, ํฐ ์ •์ˆ˜ ํ‚ค๋Š” ์ธํ„ฐ๋‹์ด ๊ธฐ๋Œ€๋Š” ๋‘ ์ „์ œ(ํ‚ค์˜ ์ข…๋ฅ˜๊ฐ€ ์œ ํ•œํ•˜๋‹ค, ๊ฐ™์€ ํ‚ค๊ฐ€ ๋ฐ˜๋ณตํ•ด์„œ ์“ฐ์ธ๋‹ค)๋ฅผ ๋ชจ๋‘ ๋งŒ์กฑํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. 1,025 ์ด์ƒ ์ •์ˆ˜ ํ‚ค๋ฅผ ์˜๊ตฌ ์บ์‹œ์— ๋‘๋Š” ๊ฒŒ ์˜๋„ํ•œ ์„ค๊ณ„์ธ์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

 

์—”์ง„ ํŒ€์—์„œ ๋‚ด๋ถ€ ๋…ผ์˜๋ฅผ ๊ฑฐ์นœ ๊ฒฐ๊ณผ, ์ •์ˆ˜ ํ‚ค๋Š” 1,024 ๋ฅผ ๋„˜์œผ๋ฉด ์บ์‹ฑํ•˜์ง€ ์•Š๊ณ  ์š”์ฒญ๋งˆ๋‹ค JSKey ๊ฐ์ฒด๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด ๋ฐ˜ํ™˜ํ•˜๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค. ํฐ ์ •์ˆ˜ ํ‚ค๋ฅผ ์บ์‹ฑํ•ด์„œ ์–ป๋Š” ์ด์ ๋ณด๋‹ค ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ฌดํ•œํžˆ ์žก์•„๋จน๋Š” ์œ„ํ—˜์ด ํ›จ์”ฌ ํฌ๊ณ , ๋งค๋ฒˆ JSKey ๋ฅผ ๋งŒ๋“œ๋Š” ์ชฝ์ด ์˜คํžˆ๋ ค ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋‚ฎ๋‹ค๊ณ  ํŒ๋‹จํ–ˆ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ œ๊ฐ€ ์ดํ•ดํ•˜๊ธฐ๋กœ๋„, ์ž ๊น ์“ฐ๊ณ  ๋ฒ„๋ ค์ง€๋Š” ์ž‘์€ ๊ฐ์ฒด๋Š” 0์„ธ๋Œ€ GC ์—์„œ ์‹ธ๊ฒŒ ํšŒ์ˆ˜๋˜๋‹ˆ static ์‚ฌ์ „์— ์Œ“์•„ ๋‘๊ณ  ๋ฒ„ํ‚ท ๋ฐฐ์—ด๊นŒ์ง€ ํ‚ค์šฐ๋Š” ๊ฒƒ๋ณด๋‹ค ๊ฐ€๋ณ์Šต๋‹ˆ๋‹ค.

์ด ๋ณ€๊ฒฝ์ด ๋“ค์–ด๊ฐ€๋ฉด ํŠน์ • ๋น„์ฆˆ๋‹ˆ์Šค ์ฝ”๋“œ ํ•œ ๊ณณ์ด ์•„๋‹ˆ๋ผ ์—”์ง„ ์œ„์—์„œ ๋„๋Š” ๋ชจ๋“  ์ฝ”๋“œ์—์„œ ๊ฐ™์€ ์ข…๋ฅ˜์˜ ๋ˆ„์ˆ˜๊ฐ€ ์ƒ๊ธธ ๊ธธ์ด ๋ง‰ํž™๋‹ˆ๋‹ค.

 

5๏ธโƒฃ๋คํ”„ ๋ถ„์„ ๋Œ€์‹œ๋ณด๋“œ๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ๋‚ด์— ๊ณต์œ 

์ด๋ฒˆ ์กฐ์‚ฌ๋ฅผ ํ•˜๋ฉด์„œ ๊ฐ€์žฅ ์†์ด ๋งŽ์ด ๊ฐ„ ๊ฑด csv ๋‘ ๊ฐœ๋ฅผ ์—‘์…€๋กœ ๊ทธ๋ ค ๋ณด๊ณ , ์ฝ˜์†”์—์„œ dumpheap, gcroot, dumpobj ๊ฒฐ๊ณผ๋ฅผ ํ•œ ์ค„์”ฉ ์ฝ๊ณ , ๋คํ”„ ๋‘ ๊ฐœ๋ฅผ ์ฐฝ ๋‘ ๊ฐœ์— ๋„์›Œ ์ˆซ์ž๋ฅผ ๋ˆˆ์œผ๋กœ ๋งž์ถ”๋Š” ์ผ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์— ๋ˆ„๊ฐ€ ๊ฐ™์€ ์ผ์„ ๊ฒช์–ด๋„ ์ด ๊ณผ์ •์„ ๋ฐ˜๋ณตํ•˜์ง€ ์•Š๋„๋ก, ์ž์ฃผ ์“ฐ๋Š” ๋ช…๋ น์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋ž˜ํ”„์™€ ํ‘œ, ๋…ธ๋“œ·๊ฐ„์„  ๊ทธ๋ž˜ํ”„๋กœ ๋ณด์—ฌ ์ฃผ๋Š” ๋กœ์ปฌ ๋Œ€์‹œ๋ณด๋“œ๋ฅผ ๋งŒ๋“ค์–ด ํŒ€์— ๊ณต์œ ํ–ˆ์Šต๋‹ˆ๋‹ค.

์™ธ๋ถ€ ์˜์กด์„ฑ ์—†์ด Node.js ์„œ๋ฒ„ ํ•˜๋‚˜๋กœ ๋Œ๊ณ , ์„œ๋ฒ„๊ฐ€ ๋คํ”„๋งˆ๋‹ค dotnet-dump analyze ํ”„๋กœ์„ธ์Šค๋ฅผ ํ•˜๋‚˜ ๋„์›Œ ๋‘๊ณ  ๋ช…๋ น์„ ๋ณด๋‚ธ ๋’ค ์ถœ๋ ฅ์„ ํŒŒ์‹ฑํ•ด์„œ ํ™”๋ฉด์— ๊ทธ๋ฆฝ๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ ์‹คํ–‰ํ•œ ๋ช…๋ น ๊ฒฐ๊ณผ๋Š” ํ…์ŠคํŠธ๋กœ ์บ์‹œํ•ด์„œ, ๋‹ค์Œ๋ถ€ํ„ฐ๋Š” ๋ช‡ ๋ถ„์”ฉ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ๋ณผ ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ™”๋ฉด ๋ณด์—ฌ ์ฃผ๋Š” ๊ฒƒ ์“ฐ๋Š” ๋ช…๋ น·ํŒŒ์ผ
๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ํƒ€์ž„๋ผ์ธ Private Bytes, Working Set, GC ํž™์„ ํ•œ ์ถ•์— ๊ทธ๋ฆฌ๊ณ  GC ๋ฐœ์ƒ ์‹œ๊ฐ(์„ธ๋Œ€๋ณ„ ์ ์„ ), ๋คํ”„ ์ƒ์„ฑ ์‹œ๊ฐ์„ ํ‘œ์‹œ. GC ๋ฉˆ์ถค ์‹œ๊ฐ„, ํ• ๋‹น๋Ÿ‰, ๋‹จํŽธํ™”, ์Šค๋ ˆ๋“œํ’€, ์˜ˆ์™ธ, CPU ๋ณด์กฐ ์ฐจํŠธ mem.csv, counters.csv
๋คํ”„ ํŒŒ์ผ ๋ถ„์„ ์„ธ๋Œ€๋ณ„ ํž™ ์˜์—ญ ๋ง‰๋Œ€, ํƒ€์ž…๋ณ„ ๋ฉ”๋ชจ๋ฆฌ ํ‘œ, ๊ฐ์ฒด ๋ชฉ๋ก, ์ฐธ์กฐ ๊ทธ๋ž˜ํ”„, ๊ฐ์ฒด ์ƒ์„ธ, ์Šค๋ ˆ๋“œ ์Šคํƒ eeheap -gc, dumpheap -stat / -mt / -min, gcroot, dumpobj, clrstack -all
๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ๋น„๊ต ์—ฌ๋Ÿฌ ํ…Œ์ŠคํŠธ์˜ csv ๋ฅผ ๊ธฐ์ค€ ์‹œ๊ฐ(T0)์— ๋งž์ถฐ ๊ฒน์ณ ๊ทธ๋ฆผ mem.csv, counters.csv
๋คํ”„ ํŒŒ์ผ ๋น„๊ต ๋คํ”„ ๋‘ ๊ฐœ ์ด์ƒ์˜ ํƒ€์ž… ํ†ต๊ณ„๋ฅผ ๋‚˜๋ž€ํžˆ ๋†“๊ณ  ์ฆ๊ฐ๊ณผ ๋ณ€ํ™”์œจ ์ˆœ์œผ๋กœ ์ •๋ ฌ ๊ฐ ๋คํ”„์˜ dumpheap -stat
๋ช…๋ น ์ฝ˜์†” ์„ ํƒํ•œ ๋คํ”„์— ์ž„์˜์˜ SOS ๋ช…๋ น ์‹คํ–‰ syncblk, finalizequeue ๋“ฑ

 

โ‘  ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ํƒ€์ž„๋ผ์ธ

 

[๊ทธ๋ฆผ 21] ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ํƒ€์ž„๋ผ์ธ. ์œ„์˜ ์นด๋“œ์— ํ”ผํฌ ๊ฐ’๊ณผ GC ํšŸ์ˆ˜(gen0 631 / gen1 523 / gen2 13), ๋ฉˆ์ถค ํ•ฉ๊ณ„ 117.44์ดˆ๊ฐ€ ๋ฐ”๋กœ ๋‚˜์˜ต๋‹ˆ๋‹ค

 

์ˆ˜์ • ์ „ ์žฌํ˜„์˜ csv ๋‘ ๊ฐœ๋ฅผ ์˜ฌ๋ฆฌ๋ฉด, ์ด๋ฒˆ ๊ธ€ ์•ž๋ถ€๋ถ„์—์„œ ํ‘œ๋กœ ์ •๋ฆฌํ–ˆ๋˜ ๋‚ด์šฉ์ด ํ•œ ํ™”๋ฉด์— ๋‚˜์˜ต๋‹ˆ๋‹ค. ๋นจ๊ฐ„ ์ ์„ ์ด 2์„ธ๋Œ€ GC ์ด๊ณ , ์ดˆ๋ก ์‹ค์„ ์ด ๋คํ”„๋ฅผ ๋œฌ ์‹œ๊ฐ์ž…๋‹ˆ๋‹ค. GC ๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ๋Œ์•˜๋Š”๋ฐ๋„ ํž™์ด ๋‚ด๋ ค์˜ค์ง€ ์•Š๋Š” ๋ชจ์–‘์ด ํ•œ๋ˆˆ์— ๋ณด์ž…๋‹ˆ๋‹ค.

 

[๊ทธ๋ฆผ 22] ๋ณด์กฐ ์ฐจํŠธ. 72์ดˆ์งœ๋ฆฌ GC ๋ฉˆ์ถค๊ณผ ์ˆ˜์ง‘ ๊ตฌ๊ฐ„์˜ ํ• ๋‹น๋Ÿ‰ ํญ์ฆ์„ ๋”ฐ๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

 

โ‘ก ๋คํ”„ ํŒŒ์ผ ๋ถ„์„

[๊ทธ๋ฆผ 23] eeheap -gc ๊ฒฐ๊ณผ๋ฅผ ์„ธ๋Œ€๋ณ„ ๋ง‰๋Œ€๋กœ(Gen2 93%), dumpheap -stat ๊ฒฐ๊ณผ๋ฅผ ํฌ๊ธฐ ๋‚ด๋ฆผ์ฐจ์ˆœ ํ‘œ๋กœ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค

 

[๊ทธ๋ฆผ 24] gcroot ๊ฒฐ๊ณผ๋ฅผ ๋…ธ๋“œ์™€ ๊ฐ„์„ ์œผ๋กœ ๊ทธ๋ฆฐ ์ฐธ์กฐ ๊ทธ๋ž˜ํ”„. ๋…ธ๋“œ๋ฅผ ๋ˆ„๋ฅด๋ฉด dumpobj ๊ฒฐ๊ณผ๊ฐ€ ์•„๋ž˜์— ์—ด๋ฆฝ๋‹ˆ๋‹ค

 

์ฝ˜์†”์—์„œ ์ฃผ์†Œ๋ฅผ ๋ณต์‚ฌํ•ด dumpobj ๋ฅผ ์น˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ์—์„œ ๋‹ค์‹œ ์ฃผ์†Œ๋ฅผ ๋ณต์‚ฌํ•˜๋˜ ์ผ์„ ํด๋ฆญ ํ•œ ๋ฒˆ์œผ๋กœ ๋ฐ”๊ฟจ์Šต๋‹ˆ๋‹ค. ์•ž์—์„œ ๋ช…๋ น ์„ธ ๋ฒˆ์œผ๋กœ ๋”ฐ๋ผ๊ฐ„ ์‚ฌ์ „ ๋ณธ์ฒด → Tables → _countPerLock ๊ฒฝ๋กœ๋„ ๊ทธ๋ž˜ํ”„์—์„œ ๋…ธ๋“œ๋ฅผ ์ฐจ๋ก€๋กœ ๋ˆ„๋ฅด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

โ‘ข ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ๋น„๊ต / ๋คํ”„ ํŒŒ์ผ ๋น„๊ต

[๊ทธ๋ฆผ 25] ์ˆ˜์ • ์ „(ํŒŒ๋ž‘)๊ณผ ์ˆ˜์ • ํ›„(์ดˆ๋ก)์˜ GC ํž™์„ ์ˆ˜์ง‘ ์‹œ์ž‘ ์‹œ๊ฐ(T0)์— ๋งž์ถฐ ๊ฒน์นœ ํ™”๋ฉด

 

[๊ทธ๋ฆผ 26] ๋คํ”„ ๋น„๊ต. Node 99%, JSKey 99%, Int32 100% ๊ฐ์†Œ๊ฐ€ ๋ณ€ํ™”์œจ ์ˆœ์œผ๋กœ ์ •๋ ฌ๋ฉ๋‹ˆ๋‹ค

 

์ด๋ฒˆ ๊ธ€์˜ "๊ฒฐ๊ณผ" ํ‘œ๋ฅผ ๋งŒ๋“ค๋ ค๊ณ  ๋คํ”„ ๋‘ ๊ฐœ๋ฅผ ๋‚˜๋ž€ํžˆ ๋„์›Œ ์ˆซ์ž๋ฅผ ๋งž์ถ”๋˜ ์ž‘์—…์ด, ๋คํ”„ ๋‘ ๊ฐœ๋ฅผ ๊ณ ๋ฅด๊ณ  ๋ฒ„ํŠผ ํ•œ ๋ฒˆ ๋ˆ„๋ฅด๋Š” ์ผ์ด ๋์Šต๋‹ˆ๋‹ค.

 

6๏ธโƒฃ๊ฒฐ๊ณผ ๋ฐ ๋ฐฐ์šด ์ 

1. "๊ทธ๋ƒฅ OO ์ด ์ด์œ ๊ฒ ์ง€" ํ•˜๊ณ  ๊ณ ์น˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ๋ฅผ ์ฝ์–ด์„œ ์„ธ์šด ๊ฐ€์„ค์€ ์…‹์ด์—ˆ๊ณ , ์ฒ˜์Œ ๊ฐ€์žฅ ์œ ๋ ฅํ–ˆ๋˜ LOH ์กฐ๊ฐํ™”๋Š” ํ‹€๋ ธ์Šต๋‹ˆ๋‹ค. ์ง€๋ ˆ์ง์ž‘์œผ๋กœ GC ์„ค์ •์„ ๋ฐ”๊ฟ” ๋ฐฐํฌํ–ˆ๋‹ค๋ฉด ํšจ๊ณผ ์—†๋Š” ์ˆ˜์ •์„ ์šด์˜์— ์˜ฌ๋ ธ์„ ๊ฒ๋‹ˆ๋‹ค. ๋คํ”„๋Š” "๋ฌด์—‡์ด ๋ฉ”๋ชจ๋ฆฌ์— ์žˆ๊ณ  ๋ˆ„๊ฐ€ ๋ถ™์žก๊ณ  ์žˆ๋Š”๊ฐ€"๋ฅผ ์ˆซ์ž๋กœ ๋ณด์—ฌ ์คฌ์Šต๋‹ˆ๋‹ค.

2. ์˜ˆ์ธก์„ ๋จผ์ € ์ ๊ณ  ์‹ค์ธก๊ณผ ๋งž์ท„์Šต๋‹ˆ๋‹ค.

"๊ธ€์ž ์ˆ˜ − 1,025 ๊ฐœ์˜ ์ •์ˆ˜ ํ‚ค๊ฐ€ ์Œ“์ผ ๊ฒƒ"์ด๋ผ๋Š” ์˜ˆ์ธก์ด ๋คํ”„์˜ ๋ฐ•์‹ฑ Int32 ๊ฐœ์ˆ˜์™€ ๋“ค์–ด๋งž์•˜์„ ๋•Œ ์„ค๋ช…์ด ๋‹จ๋‹จํ•ด์กŒ์Šต๋‹ˆ๋‹ค. ์ˆ˜์ • ๋’ค์—๋„ "๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์•ˆ ๋Š˜์—ˆ๋‹ค"๊ฐ€ ์•„๋‹ˆ๋ผ ์›์ธ์œผ๋กœ ์ง€๋ชฉํ•œ ๊ฐ์ฒด์˜ ๊ฐœ์ˆ˜๋ฅผ ๋‹ค์‹œ ์…Œ์Šต๋‹ˆ๋‹ค.

3. ์‹คํŒจํ•œ ์‹คํ—˜๋„ ์ž๋ฃŒ์˜€์Šต๋‹ˆ๋‹ค.

์„œ๋ฒ„๋ฅผ ์“ฐ๋Ÿฌ๋œจ๋ฆฐ 1์ฐจ ์žฌํ˜„์—์„œ "๋๋‚˜๋ฉด ๋œจ์ž"๊ณ  ๊ธฐ๋‹ค๋ ธ๋‹ค๋ฉด ์•„๋ฌด๊ฒƒ๋„ ๋‚จ์ง€ ์•Š์•˜์„ ๊ฒ๋‹ˆ๋‹ค. ์ด์ƒํ•˜๋‹ค ์‹ถ์€ ์ˆœ๊ฐ„์— ๋–  ๋‘” ์ค‘๊ฐ„ ๋คํ”„๊ฐ€ ์›์ธ ๊ฐ์ฒด์™€ ์‹คํ–‰ ์ค‘์ธ ํ•จ์ˆ˜๋ฅผ ํ•จ๊ป˜ ์•Œ๋ ค ์คฌ์Šต๋‹ˆ๋‹ค.

4. ์บ์‹œ๋Š” ํ‚ค์˜ ์ข…๋ฅ˜๊ฐ€ ์œ ํ•œํ•  ๋•Œ๋งŒ ์บ์‹œ์ž…๋‹ˆ๋‹ค.

์ œ๊ฑฐ ๋กœ์ง์ด ์—†๋Š” static ์บ์‹œ์— ์ž…๋ ฅ ๋ฐ์ดํ„ฐ์— ๋น„๋ก€ํ•˜๋Š” ํ‚ค๊ฐ€ ๋“ค์–ด์˜ค๋Š” ์ˆœ๊ฐ„, ๊ทธ๊ฑด ์บ์‹œ๊ฐ€ ์•„๋‹ˆ๋ผ ๋ˆ„์ˆ˜์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์›์ธ์€ str[i] ์ฒ˜๋Ÿผ ์•„์ฃผ ํ‰๋ฒ”ํ•œ ์ฝ”๋“œ์˜€์Šต๋‹ˆ๋‹ค.

GC ๊ฐ€ ์žˆ๋‹ค๊ณ  ๋ˆ„์ˆ˜๊ฐ€ ์—†๋Š” ๊ฒŒ ์•„๋‹™๋‹ˆ๋‹ค. GC ๋Š” "๋‹ฟ์„ ์ˆ˜ ์—†๋Š” ๊ฒƒ"๋งŒ ์น˜์›Œ ์ค„ ๋ฟ, "๋‹ฟ์„ ์ˆ˜ ์žˆ์ง€๋งŒ ์“ธ๋ชจ์—†๋Š” ๊ฒƒ"์€ ๋๊นŒ์ง€ ์ง€์ผœ ์ค๋‹ˆ๋‹ค.

 

 

 

์ฐธ๊ณ  ์ž๋ฃŒ

'Observability' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

MSA ํ™˜๊ฒฝ์—์„œ ๋ชจ๋‹ˆํ„ฐ๋ง  (0) 2024.11.14

๋Œ“๊ธ€