iOS/WWDC

๐Ÿ“ฑ WWDC 2024 - [Analyze heap memory] ์ •๋ฆฌ ๋ฐ ๋ฆฌ๋ทฐ

suvera 2025. 5. 17. 18:13
๋ฐ˜์‘ํ˜•

- ์•ฑ์˜ ๋™์  ๋ฉ”๋ชจ๋ฆฌ์ธ ํž™ ๋ฉ”๋ชจ๋ฆฌ์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ธฐ.
- Instruments์™€ Xcode๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ผ๋ฐ˜์ ์ธ ํž™ ๋ฉ”๋ชจ๋ฆฌ ๋ฌธ์ œ ํŒ๋‹จ, ๋ถ„์„, ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•
- ์•ฑ์—์„œ ์ผ์‹œ์  ๋˜๋Š” ์ง€์†์ ์ธ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ์ฆ๊ฐ€, ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ์ง„๋‹จํ•˜๋Š” ๊ธฐ์ˆ  ๋ฐ ๋ชจ๋ฒ” ์‚ฌ๋ก€ ์†Œ๊ฐœ

 

โœ… ์ „์ฒด ์„ธ์…˜ ์š”์•ฝ

 

์ด ์„ธ์…˜์€ iOS/macOS ์•ฑ์—์„œ ํž™ ๋ฉ”๋ชจ๋ฆฌ์˜ ์‚ฌ์šฉ๋Ÿ‰์„ ๋ถ„์„ํ•˜๊ณ , ๋ฉ”๋ชจ๋ฆฌ ๋ฌธ์ œ๋ฅผ ์ง„๋‹จํ•˜๋ฉฐ, ์ตœ์ ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค. ์ฃผ๋กœ Xcode์™€ Instruments ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•ด ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์ถ”์ ํ•˜๊ณ  ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

 

๐ŸŽฏ ์„ธ์…˜ ํ•ต์‹ฌ ์ฃผ์ œ (5๊ฐ€์ง€)

 

1. ํž™ ์ธก์ •ํ•˜๊ธฐ

2. ์ผ์‹œ์  ์ฆ๊ฐ€์— ๋Œ€์‘ํ•˜๊ธฐ

3. ์ง€์†์  ์ฆ๊ฐ€ ์ถ”์ ํ•˜๊ธฐ

4. ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์ˆ˜์ •ํ•˜๊ธฐ

5. ๋Ÿฐํƒ€์ž„ ์„ฑ๋Šฅ ๊ฐœ์„ ํ•˜๊ธฐ

 

์•ฑ์—์„œ ์ง,๊ฐ„์ ‘์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๊ณ  ๊ฐœ๋ฐœ์ž๊ฐ€ ์ œ์–ดํ•˜๊ณ  ์ตœ์ ํ™” ํ• ์ˆ˜ ์žˆ์Œ. ์•ฑ์˜ ์ฐธ์กฐํƒ€์ž… ์ €์žฅ

๐Ÿ“Œ ํž™ ๋ฉ”๋ชจ๋ฆฌ๋ž€? 

์•ฑ์—์„œ ์ˆ˜๋ช…์ด ๊ธด ๊ฐ์ฒด๋“ค์ด ์ €์žฅ๋˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ

์ง์ ‘์ ์œผ๋กœ๋Š” malloc, calloc, realloc ๋“ฑ์œผ๋กœ ํ• ๋‹น

๊ฐ„์ ‘์ ์œผ๋กœ๋Š” Swift/Objective-C ์ธ์Šคํ„ด์Šค๋ฅผ ํ†ตํ•ด ํ• ๋‹น๋จ

์šด์˜์ฒด์ œ์˜ ๊ฐ€์ƒ ๋ฉ”๋ชจ๋ฆฌ ํŽ˜์ด์ง€ (ํด๋ฆฐ, ๋”ํ‹ฐ, ์Šค์™‘)๋กœ ๊ตฌ์„ฑ

 

- ์•ฑ์ด ์‹œ์ž‘๋˜๋ฉด ์ž์ฒด์ ์ธ ๋นˆ ๊ฐ€์ƒ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ ๊ณต๊ฐ„์„ ๋ฐ›์Œ

- ์•ฑ์ด ์‹คํ–‰๋  ๋•Œ ์‹œ์Šคํ…œ์€ ๋ฉ”์ธ ์‹คํ–‰ ํŒŒ์ผ, ์—ฐ๊ฒฐ๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ/ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋กœ๋“œ, ๋””์Šคํฌ์—์„œ ์ฝ๊ธฐ ์ „์šฉ ๋ฆฌ์†Œ์Šค ์˜์—ญ์„ ๋งคํ•‘

- ์‹คํ–‰ ์ค‘์— ์•ฑ์€ ๊ฐ ์Šค๋ ˆ๋“œ์˜ ๋กœ์ปฌ ๋ฐ ์ž„์‹œ ๋ณ€์ˆ˜๋ฅผ ์œ„ํ•œ ์Šคํƒ ์˜์—ญ์„ ์‚ฌ์šฉ

- ๋™์ ์ด๊ณ  ์ˆ˜๋ช…์ด ๊ธด ๋ฉ”๋ชจ๋ฆฌ๋Š” ํž™ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์— ๋ฐฐ์น˜

 

- ์—ฌ๋Ÿฌ ๊ฐ€์ƒ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์œผ๋กœ ๊ตฌ์„ฑ๋จ

- ๊ฐ ์˜์—ญ์€ ๊ฐœ๋ณ„ ํž™ ํ• ๋‹น์œผ๋กœ ๋‚˜๋‰จ.

