[Go] memory arena

κ΄€λ ¨ 포슀트
https://blog.naver.com/sssang97/223232328524

μ΄λž˜λ‚˜ μ €λž˜λ‚˜ GoλŠ” GC 기반의 언어이고, λ©”λͺ¨λ¦¬μ˜ ν• λ‹Ήκ³Ό ν•΄μ œκ°€ μ„±λŠ₯μƒμ˜ 병λͺ©μ΄ 될 λ•Œλ„ λΆ„λͺ…νžˆ μ‘΄μž¬ν•œλ‹€.
κ·ΈλŸ΄λ•Œ GC 뢀담을 μ€„μ΄λŠ” 방법은 μ—¬λŸ¬κ°€μ§€ 접근법이 μžˆμ§€λ§Œ, κ°€μž₯ ν™•μ‹€ν•œκ±΄ μ•„λ¬΄λž˜λ„ ν• λ‹Ήκ³Ό ν•΄μ œ 자체λ₯Ό 자주 ν•˜μ§€ μ•Šλ„λ‘ μœ λ„ν•˜λŠ” 것이닀.




λ‚΄μž₯ Memory Arena

κ·Έκ±Έ μœ„ν•œ λŒ€ν‘œμ μΈ κΈ°λŠ₯ 쀑 ν•˜λ‚˜κ°€ λ°”λ‘œ memory arenaλΌλŠ” 것이닀.
Go 1.20λΆ€ν„° experimental λͺ¨λ“ˆλ‘œ μΆ”κ°€λ˜μ—ˆλ‹€.

이건 μž‘μ€ 크기의 데이터 쑰각듀을 뢀담없이 λΉ λ₯΄κ²Œ ν• λ‹Ήν•˜κ³  ν•œλ²ˆμ— λ°˜ν™˜ν•  수 μžˆλ„λ‘ ν•˜λŠ” 것을 λͺ©μ μœΌλ‘œ ν•œλ‹€.

μ‚¬μš© νŒ¨ν„΄ μžμ²΄κ°€ ν•œλ²ˆμ— λͺ°μ•„μ„œ ν™• μŒ“μ•˜λ‹€κ°€ λ‚˜μ€‘μ— λͺ°μ•„μ„œ 정리해도 λ˜λŠ” κ²½μš°μ— μ ν•©ν•˜λ‹€.
κ·ΈλŒ€μ‹  일이 λλ‚˜λ©΄ μˆ˜λ™μœΌλ‘œ 정리λ₯Ό ν•΄μ€˜μ•Ό ν•œλ‹€. κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ λˆ„μˆ˜ λ¬Έμ œκ°€ 생긴닀.

μ‚¬μš©λ²•μ€ λŒ€λž΅ 이렇닀.
arenaλΌλŠ” μ΄λ¦„μ˜ λͺ¨λ“ˆλ‘œ importν•  수 있고

μ‹€ν–‰ν•  λ•Œλ„ λͺ…μ‹œμ μœΌλ‘œ ν™œμ„±ν™”λ₯Ό ν•΄μ€˜μ•Ό ν•œλ‹€.

μ‚¬μš©λ°©λ²•μ€ κ·Έλ‹€μ§€ μ–΄λ ΅μ§€ μ•Šλ‹€.
λ¨Όμ € μ „μ—­ νž™ 곡간을 μƒμ„±ν•΄μ€˜μ•Ό ν•œλ‹€.

μ €κ²Œ μΌμ’…μ˜ 짬톡이 λ˜λŠ” μ…ˆμ΄λ‹€.
μ‚¬μš©μ΄ λ‹€ λλ‚˜λ©΄ Free ν•¨μˆ˜λ‘œ ν• λ‹Ήν•œ 객체듀을 μ „λΆ€ λ‚ λ €μ€€λ‹€.

그리고 객체λ₯Ό ν• λ‹Ήν• λ•ŒλŠ” New ν•¨μˆ˜λ₯Ό ν†΅ν•΄μ„œ μˆ˜ν–‰ν•  수 μžˆλ‹€.

각자 ν• λ‹Ήλœ 곡간에 λŒ€ν•œ 포인터λ₯Ό λ°˜ν™˜ν•˜κ³ , 이λ₯Ό 톡해 값을 μˆ˜μ •ν•˜κ±°λ‚˜ μ‘°νšŒν•  수 μžˆλ‹€.

