(재미로 봐주세요..ㅎㅎ)
unowned를 쓰는 것은 불편합니다. 왜냐면 unowned로 참조한 친구가 사라져버리면 그 포인터가 가리키는 값이 댕글링 포인터가 되어버려서 터질 수도 있기 때문이에요.
사실 Unowned로 선언하면 옵셔널 체이닝을 안해도 되는 간편함이 있긴 하지만, 차라리 옵셔널 체이닝을 하더라도 터지지 않는 앱을 위해 상황 하나 하나를 다 들여다보는게 더 귀찮더라고요.
그래서 전 그냥 weak를 쓰지만, 쓸 때마다 마음에 부채가 생겼습니다...;;
내가 엄청난 성능적 죄악을 저지르고 있는 것이 아닐까? 애플이 unowned를 괜히 만들지는 않았을텐데...

대충 이런 느낌...
그래서!!! 과연 얼마나 성능에 영향을 미치는지 테스트를 해봤습니다.
테스트는 할당과 해제를 많은 수로 반복하면서 Unowned로 선언된 변수가 참조했을 때, Weak로 선언된 변수가 참조했을 때 할당과 해제까지 얼마나 걸리는지를 보았고, 그 차이를 NanoSecond (1 / 1,000,000,000 초)로 재보았습니다.
비루한 m1 pro 맥북으로 돌리는거라 테스트 횟수를 많이 할 수도 없고, 이게 정말 맞는 방법인지 확실하지 않기 때문에 재미로 봐주시기 바랍니다..ㅎㅎ
20번을 테스트한 최종적 결과는 ...!!!
---------------------------------------
Unowned vs Weak 할당과 제거까지의 속도 테스트
(테스트는 100,000번의 할당과 제거를 20번 반복하였습니다.)
---------------------------------------
...
모든 테스트 케이스
1/20 test
Unowned 소요시간: 3339171375(ns)
Weak 소요시간: 3313989000(ns)
Unowned가 얼마나 빨랐을까?: -25182375(ns)
2/20 test
Unowned 소요시간: 3286848375(ns)
Weak 소요시간: 3260208667(ns)
Unowned가 얼마나 빨랐을까?: -26639708(ns)
3/20 test
Unowned 소요시간: 3235051000(ns)
Weak 소요시간: 3257529791(ns)
Unowned가 얼마나 빨랐을까?: 22478791(ns)
4/20 test
Unowned 소요시간: 3230886167(ns)
Weak 소요시간: 3233442375(ns)
Unowned가 얼마나 빨랐을까?: 2556208(ns)
5/20 test
Unowned 소요시간: 3230484875(ns)
Weak 소요시간: 3247422125(ns)
Unowned가 얼마나 빨랐을까?: 16937250(ns)
6/20 test
Unowned 소요시간: 3226592416(ns)
Weak 소요시간: 3245514833(ns)
Unowned가 얼마나 빨랐을까?: 18922417(ns)
7/20 test
Unowned 소요시간: 3230438000(ns)
Weak 소요시간: 3244768583(ns)
Unowned가 얼마나 빨랐을까?: 14330583(ns)
8/20 test
Unowned 소요시간: 3220529250(ns)
Weak 소요시간: 3233302875(ns)
Unowned가 얼마나 빨랐을까?: 12773625(ns)
9/20 test
Unowned 소요시간: 3245940959(ns)
Weak 소요시간: 3334592458(ns)
Unowned가 얼마나 빨랐을까?: 88651499(ns)
10/20 test
Unowned 소요시간: 3238710667(ns)
Weak 소요시간: 3235795208(ns)
Unowned가 얼마나 빨랐을까?: -2915459(ns)
11/20 test
Unowned 소요시간: 3250374542(ns)
Weak 소요시간: 3247595333(ns)
Unowned가 얼마나 빨랐을까?: -2779209(ns)
12/20 test
Unowned 소요시간: 3239318458(ns)
Weak 소요시간: 3266977666(ns)
Unowned가 얼마나 빨랐을까?: 27659208(ns)
13/20 test
Unowned 소요시간: 3244912750(ns)
Weak 소요시간: 3247433125(ns)
Unowned가 얼마나 빨랐을까?: 2520375(ns)
14/20 test
Unowned 소요시간: 3270567375(ns)
Weak 소요시간: 3254390958(ns)
Unowned가 얼마나 빨랐을까?: -16176417(ns)
15/20 test
Unowned 소요시간: 3240328625(ns)
Weak 소요시간: 3257867917(ns)
Unowned가 얼마나 빨랐을까?: 17539292(ns)
16/20 test
Unowned 소요시간: 3248741417(ns)
Weak 소요시간: 3267059333(ns)
Unowned가 얼마나 빨랐을까?: 18317916(ns)
17/20 test
Unowned 소요시간: 3251601375(ns)
Weak 소요시간: 3259435375(ns)
Unowned가 얼마나 빨랐을까?: 7834000(ns)
18/20 test
Unowned 소요시간: 3249609708(ns)
Weak 소요시간: 3260183500(ns)
Unowned가 얼마나 빨랐을까?: 10573792(ns)
19/20 test
Unowned 소요시간: 3267382958(ns)
Weak 소요시간: 3253696292(ns)
Unowned가 얼마나 빨랐을까?: -13686666(ns)
...
---------------------------------------
Unowned 평균 소요시간: 3087374514(ns)
Weak 평균 소요시간: 3096060270(ns)
Unowned가 평균적으로 얼마나 빨랐을까? : 8685756(ns)
---------------------------------------
결론적으로...! 정말 거의 차이가 없더라고요.
일단 unowned가 빠르긴 했지만, 많이 빠르진 않았고 심지어 weak가 더 빠른 테스트 케이스도 있었습니다....
10만번을 반복한 실험의 20회 평균이 8685756ns 의 차이라니!!!
이거 초로 환산하면... 0.008685756초의 차이밖에 안나요...
물론 다른 오버헤드가 있을 수도 있겠지만 그래도 꼭 위험을 감수하면서 unowned 써야할까요?? 정말 잘 모르겠네요..!ㅎㅎㅎ
누가 알려줬으면 좋겠다. 어 이거 아닌데.. 싶으면 절대 참지 말아주세요ㅎㅎ