- ์šด์˜์ฒด์ œ์˜ 16kb ๋ฉ”๋ชจ๋ฆฌ ํŽ˜์ด์ง€๋กœ ๊ตฌ์„ฑ๋จ.

- ์ƒํƒœ๋Š” ํด๋ฆฐ, ๋”ํ‹ฐ ๋˜๋Š” ์Šค์™‘

- ๋”ํ‹ฐ์™€ ์Šค์™‘๋งŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์— ํฌํ•จ๋จ.

- ํž™์ด ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์˜ ๋Œ€๋ถ€๋ถ„์„ ์ฐจ์ง€ 

 

ํด๋ž˜์Šค ์ด๋‹ˆ์…œ๋ผ์ด์ € -> malloc ํ˜ธ์ถœ

 

malloc stack logging ํ™œ์„ฑํ™”

๐Ÿ› ๏ธ ํž™ ๋ฉ”๋ชจ๋ฆฌ ์ธก์ • ๋„๊ตฌ

์‹œ๊ฐ„๊ฒฝ๊ณผ์— ๋”ฐ๋ฅธ ํ’‹ํ”„๋ฆฐํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” xcode ๋ฉ”๋ชจ๋ฆฌ ๋ณด๊ณ ์„œ

 

1. Xcode ๋ฉ”๋ชจ๋ฆฌ ๋ณด๊ณ ์„œ

์•ฑ ์ „์ฒด ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ์ถ”์ด ํ™•์ธ ๊ฐ€๋Šฅ

๊ฐ‘์ž‘์Šค๋Ÿฌ์šด ๋ฉ”๋ชจ๋ฆฌ ์ฆ๊ฐ€ ๊ฐ์ง€์— ์œ ์šฉ

๋Œ€๊ทœ๋ชจ ๋ฉ”๋ชจ๋ฆฌ ๋ฌธ์ œ์™€ ์ผ๋ถ€ ์ตœ๊ทผ ๊ธฐ๋ก์„ ๋ณด์—ฌ์ฃผ์ง€๋งŒ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์ฆ๊ฐ€ํ•˜๋Š” ์ด์œ ๋Š” ์•Œ๋ ค์ฃผ์ง€ ๋ชปํ•จ.

 

 

 

๋ชจ๋“  ํ• ๋‹น๊ณผ ๊ทธ ์‚ฌ์ด ์ฐธ์กฐ์— ๋Œ€ํ•œ ์Šค๋ƒ…์ƒท์ธ ๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ž˜ํ”„ ์บก์ณ ๊ฐ€๋Šฅ

2. Xcode ๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ž˜ํ”„ ๋””๋ฒ„๊ฑฐ

ํ˜„์žฌ ์•ฑ์˜ ๋ฉ”๋ชจ๋ฆฌ ์Šค๋ƒ…์ƒท์„ ์บก์ฒ˜ํ•˜๊ณ  ๊ฐ์ฒด ๊ฐ„ ์ฐธ์กฐ ํ™•์ธ ๊ฐ€๋Šฅ

๋ˆ„์ˆ˜๋‚˜ ์ˆœํ™˜ ์ฐธ์กฐ ์‹œ ์‹œ๊ฐ์ ์œผ๋กœ ์ถ”์  ๊ฐ€๋Šฅ

MallocStackLogging์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ ํ• ๋‹น์˜ ์—ญ์ถ”์ ์ด ํฌํ•จ๋จ

ํŠน์ • ํ• ๋‹น์— ์ง‘์ค‘ํ•ด์•ผ ํ• ๋•Œ ์œ ์šฉ, xcode์˜ ๋””๋ฒ„๊ทธ ๋ง‰๋Œ€์—์„œ ๋ฐ”๋กœ ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์žˆ์Œ

 

 

3. Instruments - Allocations

์‹œ๊ฐ„ ํ๋ฆ„์— ๋”ฐ๋ฅธ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น/ํ•ด์ œ ์ถ”์ 

์ฝœ ํŠธ๋ฆฌ ๋ฐ ์ƒ์„ฑ ์œ„์น˜ ๋ถ„์„ (ํ†ต๊ณ„์™€ ์ฝœ ํŠธ๋ฆฌ๋ฅผ ์ง‘๊ณ„ํ•ด ๋‹ค์‹œ ์ฝ”๋“œ๋กœ ์ถ”์ )

• leaks ๋„๊ตฌ๋Š” ์•ฑ์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฃผ๊ธฐ์ ์œผ๋กœ ์Šค๋ƒ…์ƒทํ•ด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๊ฐ์ง€

 

4. Command-line ๋„๊ตฌ๋“ค

leaks, heap, vmmap, malloc_history 

• macOS ๋ฐ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ง์ ‘ ๋ถ„์„ํ•˜๊ฑฐ๋‚˜ ์ด๋ฏธ ์บก์ฒ˜๋œ ๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ž˜ํ”„๋กœ ๋ฌธ์ œ๋ฅผ ์กฐ์‚ฌํ•  ์ˆ˜ ์žˆ์Œ.

 

 

 

 

๐Ÿ“ˆ ๋ฉ”๋ชจ๋ฆฌ ์ผ์‹œ์  ์ฆ๊ฐ€ ๋ถ„์„

 

DestinationVideo ์•ฑ์˜ ๋ฉ”๋ชจ๋ฆฌ ๋ฌธ์ œ : ๋น„๋””์˜ค์˜ ์ƒˆ ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง€๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ - ๊ฐค๋Ÿฌ๋ฆฌ ์—ด๊ธฐ์—์„œ ์•ฑ ํฌ๋ž˜์‰ฌ

 

๋ฌธ์ œ:

๊ฐค๋Ÿฌ๋ฆฌ ์—ด๊ธฐ → ๋ฉ”๋ชจ๋ฆฌ 1GB ๊ธ‰์ฆ (xcode ๋ณด๊ณ ์„œ) → ์•ฑ ์ข…๋ฃŒ ์œ„ํ—˜

 

Allocations ๋„๊ตฌ๋ฅผ ํ™œ์šฉ:

 Product -> Profile ๋ฉ”๋‰ด  -> ์•ฑ์˜ ๋ฆด๋ฆฌ์ฆˆ ๋นŒ๋“œ ์ˆ˜ํ–‰ -> ์•ฑ์ด ๋Œ€์ƒ์œผ๋กœ ์„ ํƒ๋œ ์ƒํƒœ์—์„œ Instruments๊ฐ€ ์—ด๋ฆผ -> ํ”„๋กœํŒŒ์ผ๋งํ•  ํ…œํ”Œ๋ฆฟ์„ ์„ ํƒํ•˜๋ผ๋Š” ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ -> allocations ์„ ํƒ ->  allocations(ํž™๊ณผ VM ์ด๋ฒคํŠธ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ธฐ๋กํ•˜์—ฌ ํ™œ๋™์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ํ™•์ธ ๊ฐ€๋Šฅ), VM Tracker(์ฃผ๊ธฐ์ ์œผ๋กœ ์Šค๋ƒ…์ƒท์„ ์ƒ์„ฑํ•ด ๋ชจ๋“  ๊ฐ€์ƒ ๋ฉ”๋ชจ๋ฆฌ ์ธก์ • ๊ฐ€๋Šฅ)์—์„œ allocations ์„ ํƒ -> ์™ผ์ชฝ ์ƒ๋‹จ์˜ Record ๋ฒ„ํŠผ์œผ๋กœ ์ถ”์  

 

์•ฑ์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ธ‰์ฆ์ด ์•ˆ์ข‹์€ ์ด์œ :

๋ฉ”๋ชจ๋ฆฌ ์••๋ฐ• ์œ ๋ฐœ

๋”ํ‹ฐ ๋ฉ”๋ชจ๋ฆฌ ๊ต์ฒด ๋ฐ ์••์ถ•, ์ฝ๊ธฐ์ „์šฉ ๋ฉ”๋ชจ๋ฆฌ ํ๊ธฐ, ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—… ์ข…๋ฃŒ

• ์ตœ์•…์˜ ๊ฒฝ์šฐ ์•ฑ ์ข…๋ฃŒ

 

๋ฉ”๋ชจ๋ฆฌ ๊ธ‰์ฆ ์ถ”์  :

1. ํŠน์ • ์ŠคํŒŒ์ดํฌ์—์„œ ์ตœ์ €์ ์—์„œ ์ตœ๊ณ ์ ์— ์žˆ๋Š” Created & Still Living ํ• ๋‹น ์ฐพ๊ธฐ 

2. ์ „์ฒด์ ์œผ๋กœ ํฐ ๋ฒ”์œ„๋ฅผ ์„ ํƒํ•ด ํ•ด๋‹น ๋ฒ”์œ„์—์„œ Created & Destroyed ๋œ ๋ชจ๋“  ํ• ๋‹น ์ฐพ๊ธฐ

 

ํƒ€์ž„๋ผ์ธ์˜ ์ŠคํŒŒ์ดํฌ ๊ตฌ๊ฐ„ ์ค‘ ํ•˜๋‚˜ ์„ ํƒ -> ํŠธ๋ž™ ๋ทฐ์—์„œ ์ŠคํŒŒ์ดํฌ์˜ ์ตœ์ €์ ์—์„œ ์ตœ์ƒ๋‹จ๊นŒ์ง€ ํด๋ฆญ + ๋“œ๋ž˜๊ทธ -> ์ •๋ณด ํ‘œ์‹œ๋จ
lifespan ํ•„ํ„ฐ destroyed ๋ณ€๊ฒฝ, ์ŠคํŒŒ์ดํฌ 3๊ฐœ ์ „์ฒด ์„ ํƒ - ์ฝœํŠธ๋ฆฌ๋กœ ์ „ํ™˜ - ํ• ๋‹น์„ ์—ญ์ถ”์ ์œผ๋กœ ๋ถ„์„ํ•ด ๊ฐ€์žฅ ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌํ• ๋‹นํ•˜๋Š” ์ฝ”๋“œ ๋ณผ ์ˆ˜ ์žˆ์Œ
ํ•œ ์ค„์—์„œ GB ๋‹จ์œ„์˜ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ƒ์„ฑ & ํŒŒ๊ดด

func makeThumbnail(from photoURL: URL) -> PhotoThumbnail {
  validate(url: photoURL)
  var coreImage = CIImage(contentsOf: photoURL)!

  let sepiaTone = CIFilter.sepiaTone()
  sepiaTone.inputImage = coreImage
  sepiaTone.intensity = 0.4
  coreImage = sepiaTone.outputImage!

  let squareSize = min(coreImage.extent.width, coreImage.extent.height)
  coreImage = coreImage.cropped(to: CGRect(x: 0, y: 0, width: squareSize, height: squareSize))

  let targetSize = CGSize(width:64, height:64)
  let scalingFilter = CIFilter.lanczosScaleTransform()

  scalingFilter.inputImage = coreImage
  scalingFilter.scale = Float(targetSize.height / coreImage.extent.height)
  scalingFilter.aspectRatio = Float(Double(coreImage.extent.width) / Double(coreImage.extent.height))
  coreImage = scalingFilter.outputImage!

  let imageData = context.generateImageData(of: coreImage)

  return PhotoThumbnail(size: targetSize, data: imageData, url: photoURL)
}