그리고 μœ„μ˜ Free ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜λ©΄ ν•œλ²ˆμ— 싸그리 μ •λ¦¬λ˜λŠ” μ…ˆμ΄λ‹€.
Free ν•¨μˆ˜κ°€ μ‹€ν–‰λœ μ΄ν›„μ—λŠ” μ € 포인터 핸듀듀을 μ‚¬μš©ν•˜λ©΄ μ•ˆλœλ‹€.

μ•„λž˜λŠ” 전체 예제 μ½”λ“œλ‹€.

package main

import (
	"arena"
	"fmt"
)

func main() {
	// arena 전역곡간 생성
	mem := arena.NewArena()
	defer mem.Free()

	// ν• λ‹Ή
	number := arena.New[int](mem)
	*number = 4444
	fmt.Println(*number)

	// 슬라이슀 ν• λ‹Ή
	slice := arena.MakeSlice[string](mem, 100, 200)
	fmt.Println(len(slice), cap(slice))
	slice[0] = "Hello"
	slice[1] = "World"
	fmt.Println(slice[0], slice[1])
}

잘 λ™μž‘ν•œλ‹€.

λ‹€λ§Œ ν˜„μž¬ arena κ΅¬ν˜„μ€ λ¬Έμ œκ°€ λ§Žμ•„μ„œ μ œκ±°λ˜κ±°λ‚˜ 변경될 κ°€λŠ₯성이 λ§Žλ‹€κ³  ν•œλ‹€. μƒμ„Έν•œ λ‚΄μš©μ€ 이슈λ₯Ό μ°Έκ³ ν•œλ‹€.
https://github.com/golang/go/issues/51317
적어도 κ·Όμ‹œμΌμ— 이 κΈ°λŠ₯이 μ•ˆμ •ν™”λ  일은 μ—†λŠ”κ±°κ°™λ‹€.




λŒ€μ•ˆ: 직접 κ΅¬ν˜„ν•˜κΈ°

λ²”μš©μ„±μ„ μ•½κ°„ ν¬κΈ°ν•œλ‹€λ©΄ μ•„λ ˆλ‚˜λ₯Ό 직접 κ΅¬ν˜„ν•˜λŠ” 것도 μ–΄λ ΅μ§€λŠ” μ•Šλ‹€.

ν• λ‹Ήν•΄μ œλ₯Ό 막기 μœ„ν•΄μ„œλŠ” root 객체가 κ·Έ 객체의 포인터λ₯Ό λ“€κ³ λ§Œ μžˆμ–΄λ„ λ˜λŠ”λ°, any 포인터든 λ­˜λ‘œλ“  데이터λ₯Ό λ“€κ³  μžˆκ²Œλ” λ§Œλ“€λ©΄ 되기 λ•Œλ¬Έμ΄λ‹€.

ν˜Ήμ€ λͺ¨λ“  λ³€μˆ˜λ“€μ„ ν•˜λ‚˜μ˜ ꡬ쑰체에 λ‹€ μ •μ˜ν•΄λ†“κ³  μƒμœ„ μ»¨ν…μŠ€νŠΈμ—μ„œ μƒμ„±ν•œ λ‹€μŒμ— ν¬μΈν„°λ‘œ κ³΅μœ ν•˜λŠ” μ‹μœΌλ‘œ μ‚¬μš©ν•΄λ„ 거의 λ™λ“±ν•œ λ™μž‘μ„ κΈ°λŒ€ν•  μˆ˜λ„ μžˆμ„ 것이닀.




λŒ€μ•ˆ: sync.Pool

μ‚¬μš© ν˜•νƒœκ°€ 쑰금 λ‹¬λΌμ„œ λŒ€μ•ˆμ΄λΌκ³  ν•˜κΈ΄ μ–΄λ ΅μ§€λ§Œ, λΉ„μŠ·ν•œ λ™μž‘λ°©μ‹μ„ κ°€μ§„ κΈ°λŠ₯으둜 sync.Pool이 μžˆλ‹€.

https://blog.naver.com/sssang97/223304134705



μ°Έμ‘°
https://uptrace.dev/blog/golang-memory-arena.html
https://github.com/golang/go/issues/51317
https://pyroscope.io/blog/go-1-20-memory-arenas/