배경NumberFormatter는 생성 비용이 크고 내부 상태를 가지기 때문에, 멀티스레드 환경에서 공유할 경우 성능 최적화와 함께 스레드 안정성도 중요한 고려사항입니다.이번 실험에서는 os_unfair_lock, Mutex(NSLock), RecursiveLock, SpinLock 등 여러 락 기법을 사용해 NumberFormatter를 공유했을 때의 실행 시간, CPU 효율, 메모리 사용량을 측정하여 가장 효율적인 방법을 분석하였습니다. 성능 측정 지표 정의Clock Time실제 경과 시간 (사용자가 체감하는 대기 시간)CPU Time모든 스레드의 CPU 연산 총합CPU 활용도CPU Time ÷ Clock Time × 100 (멀티코어 활용도 지표)Memory Peak프로그램 실행 중 가장 많이 사용..
배경이전 포스팅에서 10개 스레드로 NumberFormatter 성능을 테스트했지만, 최적의 스레드 수에 대한 의문이 남았습니다.이번에는 1개부터 8개까지 체계적으로 측정하여 진짜 최적점을 찾아보았습니다. 또한 Clock Time 뿐만 아니라 Memory Peak 등에 대해서도 고려했습니다. 테스트 환경하드웨어: MacBook Pro M1 (4P + 4E 코어)측정: XCTest measure() 100,000번 반복메트릭: Clock Time, CPU Time, Memory Peak조건: 모든 테스트에서 동일한 NumberFormatter 설정 성능 테스트 결과방식스레드Clock Time (초)CPU Time (초)CPU 효율Memory Peak (KB)성능 향상매번 생성1개4.1214.09899.4%..
검증NumberterKit이 그럼 기존의 Race Condition 문제를 해결했는지와 실제로 성능은 어느정도 개선되었는지에 대해 분석하였습니다. 테스트 케이스를 통한 검증앞서 수동 테스트로 동작을 확인했지만,신뢰할 수 있는 결과를 보장하기 위해 XCTestCase를 통한 자동화 테스트도 함께 진행하였습니다.다음과 같이 Race Condition 재현 테스트를 테스트 케이스로 등록하여,매번 일관된 결과가 출력되는지 검증했습니다.import XCTestfinal class FormatterProviderTests: XCTestCase { func testDecimalFormatterRaceSafe() { let number = NSNumber(value: 1234.5678) ..
NumberFormatter()를 개발하던 도중, static Formatter 공유 방식이 멀티스레드 환경에서 Race Condition을 유발한다는 테스트 결과를 확인하였습니다. 이번 개선에서는 해당 테스트를 동일하게 반복 실행하여,SpinLock 동기화 적용 전후의 차이를 직접 검증하였습니다. 결과적으로, SpinLock을 적용한 이후에는 설정 충돌 없이 일관된 결과가 출력됨을 확인할 수 있었습니다. 공용 NumberForamtter() 인스턴스 접근앞선 블로그에서 작성했듯이, 다음과 같은 문제점이 발생하였습니다.public extension Decimal { func formatted(fractionDigits: Int) -> String { FormatterProvider.d..
데이터 변환의 불편함iOS 앱을 개발하다 보면 숫자를 문자열로 변환하거나, 통화 및 퍼센트로 표시하는 등의 작업을 반복적으로 하게 됩니다. 저 또한 최근에 개발한 프로젝트가 가상 화폐와 관련된 프로젝트였기 때문에 Int64, Decimal 등의 데이터 타입의 변환이 빈번하게 발생하였습니다. 보통 이런 상황에서 Extension이나 Formatter와 관련된 폴더 및 파일을 생성하고 관리합니다.하지만 이러한 처리 로직이 프로젝트마다 다르게 작성되고, formatter 설정 방식도 일관되지 않다 보니 유지보수가 어려워지는 문제를 겪게 되었습니다. 특히, 같은 Decimal 타입이라도 어떤 화면에서는 소수점 없이, 어떤 화면에서는 소수점 둘째 자리까지 표현해야 하는 상황이 빈번하게 발생하였고, 이에 따른 fo..