๋ฃจํ”„์—์„œ ์ธ๋„ค์ผ์„ ํดํŠธํ•˜๊ณ  ์žˆ๊ณ  ๋ฃจํ”„๊ฐ€ ์‹คํ–‰๋˜๋Š” ๋™์•ˆ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ฆ๊ฐ€ํ•˜๋‹ค ๋์—์„œ ๋–จ์–ด์ง

func loadThumbnails(with renderer: ThumbnailRenderer) {
  for photoURL in urls {
    renderer.faultThumbnail(from: photoURL)
  }
}

Swift์—๋Š” ์ž๋™ ์ฐธ์กฐ ์นด์šดํŒ…์ด ์žˆ์ง€๋งŒ autoreleasepool์€ ์ž„์‹œ ๋ฉ”๋ชจ๋ฆฌ ์ฆ๊ฐ€์˜ ํ”ํ•œ ์›์ธ. ์˜ต์ ์”จ๋Š” ์ด ํ’€์„ ์‚ฌ์šฉํ•ด ํ•จ์ˆ˜ ๋ฐ˜ํ™˜๊ฐ’์˜ ๊ฐ์ฒด ์ˆ˜๋ช…์„ ์—ฐ์žฅ, autoreleasepool์€ ํ•ด์ œ๋ฅผ ์ง€์—ฐ์‹œ์ผœ ์ด ๋ฐ˜ํ™˜๊ฐ’๋“ค์„ ์œ ์ง€ํ•จ. swift ๊ฐ€ ์˜ต์ ์”จ api๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ž๋™ ๋ฆด๋ฆฌ์ฆˆ๋œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ

 

 

์˜ˆ์‹œ : ํ˜„์žฌ ๋‚ ์งœ ์ถœ๋ ฅ - ์ž๋™๋ฆด๋ฆฌ์ฆˆ๋œ ๋ฌธ์ž์—ด๋„ ์ƒ์„ฑ, ํ˜„์žฌ ์ž๋™ ๋ฆด๋ฆฌ์ฆˆ ๋ฒ”์œ„๊ฐ€ ๋๋‚  ๋•Œ ๊นŒ์ง€ ํž™์— ๋‚จ์•„์žˆ๊ฒŒ ๋จ

print("Now is \(Date.now)") // Produces autoreleased .description String

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

 

ํ’€์—์„œ ์ง€์—ฐ๋œ ๋ฆด๋ฆฌ์ฆˆ๋ฅผ ๋ณด๋‚ด๊ณ  ๋งŽ์€ ๊ฐ์ฒด๊ฐ€ ํ•œ๊บผ๋ฒˆ์— ํ’€๋ ค๋‚  ์ˆ˜ ์žˆ๋‹ค.

 

์›์ธ ๋ถ„์„:

 @autoreleasepool ๋ฏธ์‚ฌ์šฉ์œผ๋กœ ๋ฃจํ”„ ๋‚ด ์ž„์‹œ ๊ฐ์ฒด๊ฐ€ ๋ฐ˜๋ณต ๋ˆ„์ 

 makeThumbnail() ๋‚ด ๋ฐ˜๋ณต ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์‹œ ๊ฐ์ฒด ํ•ด์ œ๊ฐ€ ์ง€์—ฐ๋จ

 

๋กœ์ปฌ ์ž๋™ ๋ฆด๋ฆฌ์ฆˆ ํ’€ ๋ฒ”์œ„๋ฅผ ์ •์˜ํ•ด ์ˆ˜๋ช… ์ขํžˆ๊ธฐ - ์ž๋™ ๋ฆด๋ฆฌ์ฆˆ๋œ ๊ฐ์ฒด๊ฐ€ ๋‚ด๋ถ€ ๋ฃจํ”„๋ณ„ ํ’€์— ๋ณด๊ด€๋จ. ๊ฐ ๋ฐ˜๋ณต๋งˆ๋‹ค ๋ฆด๋ฆฌ์ฆˆ ๋จ. ๋ˆ„์ ๋˜๋Š” ๊ฐ์ฒด์ˆ˜๊ฐ€ ์ค„์–ด๋“ค๊ณ  ์ฐธ์กฐ๋ฅผ ์ถ”์ ํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ์ฝ˜ํ…์ธ  ํŽ˜์ด์ง€๊ฐ€ ์ค„์–ด๋“ฌ

 

 

ํ•ด๊ฒฐ:

 ๋ฃจํ”„ ๋‚ด๋ถ€์— autoreleasepool {} ์ถ”๊ฐ€

 ๋ฐ˜๋ณต๋งˆ๋‹ค ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ๋ฅผ ์œ ๋„

 

 

func loadThumbnails(with renderer: ThumbnailRenderer) {
    for photoURL in urls {
        autoreleasepool {
            renderer.faultThumbnail(from: photoURL)
        }
    }
}

- ๋ฃจํ”„ ๋ณธ๋ฌธ์— ์ž๋™ ๋ฆด๋ฆฌ์ฆˆ ํ’€ ๋ฒ”์œ„๋ฅผ ์ถ”๊ฐ€ํ•ด ๊ฐ ๋ฐ˜๋ณต ํ›„์— ๊ฐ์ฒด๋ฅผ ๋น„์šฐ๋„๋ก !

- ๋Œ€๋ถ€๋ถ„์˜ ํ”„๋กœํŒŒ์ผ๋ง์—์„œ๋Š” ์ •ํ™•ํ•œ ํƒ€์ด๋ฐ์„ ์œ„ํ•ด ๋ฆด๋ฆฌ์ฆˆ ๋นŒ๋“œ๋ฅผ ์‹ค์ œ ๊ธฐ๊ธฐ์—์„œ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”.

