엔지니어링 업데이트
Photo Explorer, Constellations, 그리고 더욱 빠른 Mapsake
두 가지 야심 찬 사진 기능이 동일한 질문을 제기했습니다. Mapsake는 속도를 늦추지 않고 훨씬 더 많은 작업을 수행할 수 있을까요? 새로운 시뮬레이터 및 장치 벤치마크 세트가 이 질문에 측정 가능한 엔지니어링 방식으로 답변했습니다.
기능 출시 및 엔지니어링 출시입니다.
이 업데이트는 Mapsake의 가장 야심찬 사진 경험 두 가지를 소개합니다. 사진 탐색기, 은 대규모 지도 라이브러리를 검색 가능하게 하며, 별자리, 은 멀리 떨어진 장소 간의 시각적 연결을 발견합니다.
또한, 릴리스에서 가장 눈에 띄지 않는 기능인 영구 성능 벤치마크 스위트가 포함되어 있습니다. 이 스위트는 가장 느린 공유 경로를 즉시 찾아 수정 사항을 측정 가능하게 만들고, 향후 작업이 이를 다시 느리게 만들 때 앱이 감지할 수 있는 방법을 제공했습니다.
결과는 단순히 더 많은 기능을 제공하는 것이 아닙니다. Mapsake는 대규모 사진 라이브러리를 장소로 변환하고, 근처 도시를 찾고, 별자리의 하늘을 계획하는 데 훨씬 빠릅니다.
Photo Explorer는 카메라 롤이 아닌 여행 기록을 검색합니다.
Photo Explorer는 Mapsake가 이미 매핑된 사진에 대해 유지하는 간결한 메타데이터로 시작합니다. 여기에는 위치, 날짜, 소스, 카메라, 메모, 고도, 속도, 즐겨찾기, 스크린샷, 편집, 그리고 앱 내에서 추가된 구성이 포함됩니다.
인덱스는 장치에 저장됩니다. 검색은 직접 검색(예: 일본, 2024, iPhone, 즐겨찾기) 또는
검색은 라이브러리에 접근하는 방법 중 하나입니다. 컬렉션은 유용한 그룹을 제공하고, 지도 영역은 결과를 지리적으로 제한하며, 타임라인은 날짜별로 그룹화하고, 저장된 검색 및 최근 검색은 반복적인 질문을 쉽게 할 수 있도록 합니다. 즐겨찾기, 평가, 태그, 레이블 및 메모는 로컬 보조 데이터로 저장되므로, 사진을 정리할 때 원본 파일을 변경하거나 업로드하지 않습니다.
중요한 아키텍처 선택은 각 도구가 동일한 인덱스된 스냅샷을 공유한다는 것입니다. 컬렉션, 타임라인, 지도, 그리고 텍스트 검색은 각각 82,000 사진으로 구성된 세상을 처음부터 다시 구축하지 않습니다.
인덱스는 파생되고, 개인 구성은 영구적입니다.
Photo Explorer는 매우 다른 수명 주기를 가진 두 가지 유형의 스토리지가 필요했습니다. 위치 이름, 촬영 연도, 카메라, 고도, 소스와 같은 검색 필드는 Mapsake의 기존 메타데이터에서 다시 구축할 수 있습니다. 즐겨찾기, 개인 메모, 평점, 태그 또는 색상 레이블은 사용자가 작성한 것이므로 일시적인 캐시 데이터로 취급할 수 없습니다.
따라서 Mapsake는 사용자가 만든 구성 요소를 백업 가능한 작은 사이드카에 저장합니다. 더 큰 검색 인덱스는 캐시에 저장되며, 이미지 바이트는 포함되지 않고 백업에서 제외되며, 스키마가 변경될 때마다 다시 생성할 수 있습니다. 라이브러리를 다시 스캔하거나 파생 데이터를 지우더라도 누군가가 정리하는 데 쏟은 노력은 사라지지 않습니다.
이 구분은 백업을 더욱 정확하게 만들었습니다. 압축되지 않은 JSON 및 HTML 백업은 메모와 정리를 유지할 수 있지만, 사진 아카이브로 조용히 팽창하지 않습니다. Apple Photos의 주석은 iCloud 식별자를 최대한 유지하므로 복원된 백업은 다른 Apple 장치의 로컬 복사본에 다시 연결할 수 있습니다. Immich 자산 식별자는 이미 소스에서 안정적입니다.
첫 번째 전체 스트레스 테스트에서 약 12.4 MB의 압축된 인덱스가 82,000장의 사진에 대해 생성되었습니다. 개발 시뮬레이터에서의 초기 지리적 빌드는 2.61초가 걸렸고, 디스크에서 나중에 복원하는 데는 1.20초가 걸렸으며, 컬렉션 생성에는 126 밀리초가 걸렸고, 일일 타임라인 모델에는 211 밀리초가 걸렸습니다. 이러한 숫자는 기능의 각 부분에 자체 예산을 할당하여 모든 것을 하나의 일반적인 "검색" 측정값 뒤에 숨기는 대신 개별적으로 관리할 수 있도록 했습니다.
Photo Explorer는 항목이 일치하는 이유를 설명합니다. 결과는 특정 위치, 2024, iPhone 카메라, 개인 메모 또는 선택한 필터와 일치한다고 나타낼 수 있습니다. 이 작은 정보는 자연어와 여러 정확한 제어를 결합한 쿼리를 사용하는 경우에 중요합니다. 사용자는 검색 엔진이 의도한 의미를 추측할 필요가 없습니다.
검색 언어는 인터페이스이며, 자유롭게 사용하는 라이선스가 아닙니다.
모든 지원되는 쿼리는 궁극적으로 유효한 필터 구조로 변환됩니다. 직접적인 경로는 장소, 날짜, 소스, 카메라 모델, 메모, 즐겨찾기, 평가, 태그, 고도, 속도, 스크린샷, 그리고 편집된 사진 등을 인식합니다. 제한된 철자 교정기는 의도된 단어와 알려진 색인 단어를 수정할 수 있지만, 임의의 개인 메모를 다시 쓰지는 않습니다.
Apple의 온디바이스 Foundation 모델을 지원하는 기기에서는 입력된 텍스트도 동일한 제한된 구조로 해석할 수 있습니다. 제공되는 정보는 쿼리와 현재 연도에 국한됩니다. 사진 픽셀, 메타데이터 인덱스, 위치 정보, 그리고 개인적인 정보는 제공되지 않습니다. 유효하지 않은 범위나 알 수 없는 값은 거부되며, 결정적인 파서가 대체 수단으로 사용됩니다.
인터페이스는 해석 결과를 보여주고 원래 단어로 돌아가는 방법을 제공합니다. 이 부분에서는 창의성이 유용하려면 검토 가능해야 합니다. “3,000 미터 이상 높이의 작년 사진”은 대화체로 느껴져야 하지만, 여전히 정확한 필터 세트로 작동해야 합니다.
Constellations는 거리에서 반복되는 패턴을 찾습니다.
'Then & Now'는 누군가가 같은 장소로 돌아갔는지 확인합니다. 반대로 'Constellations'는 거의 반대 질문을 합니다. 즉, 멀리 떨어진 장소에서 어떤 시각적 아이디어가 반복되었는지 묻는 것입니다.
온장치 인덱스는 대상 여행 사진에서 시각적 신호와 모티프의 작은 집합을 추출합니다. 플래너는 이미지에만 고유한 특징을 찾고, 다양한 목적지에서 후보를 연결합니다. 문, 해안선, 스카이라인, 산의 형태, 색상, 계절, 구도 등이 스레드의 어휘가 될 수 있습니다.
해당 스레드는 3차원 하늘로 구성되어 있습니다. 사용자는 이 안에서 자유롭게 이동하고, 별자리를 열고, 연결을 유지하거나 해제하고, 관련된 사진이 한 장소에서 다른 장소로 녹아드는 매치컷 영화를 재생할 수 있습니다. 공유 카드와 리일은 동일한 저장된 스레드 데이터를 사용합니다.
추출 및 계획 작업은 장치에서 수행됩니다. Mapsake는 여행 라이브러리를 이미지 분석 서비스로 보내지 않습니다. 백그라운드 일괄 처리는 첫 번째 실행이 전체 라이브러리를 기다리지 않고도 시간이 지남에 따라 인덱스를 심화할 수 있습니다.
시각적 인덱스는 저렴하게 재조정할 수 있도록 설계되었습니다.
Mapsake는 각 대상 사용자에 대해 작은 이미지 디코딩을 수행하고 여러 신호를 파생합니다. 여기에는 Vision 특징, 원시 분류기 레이블, 간결한 색상 팔레트 및 위치, 시간 및 태양 고도에서 추정된 광 클래스가 포함됩니다. 특징은 유사성을 판단하는 데 사용되는 작은 숫자 데이터이며 이미지의 복사가 아닙니다. 표시할 수 없습니다.
인덱스는 제품에 표시되는 디자인 요소로 즉시 대체하는 대신, 원본 분류기 식별자를 저장합니다. 이러한 선택은 실제 라이브러리 테스트에서 효과를 발휘했습니다. 초기 디자인 요소 목록에는 적절하게 들리는 레이블이 포함되어 있었지만, 실제로 Vision에서 지원하는 분류 체계에는 존재하지 않았습니다. 원본 레이블이 여전히 사용 가능했기 때문에 “타워와 다리”, “보트와 항구”와 같은 디자인 그룹을 재구성하는 것은 수천 개의 원본 데이터를 다시 스캔하는 대신, 빠른 평가 프로세스를 통해 가능했습니다.
인덱싱은 최신부터 순서대로 라이브러리 전체를 읽는 대신 대표적인 사진부터 시작됩니다. 사진은 대략적인 위치 셀과 날짜별로 그룹화되며, 유용한 정지 이미지를 우선시하고, 연속 촬영 간의 간격을 둡니다. 플래너는 위치를 순환 방식으로 이동합니다. 이를 통해 젊은 인덱스는 지리적 폭을 가지며, 백그라운드 일괄 처리를 통해 점진적으로 깊이를 더합니다.
첫 번째 버전에서는 각 위치에 대해 한 장의 사진만 선택했습니다. 실제 장치 데이터를 통해 대부분의 위치가 스레드 엔진에서 사용하는 세 장의 최소 사진 수보다 적다는 것을 알 수 있었습니다. 따라서 인덱싱된 자산이 수천 개가 있어도 후보가 나타나지 않는 경우가 있었습니다. 각 라운드를 세 개의 대표적인 사진으로 나누어 인덱스가 더 빨리 유용해지도록 했지만, 총 예산은 증가시키지 않았습니다. 이는 합성 테스트와 실제 복잡한 라이브러리가 모두 중요하다는 명확한 이유입니다.
추출기는 시리얼 일괄 처리로 작동하며, 진행 상황을 원자적으로 커밋하고, 열 방출로 인해 일시 중지하며, 저전력 모드에서는 백그라운드 추출을 건너뜁니다. 장치에 이미 있는 Apple Photos의 썸네일이 먼저 시도되고, iCloud에서만 사용할 수 있는 이미지는 나중에 네트워크 연결이 허용된 경우에 처리됩니다. Immich는 기존 썸네일 클라이언트를 통해 동일한 시각적 파이프라인을 사용합니다.
유사성만으로는 스토리를 만들 수 없습니다.
기능 기반 거리 측정 기능을 사용하면 시각적으로 유사한 두 장의 사진을 찾을 수 있지만, Constellations는 중복 감지 기능이 아닌 장소 간의 연결을 찾는 데 사용됩니다. 후보 사진은 최소 150 킬로미터 이상 떨어진 목적지에 속해야 합니다. 또한 엔진은 독특한 모티프, 특이한 조명, 계절 및 반복되는 달력 의식을 고려하여 연결을 생성합니다.
"독특함"이 가장 어려운 부분이었습니다. 초기 점수 모델은 두 장소 모두에 존재하는 특징을 우선시했습니다. 개발 라이브러리에서는 이로 인해 밤과 일반적인 계절과 관련된 수백 개의 연결이 지배적이었습니다. 이러한 특징은 기술적으로 공유되었지만, 그다지 놀랍지는 않았습니다. 이제 엔진은 차이를 평가합니다. 특징은 개인의 전체 라이브러리와 비교하여 두 장소 모두에서 비정상적으로 강할 때 중요합니다.
이는 질문을 '두 장소 모두 밤 사진을 포함하고 있습니까?'에서 '두 장소 모두 이 라이브러리에서 밤 사진이 비정상적으로 많은가요?'로 바꿨습니다. 일반적인 신호는 배경으로 사라지지만, 반복되는 푸른 시간, 문 모양, 항구, 겨울 빛 또는 특정 휴가 주가 의미가 될 수 있습니다.
시각적 후보는 각 장소에 여러 대표적인 장소를 사용하며, 단일 "행운의 쌍"을 사용하는 것이 아닙니다. 스레드 식별자는 장소와 가족에서 파생되므로, 재평가 후에도 동일한 연결은 식별자를 유지합니다. 보류, 거부, 그리고 확인 상태는 조정 후에도 유지되므로, 엔진이 다시 실행되더라도 거부된 스레드는 다시 표시되지 않습니다.
하늘 레이아웃도 미리 계산되고 결정적입니다. 지리적 위치가 노드를 생성하고, 관련 위치가 서로 끌어당겨지고, 작은 무작위 변동으로 정확한 중복이 방지됩니다. 라이브 인터페이스는 하나의 전환 값으로 구체와 같은 지리에서 완성된 별자리로 애니메이션할 수 있으며, 모든 프레임에서 배터리를 소모하는 물리 시뮬레이션을 실행하지 않습니다.
매치컷 시네마는 Vision의 주의 집중 기술을 사용하여 각 예시의 중요한 부분 주변에 카메라 움직임을 부드럽게 배치합니다. 문이 다른 문으로 서서히 전환되므로 이미지 중앙을 단순히 정렬하지 않습니다. Reduce Motion은 드리프트하는 움직임을 제거하고 전환 시간을 단축합니다. 주의 집중 기술이 사용할 수 없는 경우, 화면 중앙 크롭이 우아한 대체 방법입니다.
왜 지금 벤치마크 스위트를 개발해야 할까요?
대규모 라이브러리 성능이 한계에 도달하여 직관만으로는 충분하지 않았습니다. 변경 사항은 한 화면의 속도를 높일 수 있지만, 가져오기, 추억 또는 별자리의 속도를 늦출 수 있습니다. 이는 모두 동일한 지리 및 사진 파이프라인에 의존하기 때문입니다.
새 세트에는 두 가지 방법이 있습니다.
- 로직 레인은 개발 중에 사용 가능한 가장 큰 실제 보고서에 따라 82,000 사진을 포함하여 소규모, 중간 규모 및 스트레스 테스트 환경에서 기능 엔진을 엄격하게 테스트합니다.
- UI 레이아웃은 대표적인 화면을 표시하며, Mapsake 자체의 성능 측정 도구는 작업 시간, 오류 및 메모리 사용량을 기록합니다.
벤치마크는 릴리스 최적화를 사용하며, 테스트 기능이 활성화되어 있습니다. 디버그 빌드는 최적화되지 않은 Swift가 배포된 앱과 관련 없는 숫자를 생성하므로, 의도적으로 제외됩니다. 시뮬레이터와 실제 장치 결과는 서로 다른 하드웨어를 동일한 환경으로 비교하지 않도록 별도의 기준선을 유지합니다.
이 기능 모음에는 지도, 지도 데이터, 가져오기, 사진 메타데이터, 업적, Passport, 친구, 백업, 스탬프, Constellations, 추억, 사진 탐색기가 포함됩니다. 실시간 네트워크, 카메라 품질, 시스템 사진 열거, 그리고 CloudKit은 통합 테스트로 남아 있습니다. 이러한 입력이 결정론적이라고 가정하면 결과가 부정확해질 수 있기 때문입니다.
벤치마크는 잘못될 수 있습니다.
이 애플리케이션 스위트를 개발하는 데에는 스톱워치로 앱 코드를 측정하는 것보다 더 많은 시간이 필요했습니다. 초기 테스트 환경에서는 좌표를 선택하기 위해 일반적인 해시 함수가 사용되었지만, Swift는 프로세스 간에 해당 해시를 의도적으로 무작위화하여 실행마다 기하학적 작업이 약 30% 정도 변경됩니다. 현재 테스트 환경에서는 고정 생성기를 사용하며, 스위트는 결과를 수락하기 전에 생성된 모양을 검증합니다.
이전에는 import.merge라는 시나리오에서 새 데이터 추가를 측정했습니다. 이는 기존 지도에 안전하게 변경 사항을 적용하기 위한 것이었습니다. 벤치마크는 빠르고 반복 가능했지만, 테스트하는 내용이 잘못되었습니다. 이 문제를 수정하면서 기본값이 변경되었습니다.
UI 측정에는 유사한 함정이 있었습니다. 성능 카운터는 시작 시부터 누적되므로, 탭 제스처는 시작 애니메이션의 지연을 상속받아 실제보다 느려 보일 수 있습니다. 이제 각 상호 작용은 제스처 전 스냅샷을 플러시하고, 해당 시나리오 자체의 컨텍스트 내에서만 작업을 수행합니다.
실행 환경, 운영 체제, 하드웨어 구성, 빌드 버전 및 온도 상태를 기록합니다. 시뮬레이션 결과는 장치 기준보다 우선시되지 않습니다. 비정상적인 온도 조건에서의 실행은 여전히 유용한 진단 정보를 제공하지만, 회귀 테스트 실패로 간주되지 않고 대신 주석이 추가됩니다. 회귀 테스트는 상대적인 임계값과 작은 절대값 임계값 모두를 충족해야 합니다. 이를 통해 서브밀리초 단위의 노이즈가 잘못된 오류로 감지되는 것을 방지합니다.
이러한 세부 사항은 벤치마크 주변의 관료적인 절차가 아닙니다. 이것들은 숫자가 가치를 지니도록 만드는 요소입니다.
정확성 검사 기능에서 실제 지도 오류가 발견되었습니다.
첫 번째 성능 테스트에서 가장 중요한 테스트는 속도를 측정하는 것이 아니었습니다. 최적화된 사진에서 장소로의 파생을 경계선이 많은 좌표에서 의도적으로 단순화된 참조와 비교했습니다.
이 보호 기능은 엔진이 최적화되기 전에 실패했습니다. 겹치는 행정 구역 내의 사진(베를린이 브란덴부르크 내, 서울이 경기도 내, 키예프 시가 주변 지역 내)은 딕셔너리의 임의 반복 순서에 따라 할당될 수 있습니다. 동일한 좌표가 시작될 때마다 다른 결과를 낼 수 있습니다.
참조 엔진과 프로덕션 엔진은 모두 겹치는 후보를 다각형 면적순으로 정렬하여 가장 구체적인 행정 지형지물이 결정론적으로 선택되게 합니다. 82,000장의 테스트용 사진에서 차이가 전혀 없고 웜 경로와 콜드 경로의 결과가 일치한 뒤에야 공간 처리 단축 방식을 채택했습니다.
동등성 검사를 통한 성능 엔지니어링은 일반적인 타이밍 작업으로는 발견할 수 없는 정확성 문제를 찾아낼 수 있다는 장점이 있습니다.
최초의 측정 단위 변경 사항.
초기 스트레스 테스트에서 여러 가지 공유된 병목 현상이 드러났습니다. 첫 번째 최적화 단계에서는 인덱싱된 지오메트리 충돌 감지, 지속적인 지리적 셀 캐시, 메모이제이션된 위치 해결, 공유된 사진 스냅샷, 그리고 점진적인 아틀라스 주석 업데이트가 추가되었습니다.
시뮬레이터에서, 82,000장의 사진 지도를 생성하는 데 걸리는 시간이 34.5 초에서 8.0 초.. 필터 변경 또는 '장소' 열기 후 일반적인 경로는 이전과 동일합니다. 2.8 초. 10,000 사진 티어에서 컨스텔레이션 계획 기능이 저하되었습니다. 3.3 초에서 0.9 초. 탭 사이클 응답 시간이 31% 감소하고, Passport 페이지어 응답 시간이 47% 감소했습니다.
다음 단계에서는 반복적인 SQLite 위도 대역 스캔을 지연된 위도 정렬된 가장 가까운 도시 인덱스와 경계가 있는 레코드 캐시로 대체했습니다. 시뮬레이터 벤치마크에서 중간 크기의 가장 가까운 도시 일괄 처리가 감소했습니다. 2.11 초에서 5.2 밀리초. 물리적인 iPhone에서 동일한 공유 엔진 기능이 저하되었습니다. 3.06 초에서 6.35 밀리초, 은 스트레스 수준에 따른 별자리 계획이 감소했습니다. 5.60 초에서 65.9 밀리초.
두 번째 단계에서 82,000 사진의 콜드 파생 시간이 7.96초에서 약 ~초로 단축되었습니다. 1.00 초 시뮬레이터에서는 984 밀리초의 초기 실행 시간이 있습니다. 가장 가까운 도시 검색 기능이 다른 기능(인포, Then & Now, 지도 생성, Constellations) 아래에 위치하여 단일 화면에 속하지 않기 때문에 성능 향상이 발생했습니다.
이는 제어된 벤치마크 작업이며, 모든 장치 또는 라이브러리가 동일한 결과를 생성한다는 약속이 아닙니다. 그 가치는 비교 가능성에 있습니다. 즉, 고정된 구성, 기록된 열 상태, 확정된 결과 및 의미 있는 회귀를 식별할 수 있는 메커니즘이 있다는 것입니다.
작업의 재사용성이 향상되어 더 빨라졌습니다.
가장 큰 개선은 기능 제거나 로딩 스피너 추가가 아니라, 반복적인 작업을 중단함으로써 이루어졌습니다.
- 지역 지리 정보는 비용이 많이 드는 포인트 테스트 전에 후보 다각형을 좁힙니다.
- 빌드 키로 식별되는 지리적 셀 캐시는 해결된 영역을 여러 실행 간에 기억합니다.
- 가장 가까운 도시 검색은 각 좌표에 대해 데이터베이스 정렬을 다시 수행하는 대신 숫자 공간 인덱스를 사용합니다.
- 사진 기반 인터페이스는 항상 동일한, 변경 불가능한, 필터링된 스냅샷을 제공합니다.
- 아틀라스 핀과 플래그는 식별자를 기준으로 업데이트되며, 모든 것을 삭제하고 다시 만드는 방식이 아닙니다.
Photo Explorer와 Constellations는 모두 이러한 동일한 기반 위에 구축되어 이점을 얻습니다. 가져오기, Then & Now, 데이터 맵, 그리고 장소 이야기도 마찬가지입니다.
벤치마크 코드는 App Store 아카이브에서 제외되지만, 해당 코드는 저장소에 남아 있습니다. 핫 패스에 대한 변경 사항이 있을 때마다 이 테스트 스위트를 실행하고, 올바른 기본값과 비교하고, 결과를 유지하십시오. 이제 성능은 프로젝트가 추측하는 것이 아니라 테스트할 수 있는 항목입니다.
이러한 숫자는 아직 완료되지 않은 작업도 유지합니다. 물리적 장치 UI의 후속 단계에서는 심각한 열 상태가 발생했으며 여전히 큰 탭 사이클 메모리 피크와 Constellations를 실제 라이브러리에 대해 열 때 약 1초의 지연이 발생했습니다. 이러한 측정값은 진단용이며 깨끗한 회귀 비교가 아닙니다. 그러나 앱이
이 세 가지 프로젝트에 공통적으로 적용되는 사항.
Photo Explorer, Constellations, 그리고 벤치마크 스위트는 모두 동일한 제약 조건에서 시작되었습니다. 대규모 여행 라이브러리가 장치를 떠나지 않고도 앱의 다른 부분이 느려지지 않도록 더욱 유용해야 합니다.
Photo Explorer는 알려진 메타데이터를 질문과 컬렉션으로 변환합니다. Constellations는 대표적인 이미지 신호를 시각적인 스토리로 변환합니다. 벤치마크 스위트는 이 모든 기능을 공유하는 기본 엔진에 맞게 조정합니다.
이 기능의 작업은 검색 결과, 별이 빛나는 하늘, 그리고 매치 컷에서 확인할 수 있습니다. 엔지니어링 작업은 주로 발생하지 않는 것에 의해 확인할 수 있습니다. 시작은 모든 82,000 사진의 다운로드를 기다리지 않고, 필터는 동일한 배열의 5개의 복사본을 다시 만들지 않고, 빠른 공간 인덱스는 사진이 속하는 도시를 조용히 변경하지 않습니다.
이것이 Mapsake에서 성능 작업을 진행하고 싶은 방향입니다. 속도는 야심찬 아이디어가 떠오른 후 정리 단계가 아닙니다. 이는 해당 아이디어를 안전하게 유지하는 데 사용되는 도구 중 하나입니다.