- 퍼포먼스도 여러가지 측면이 있다.
- 실행 속도, 전력 소모량, 메모리 소모량
- 이는 어떤 크기의 데이터를 얼마나 자주 처리하는 지로 간략화 할 수 있다.
- 큰 데이터 처리가 자주 일어나면 당연히 느려진다.
- 작은 데이터 처리가 드물게 일어나면 별로 신경쓸 일이 없다.
- 문제는 그 사이의 회색 지대들이다. 이 영역은 측정이 필요하다.
- 작은 데이터를 자주 처리
- 큰 데이터를 가끔 처리
- Improvements in Foundation
- NSCalendar의 성능 향상 및 엣지 케이스 처리 능력 향상
- 내부적인 락 성능 향상
- NSOperation, NSOperationQueue 성능 향상
- Copy on write 콜렉션 도입
- Swift에서 쓰던 것을 Foundation에 역수입
- 변경이 일어나기 전까지, 복사는 상수 시간에 이루어진다.
@property (strong) NSArray<Item *> *items; // 의도치 않은 공유가 일어날 수 있다.
@property (copy) NSArray<Item *> *items;
- (NSArray<Item*> *items {
NSMutableArray *items = [[ NSMutableArray alloc] init];
[self buildItems: items];
// items를 그대로 반환하지 말고, copy해서 반환하라
return [items copy]
}
aNSArray as? [Any] // copy가 일어난다.
- Data: bytes열을 다루는 타입
- 개별적인 slice를 가짐
- 최적화된 빌드에서는 인덱스 참조도 효율적으로 일어남(16ns -> 4ns)
- append도 빠르다.
- region 단위로 갈아끼우는 것도 빠르다.
var bytes = [oxcf, 0xfa, 0xed, 0xfe] // 과거
var bytes = Data(bytes: [oxcf, 0xfa, 0xed, 0xfe]) // 현재
var buffer = malloc(250).assumingMemoryBound(to: UInt8.self)
defer { free(buffer) } // 과거
var buffer = Data(count: 250)
let header = buffer.subdata(in buffer.startIndex..<buffer.startIndex.advanced(by: 4)) // 과거, 복사가 일어남
let header = buffer[..<buffer.startIndex.advanced(by: 4)] // 복사 없음
- bridges and how the affect your app
- 무비용 전환(Toll-free bridging)
- CF <-> NS의 전환이 자유롭다.
- 캐스팅에는 코스트가 들어가지 않는다.
- 다만 사용할 때는 코스트가 들어간다.
- 이는 CF호출을 할때, 실제 CF 객체가 아니면 NS로 다시 해석하기 때문이다. -> 호출 비용이 2배로 발생
- Swift 브릿지
- 참조 타입 <-> 값 타입 사이의 전환
- 캐스팅 될 때 이미 코스트가 발생 -> 캐스팅하는 과정에서 복사되기 때문
- 사용할 때는 추가 코스트 없음
- 이러한 브릿지는 하나하나는 작지만, 모이면 큰 비용일 수 있다. 반드시 측정해야 된다.
- Strings, ranges, and text
- String은 굉장히 자주 쓰이기 때문에, 사용자 시나리오에 맞춰서 성능을 체크해야 한다.
- String bridging
- Objective-C로 된 프레임워크에서 온 String(Ex. UIKit)은, NSString을 저장소로 가진다.
- 불변 객체라면, 복사되도 레퍼런스 카운팅만 될테니 비교적 저렴하다.
- 하지만 가변 객체라면, copy비용이 상당하다. -> 이 때 Stirng이 아닌 NSMutableString으로 받으면 카피 비용이 사라진다. 아직 해결법이 없으니 성능 향상을 위해서는 바꿀 생각이 없더라도 그렇게 받는 것이 좋다.
- Ranges
-
이모지같은 경우는 Unicode Scalar하나가 크기를 크게 가질 수 있다.
-
이 때 NSAttributedString을 쓰기 위해 NSString과 String을 왔다갔다 하면 별로 좋지 않다.
-
그래서 NSRange에 String과 range를 인자로 받는 생성자를 추가해서 브릿징을 최소화했다.
- Text Layout and rendering
- 텍스트 처리는 수많은 성능적인 고려사항이 필요한 복잡한 것이다.
- 특정 언어에 대한 렌더링과 인풋 최적화는, 다른 언어에서 통하지 않는 경우가 있다.
- best practice
- 표준 컴포넌트를 쓰라.
- 모던 레이아웃(오토 레이아웃)을 쓰라
- 렌더링에 필요한 attribute들을 직접 제공해주는 것도 도움이 된다. -> 없으면 시스템이 결정하는데, 이 오버헤드를 줄이자는 것
- alignment와 writingDirection이 확실히 정해져 있다면, 미리 명시해두는 것도 좋다.
- 단일 라인 라벨에 대해서는 클리핑을 쓰면 성능에 좋다.