- ํ•˜์ง€๋งŒ ํž™ ๋ถ„์„์˜ ๊ฒฝ์šฐ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ ํ™˜๊ฒฝ์ด ๋™์ž‘์— ๋” ๊ฐ€๊นŒ์›Œ์„œ ๋ฉ”๋ชจ๋ฆฌ ํ”„๋กœํŒŒ์ผ๋ง์— ์‚ฌ์šฉํ•ด๋„ ๊ดœ์ฐฎ์Œ.

 

๊ธฐ๊ฐ€๋ฐ”์ดํŠธ ๋‹จ์œ„๊นŒ์ง€ ์˜ฌ๋ผ๊ฐ€๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ŠคํŒŒ์ดํฌ๋Š” ์‚ฌ๋ผ์กŒ์ง€๋งŒ ๋งค๋ฒˆ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๊ณ„๋‹จ์‹ ํŒจํ„ด์œผ๋กœ ์˜ฌ๋ผ๊ฐ. ๊ฐค๋Ÿฌ๋ฆฌ๋ฅผ ์ฒ˜์Œ ์—ด์—ˆ์„ ๋•Œ๋งŒ ์ฆ๊ฐ€ํ•ด์•ผ๋˜๋Š”๋ฐ.. ์—ด๊ณ  ๋‹ซ๊ณ  ํ•  ๋•Œ๋งˆ๋‹ค ๊ณ„๋‹จ์‹์œผ๋กœ ??

 

 

 

๐Ÿ”„ ์ง€์†์  ๋ฉ”๋ชจ๋ฆฌ ์ฆ๊ฐ€ (Memory Leak ์•„๋‹˜)

 

๋ฌธ์ œ:

๊ฐค๋Ÿฌ๋ฆฌ๋ฅผ ์—ด ๋•Œ๋งˆ๋‹ค ์ ์ง„์  ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ์ฆ๊ฐ€ (๊ณ„๋‹จ ํ˜•ํƒœ)

 

๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ž˜ํ”„ ๋””๋ฒ„๊ฑฐ๋ฅผ xcode์˜ ๋””๋ฒ„๊ทธ ๋ฐ”์—์„œ ์ผ์‹œ์ค‘์ง€ > ํž™์˜ ๋ชจ๋“  ํ• ๋‹น์ด ์บก์ฒ˜๋จ > ์ฆ๊ฐ€์˜ ์›์ธ์ด ๋œ ์œ ํ˜•์„ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ฆ๊ฐ€ > ์—ฌ๋Ÿฌ๋ฒˆ์˜ ํ• ๋‹น

 

 

๋ถ„์„ ๋ฐฉ๋ฒ•:

Instruments - Allocations์˜ Mark Generation ๊ธฐ๋Šฅ์œผ๋กœ ์‹œ๊ฐ„๋Œ€๋ณ„ ํž™ ์ƒํƒœ ๊ตฌ๋ถ„

์ฆ๊ฐ€ ๊ตฌ๊ฐ„ ๋ณ„ ๊ฐ์ฒด ์œ ํ˜• ํ™•์ธ

 

mark generation ๋ฒ„ํŠผ ํด๋ฆญ > ํ• ๋‹น์„ ์œ„ํ•œ ์ƒˆ ๊ทธ๋ฃน์„ ๋งŒ๋“ฌ > ์ด ์‹œ์  ์ด์ „์— ์ƒ๊ธด ๋ชจ๋“  ํ• ๋‹น์„ ์ˆ˜์ง‘

 

 

3๊ฐœ์˜ ์„ธ๋Œ€ ์ค‘ ํ•˜๋‚˜๋ฅผ ํ™•์žฅํ•ด์„œ ํ• ๋‹น๋Ÿ‰ ํ™•์ธ > ๋ฐ์ดํ„ฐ์šฉ ์Šคํ† ๋ฆฌ์ง€์—์„œ > ๊ฐœ๋ณ„ ํ• ๋‹น๋Ÿ‰๊ณผ ์ฃผ์†Œ ํ™•์ธ > ๋ชจ๋“  ๋ฐ์ดํ„ฐ ์Šคํ† ๋ฆฌ์ง€ ํ• ๋‹น ์ƒ์„ฑ ํ™•์ธ

 

์ด ์ฃผ์†Œ ์ค‘ ํ•˜๋‚˜๋ฅผ ๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ž˜ํ”„ ๋””๋ฒ„๊ฑฐ์— ๋„ฃ์–ด ์ฐธ์กฐํ•˜๋Š” ํ•ญ๋ชฉ ํ™•์ธ > ๋ฐ์ดํ„ฐ๊ฐ€ ์ž”์กดํ•˜๋Š” ์ด์œ ๋ฅผ ์•Œ์ˆ˜ ์žˆ๋‹ค.

 

๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ž˜ํ”„ ๋””๋ฒ„๊ฑฐ๊ฐ€ ์ด ์งˆ๋ฌธ์— ๋Œ€ํ•œ ๋‹ต์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค.

 

ํƒ€์ž… ์ •๋ณด์™€ ์ฐธ์กฐ ์Šค์บ”์— ๋Œ€ํ•œ ์ดํ•ด : 

์ฐธ์กฐ์˜ 4๊ฐ€์ง€ ํƒ€์ž…

 

ํž™ ํ• ๋‹น์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ > ์ฝ”์ฝ”๋„› ๊ฐ์ฒด์— ๋Œ€ํ•œ ๊ฐ• ํ•œ ์ฐธ์กฐ

 