테스트는 다음과 같이 진행하였습니다.
import Foundation
class TestClass {
var value: Int = 0
}
var unownedTotal: Int = 0
var weakTotal: Int = 0
print("---------------------------------------")
print("Unowned vs Weak 할당과 제거까지의 속도 테스트")
print("(테스트는 100,000번의 할당과 제거를 20번 반복하였습니다.)")
print("---------------------------------------")
for idx in 1 ..< 20 {
print("\(idx)/20 test")
// Unowned
var startTime = DispatchTime(uptimeNanoseconds: 0)
startTime = DispatchTime.now()
for _ in 0 ..< 100000 {
let TestClass = TestClass()
unowned var unownedReference: TestClass? = TestClass
unownedReference?.value = 10
unownedReference = nil
}
var endTime = DispatchTime(uptimeNanoseconds: 0)
endTime = DispatchTime.now()
var nanoTime = endTime.uptimeNanoseconds - startTime.uptimeNanoseconds
print("Unowned 소요시간: \(nanoTime)(ns)")
var temp = nanoTime
// Weak
startTime = DispatchTime.now()
for _ in 0 ..< 100000 {
let TestClass = TestClass()
weak var weakReference: TestClass? = TestClass
weakReference?.value = 10
weakReference = nil
}
endTime = DispatchTime.now()
nanoTime = endTime.uptimeNanoseconds - startTime.uptimeNanoseconds
print("Weak 소요시간: \(nanoTime)(ns)")
print("Unowned가 얼마나 빨랐을까?: \(Int(nanoTime) - Int(temp))(ns)\n\n")
unownedTotal += Int(temp)
weakTotal += Int(nanoTime)
}
print("---------------------------------------")
print("Unowned 평균 소요시간: \(unownedTotal / 20)(ns)")
print("Weak 평균 소요시간: \(weakTotal / 20)(ns)")
print("Unowned가 평균적으로 얼마나 빨랐을까? : \((weakTotal - unownedTotal) / 20)(ns)")
print("---------------------------------------")
'iOS 개발 > Swift' 카테고리의 다른 글
Swift Hashable을 이해하자 (0) | 2023.12.26 |
---|---|
[Swift] iOS는 화면을 어떻게 렌더링할까? (1) | 2023.10.04 |
[Swift] Struct와 Class를 메모리 원리부터 자세하게 비교해보자 (2) | 2023.02.12 |
[ARC] Lazy 변수 클로저에서 Unowned 캡처가 항상 안전할까? (0) | 2023.02.02 |
[Concurrency] Semaphore로 비동기적 이벤트를 동기적으로 발생시키기 (0) | 2023.01.20 |
[ARC] 약한참조(Weak, Unowned)에 대해서 (0) | 2022.11.06 |
[Swift] 지정한 For-Loop 탈출하기 (0) | 2022.10.03 |
[Swift] Stride 함수를 사용하자 (0) | 2022.10.02 |