c์™€ c++์—๋Š” ์ฐธ์กฐ ์†Œ์œ ๊ถŒ ์ •๋ณด๊ฐ€ ์—†์–ด ๋ณด์ˆ˜์  ์ฐธ์กฐ๋งŒ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

์„ ํƒ๋œ ํ• ๋‹น์„ _DataStorage ๊ฐ์ฒด๊ฐ€ ๋ณด์œ ํ•˜๊ณ  ์žˆ์Œ.

 

๋๊นŒ์ง€ ๊ฑฐ์Šฌ๋Ÿฌ ์˜ฌ๋ผ๊ฐ€๋ฉด thumbnailLoader.globalImageCache ๊ฐ€ ๋ณด์œ 

 

 

func faultThumbnail(from photoURL: URL) {
  // Cache the thumbnail based on url + creationDate
  let timestamp = UInt64(Date.now.timeIntervalSince1970) // Bad - caching with wrong timestamp
  let cacheKey = CacheKey(url: photoURL, timestamp: timestamp)

  let thumbnail = cacheProvider.thumbnail(for: cacheKey) {
    return makeThumbnail(from: photoURL)
  }
  images.append(thumbnail.image)
}

-> faultThumbnail ๋ฉ”์„œ๋“œ๊ฐ€ ์ธ๋„ค์ผ์„ ์บ์‹ฑํ•˜๊ณ  ์บ์‹œ ๋ฏธ์Šค ์‹œ ์ƒˆ ์ธ๋„ค์ผ ์ƒ์„ฑ

-> URL๊ณผ creationDate๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์บ์‹ฑํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ์ฃผ์„์— ๋˜์–ด์žˆ์ง€๋งŒ, ์ฝ”๋“œ๋ฅผ ๋ณด๋‹ˆ ํ˜„์žฌ ์‹œ๊ฐ„์œผ๋กœ ๋˜์–ด์žˆ๋‹ค. 

-> ์ด ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ ๋  ๋•Œ๋งˆ๋‹ค ํ•ญ์ƒ ์ƒˆ๋กœ์šด photoThumbnail์„ ์บ์‹œ

 

 

์›์ธ:

์ธ๋„ค์ผ ์บ์‹ฑ ์‹œ creationDate๊ฐ€ ์•„๋‹Œ ํ˜„์žฌ ์‹œ๊ฐ„์„ ํ‚ค๋กœ ์‚ฌ์šฉ   

์บ์‹œ ๋ฏธ์Šค๊ฐ€ ๋ฐ˜๋ณต๋˜๋ฉฐ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ 

 

func faultThumbnail(from photoURL: URL) {
  // Cache the thumbnail based on url + creationDate
  let timestamp = cacheKeyTimestamp(for: photoURL) // Fixed - caching with correct timestamp
  let cacheKey = CacheKey(url: photoURL, timestamp: timestamp)

  let thumbnail = cacheProvider.thumbnail(for: cacheKey) {
    return makeThumbnail(from: photoURL)
  }
  images.append(thumbnail.image)
}

 

ํ•ด๊ฒฐ:

์ •ํ™•ํ•œ ํŒŒ์ผ ์ƒ์„ฑ ์‹œ๊ฐ„์œผ๋กœ ์บ์‹ฑ ํ‚ค ์„ค์ • ( ์‹ค์ œ ํŒŒ์ผ ์ƒ์„ฑ ๋‚ ์งœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์บ์‹ฑ )

 

 

๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐœ๊ฒฌ

 

๐Ÿšจ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ถ„์„ ๋ฐ ์ˆ˜์ •

 

* reachability ๋„๋‹ฌ ๊ฐ€๋Šฅ์„ฑ ? 

 

ํž™์˜ 3๊ฐ€์ง€ ์ข…๋ฅ˜์˜ ๋ฉ”๋ชจ๋ฆฌ:

1. useful ์œ ์šฉํ•œ ๋ฉ”๋ชจ๋ฆฌ: ์‹ค์ œ๋กœ ์‚ฌ์šฉ ์ค‘ , ๋„๋‹ฌ ๊ฐ€๋Šฅ ๋‚˜์ค‘์— ๋‹ค์‹œ ์‚ฌ์šฉํ•  ๋ฉ”๋ชจ๋ฆฌ 

2. abandoned ๋ฒ„๋ ค์ง„ ๋ฉ”๋ชจ๋ฆฌ: ๋„๋‹ฌ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์œ ์ง€ ( ์‹ค์ œ๋กœ๋Š” ๋‹ค์‹œ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ ), ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์— ํฌํ•จ, ๋‚ญ๋น„ 

- ์บ์‹œ์— ๋ฐ์ดํ„ฐ ๋„ˆ๋ฌด ๋งŽ์ด ์ €์žฅ, ์‹ฑ๊ธ€ํ†ค์— ํฐ ์šฉ๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ ์œ ์ง€

3. Leaked ๋„๋‹ฌ ๋ถˆ๊ฐ€๋Šฅํ•œ ๋ฉ”๋ชจ๋ฆฌ: ์ฐธ์กฐ ์‚ฌ๋ผ์ง → ๋ˆ„์ˆ˜ , ์žฌ์‚ฌ์šฉ ์ ˆ๋Œ€ ๋ถˆ๊ฐ€๋Šฅ

 

๋Œ€๋ถ€๋ถ„์˜ ๋ˆ„์ˆ˜์˜ ๊ฒฝ์šฐ ํ•œ ์ˆœํ™˜์—์„œ ํ•˜๋‚˜์˜ ์ฐธ์กฐ๋ฅผ ์ฐพ์•„ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ

 

ํ”„๋กœ์ ํŠธ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ๋งŒ ๋ณด๊ธฐ

 

์Šค์œ„ํ”„ํŠธ ํด๋กœ์ €๊ฐ€ ๊ฐ’์„ ์บก์ฒ˜ํ•ด์•ผํ•  ๋•Œ ํž™์— ๋ฉ”๋ชจ๋ฅผ ํ• ๋‹นํ•ด ์ €์žฅ. ๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ž˜ํ”„ ๋””๋ฒ„๊ฑฐ๋Š” ์ด๋Ÿฌํ•œ ํ• ๋‹น์„ ํด๋กœ์ € ์ปจํ…์ŠคํŠธ๋กœ ํ‘œ์‹œ. ์•ฑ ํž™์˜ ๊ฐ ํด๋กœ์ € ์ปจํ…์ŠคํŠธ๋Š” ๋ผ์ด๋ธŒ ํด๋กœ์ €์™€ 1๋Œ€1 ๋Œ€์‘. ํด๋กœ์ €๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ฐธ์กฐ๋ฅผ ๊ฐ•ํ•˜๊ฒŒ ์บก์ฒ˜, ์ฐธ์กฐ์ˆœํ™˜์„ ๋งŒ๋“ฌ.

 

์›์ธ:

 ํด๋กœ์ € ๋‚ด self๋ฅผ ๊ฐ•ํ•˜๊ฒŒ ์บก์ฒ˜ → ์ˆœํ™˜ ์ฐธ์กฐ ๋ฐœ์ƒ

 

๊ฐ•ํ•œ ์ฐธ์กฐ๋ฅผ ์ฐพ์Œ > ํด๋กœ์ € ์ฝ”๋“œ ์ฐพ๊ธฐ

 

thumbnailloader ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ > ์™„๋ฃŒ ํ•ธ๋“ค๋Ÿฌ์— ํ• ๋‹น > ๋กœ๋”ฉ ์‹œ์ž‘ ์ง€์‹œ, ํด๋กœ์ €๊ฐ€ thumbnailRenderer๋ฅผ ๊ฐ•ํ•˜๊ฒŒ ์บก์ฒ˜ > ์ฐธ์กฐ์ˆœํ™˜

 

// ...
let renderer = ThumbnailRenderer(style: .vibrant)
let loader = ThumbnailLoader(bundle: .main, completionQueue: .main)
loader.completionHandler = {
  self.thumbnails = renderer.images // implicit strong capture of renderer causes strong reference cycle
}
loader.beginLoading(with: renderer)
// ...

 

// ...
let renderer = ThumbnailRenderer(style: .vibrant)
let loader = ThumbnailLoader(bundle: .main, completionQueue: .main)
loader.completionHandler = { [weak renderer] in
	guard let renderer else { return }

  self.thumbnails = renderer.images
}
loader.beginLoading(with: renderer)
// ...

 

ํ•ด๊ฒฐ:

 ํด๋กœ์ €์— [weak self] ๋˜๋Š” [unowned self] ์‚ฌ์šฉ

 ์˜ต์…”๋„ ์ฒ˜๋ฆฌ๋ฅผ ํ†ตํ•ด ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉ

 

๋ˆ„์ถœ ๋ณด๊ณ  > ๋ช…์‹œ์ ์œผ๋กœ ์ „์—ญ์— ์ €์žฅ > ๊ฐ์ฒด๋ฅผ ๋กœ์ปฌ ํ•จ์ˆ˜ ๋ฒ”์œ„ ๋ฐ”๊นฅ์— ์ €์žฅ.

 

๐Ÿš€ ๋Ÿฐํƒ€์ž„ ์„ฑ๋Šฅ ๊ฐœ์„ 

 

weak vs unowned ์ฐจ์ด

ํ•ญ์ƒ ์˜ต์…”๋„ ํƒ€์ž…, ์ˆ˜๋ช…๊ณผ ๊ด€๊ณ„์—†์ด ์‚ฌ์šฉ. ์ฝ”์ฝ”๋„›์ด ์ œ๋น„ ์ฐธ์กฐ. ๋Œ€์ƒ ๊ฐ์ฒด์— ๋Œ€ํ•œ weak ์ฐธ์กฐ ์ €์žฅ์†Œ ํ• ๋‹น,

 

 

๋Œ€์ƒ์„ ์ง์ ‘ ๋ณด์œ , ์ถ”๊ฐ€๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , weak ์ฐธ์กฐ๋ณด๋‹ค ์ ‘๊ทผ์‹œ๊ฐ„์ด ์งง์Œ.์˜ต์…”๋„์ด ์•„๋‹์ˆ˜๋„ ์žˆ๊ณ  ์ƒ์ˆ˜์ผ ์ˆ˜๋„. ํ•ญ์ƒ ์œ ํšจํ•œ๊ฑด ์•„๋‹˜. swallow๊ฐ€ ์ฐธ์กฐ๋ณด๋‹ค ๋จผ์ € ์‚ฌ๋ผ์ง€๋ฉด swallow๋Š” ์ œ๊ฑฐ๋˜์ง€๋งŒ ํ• ๋‹น์ด ํ•ด์ œ๋˜์ง€๋Š” ์•Š์Œ.

 

- unowend ์ฐธ์กฐ๋Š” ๋ฐ˜๋“œ์‹œ ๋ฌด์–ธ๊ฐ€๋ฅผ ๊ฐ€๋ฆฌ์ผœ์•ผ ํ•˜๋ฏ€๋กœ  ๋Ÿฐํƒ€์ž„์€ swallow๋ฅผ ์œ ์ง€

- weak ์ฐธ์กฐ๋ฅผ ๊ฐ•์ œ๋กœ ์–ธ๋ž˜ํ•‘ํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šท

- ์ฐธ์กฐ ๋Œ€์ƒ์€ ํ• ๋‹น ํ•ด์ œ๋  ์ˆ˜ ์—†๊ณ , ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„

 

 

๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ž˜ํ”„์— weak์ฐธ์กฐ ๋˜๋Š” unowned ์ฐธ์กฐ๊ฐ€ ๋ณด์ด์ง€ ์•Š์œผ๋ฉด xcode์—์„œ ํ”„๋กœ์ ํŠธ์˜ reflection metadata level ๋นŒ๋“œ ์„ค์ • ํ™•์ธํ•ด์•ผ ํ• ์ˆ˜ ์žˆ์Œ. ๋˜๋„๋ก ๊ธฐ๋ณธ๊ฐ’์ธ all level ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ.

 

class ByteProducer {
  let data: Data
  private var generator: ((Data) -> UInt8)? = nil

  init(data: Data) {
    self.data = data
    generator = defaultAction // Implicitly uses `self`
  }

  func defaultAction(_ data: Data) -> UInt8 {
    // ...
  }
}

- defaultAction ๋ฉ”์„œ๋“œ์— ํ• ๋‹น๋œ ํด๋กœ์ €๋ผ๋Š” ์ƒ์„ฑ๊ธฐ ์†์„ฑ์ด ์žˆ์Œ. ์•”๋ฌต์ ์œผ๋กœ self ์‚ฌ์šฉ. 

๋ฉ”์„œ๋“œ๋ฅผ ํด๋กœ์ €๋กœ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋งค์šฐ ์กฐ์‹ฌ

 

defaultAction์„ ํ˜ธ์ถœํ•˜๋Š” ํด๋กœ์ € ์ •์˜. > self ์บก์ฒ˜๊ฐ€ ๋ช…์‹œ์ . weak. unowned ๊ฐ€๋Šฅ : ์ƒ์„ฑ๊ธฐ ํด๋กœ์ €๋Š” ๋Œ€์ƒ์ธ byteProducer ์ธ์Šคํ„ด์Šค์™€ ์ˆ˜๋ช… ๋™์ผ.ํด๋กœ์ €๋Š” ๋‹ค๋ฅธ ์ฝ”๋“œ๋กœ ํ• ๋‹น๋˜๊ฑฐ๋‚˜ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๋””์ŠคํŒจ์น˜ ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์บก์ฒ˜๋œ ์ž์‹ ๋ณด๋‹ค ์˜ค๋ž˜ ์ง€์†๋  ์ˆ˜ ์—†์Œ

 

unowned๋Š” ๋ฉ”๋ชจ๋ฆฌ ํ•„์š”์—†์Œ. ๊ธฐ๋ณธ๊ฐ’์€ weak. unowned์€ ์ฐธ์กฐ๊ฐ€ ๋Œ€์ƒ๋ณด๋‹ค ์˜ค๋ž˜ ์ง€์†๋˜์ง€ ์•Š์Œ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์„๋•Œ ๋ฉ”๋ชจ๋ฆฌ๋ž‘ ์‹œ๊ฐ„ ์ ˆ์•ฝ. cpu ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์œ ๋ฐœํ•˜๋Š” ์˜์—ญ์„ ์ฐพ์œผ๋ ค๋ฉด ํ”„๋กœํŒŒ์ผ๋ง > swift_weakLoadStrong()๊ณผ ๊ฐ™์€ ๋Ÿฐํƒ€์ž„ ํ•จ์ˆ˜์— ๋Œ€ํ•œ ํ˜ธ์ถœ ์ฐพ๊ธฐ.

 

 

 

์„ฑ๋Šฅ ์ตœ์ ํ™” ํŒ

-whole-module-optimization ํ™œ์„ฑํ™”

๊ตฌ์กฐ์ฒด๋Š” ๋‹จ์ˆœํ™”ํ•˜์—ฌ ๋ณต์‚ฌ ๋น„์šฉ ์ค„์ด๊ธฐ

ARC๋ฅผ ์šฐํšŒํ•˜์ง€ ๋ง ๊ฒƒ

Objective-C๋Š” objc_direct, objc_externally_retained ๋“ฑ์„ ํ™œ์šฉ

 

 

๐ŸŽฏ ํ•ต์‹ฌ ๋ฉ”์‹œ์ง€ ์š”์•ฝ

ํž™ ๋ฉ”๋ชจ๋ฆฌ ์ตœ์ ํ™”๋Š” ์•ฑ ์•ˆ์ •์„ฑ๊ณผ ์„ฑ๋Šฅ ํ–ฅ์ƒ์— ํ•„์ˆ˜

๋ฉ”๋ชจ๋ฆฌ ๋ฌธ์ œ๋Š” ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐ˜๋ณต ์ธก์ • ๋ฐ ์ถ”์ ์œผ๋กœ ํ•ด๊ฒฐ ๊ฐ€๋Šฅ

์ž๋™ ๋ฆด๋ฆฌ์ฆˆ ํ’€, ํด๋กœ์ €์˜ ์บก์ฒ˜ ๋ฐฉ์‹์— ์ฃผ์˜ํ•ด์•ผ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€

weak/unowned ์„ ํƒ์€ ์ˆ˜๋ช…์— ๋”ฐ๋ผ ๊ฒฐ์ •

ํ”„๋กœํŒŒ์ผ๋ง๊ณผ ๋„๊ตฌ ํ™œ์šฉ ๋Šฅ๋ ฅ์ด ๊ฐœ๋ฐœ์ž ์ˆ™๋ จ๋„๋ฅผ ์ขŒ์šฐ

๋ฐ˜์‘ํ˜•