Инженерное обновление
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 МБ для 82,000 фотографий. Полная географическая сборка занимала 2.61 секунды на эмуляторе разработки, последующая загрузка с диска занимала 1.20 секунды, создание коллекций занимало 126 миллисекунд, а модель ежедневной временной шкалы занимала 211 миллисекунд. Эти цифры позволили установить бюджет для каждой части функции, а не скрывать все за одним общим показателем "поиска".
Photo Explorer также объясняет, почему элемент соответствует запросу. Результат может указывать на соответствие Киото, 2024, камере iPhone, личной заметке или выбранному фильтру. Эта небольшая строка важна, когда запрос сочетает естественный язык с несколькими точными параметрами: пользователь никогда не должен гадать, что имел в виду поисковый движок.
Язык поиска – это интерфейс, а не разрешение на импровизацию.
Каждый поддерживаемый запрос в конечном итоге становится структурой проверенной фильтрации. Прямой путь распознает места, даты, источники, модели камер, заметки, избранное, оценки, теги, высоту, скорость, скриншоты и отредактированные фотографии. Ограниченный корректор правописания может исправлять слова, выражающие намерения, и известные слова в индексе, но он не переписывает произвольные личные заметки.
На устройствах, поддерживающих локальные модели Foundation от Apple, введенный текст также может быть интерпретирован в ту же ограниченную структуру. В эту систему передается только запрос и текущий год. Пиксели фотографий, индексы метаданных, примечания о местоположении и личная организация никогда не передаются. Недопустимые диапазоны и неизвестные значения отклоняются, а детерминированный парсер остается резервным вариантом.
Интерфейс показывает интерпретацию и предлагает способ вернуться к исходным словам. Это место, где хитрость полезна только тогда, когда ее можно проверить. «Фотографии выше 3,000 метров от прошлого года» должны звучать разговорно, но при этом должны вести себя как точный набор фильтров.
Constellations ищет повторения на больших расстояниях.
«Then & Now» определяет, вернулся ли человек в то же место. «Constellations» задает почти противоположный вопрос: какие визуальные идеи он повторял в разных местах?
Встроенный индекс извлекает компактный набор визуальных сигналов и мотивов из подходящих фотографий путешествий. Планировщик ищет особенности, которые являются отличительными для одного изображения, а не просто распространенными повсюду, и связывает кандидатов из разных мест. Двери, береговые линии, горизонты, формы гор, цвета, времена года и композиция могут стать словарем для создания цепочки.
Эти потоки организованы в трехмерное пространство. Пользователь может перемещаться в этом пространстве, открывать созвездия, сохранять или удалять связи и воспроизводить фильм с переходом, в котором связанные фотографии перетекают из одного места в другое. Карты для обмена и ленты используют одни и те же сохраненные данные потока.
Извлечение и планирование выполняются на устройстве. Mapsake не отправляет библиотеку путешествий на службу анализа изображений. Фоновые пакеты могут со временем углублять индекс, не заставляя первое открытие ждать загрузки всей библиотеки.
Визуальный индекс был разработан для быстрой перенастройки.
Для каждого подходящего пользователя Mapsake выполняет небольшую декодировку изображения и получает несколько сигналов: отпечаток Vision, необработанные метки классификатора, компактную цветовую палитру и класс освещения, оцененный по местоположению, времени и высоте солнца. Отпечаток – это небольшое числовое описание, используемое для определения сходства; это не копия изображения и не может быть отображено как таковое.
Индекс хранит необработанные идентификаторы классификаторов, а не сразу заменяет их продуктовыми мотивами. Этот выбор оказался полезным во время тестирования реальной библиотеки. В первый список мотивов были включены метки, которые звучали разумно, но фактически отсутствовали в поддерживаемой таксономии Vision. Поскольку необработанные метки все еще были доступны, восстановление таких групп мотивов, как «Башни и мосты», «Лодки и гавани», было быстрым процессом, а не повторным сканированием тысяч оригиналов.
Индексация начинается с репрезентативных фотографий, а не со строгого чтения библиотеки от новых к старым. Фотографии группируются в приблизительные области и дни, с предпочтением полезных неподвижных изображений и интервалов между сериями. Затем планировщик перемещается по местам последовательно. Это обеспечивает широту географического охвата на ранних этапах, а фоновые пакеты постепенно добавляют глубину.
В первой версии для каждого места выбиралась одна фотография за раунд. Данные с реальных устройств показали проблему: в большинстве мест было меньше трех фотографий, используемых движком потоков, поэтому тысячи проиндексированных ресурсов все равно могли не давать результатов. Разбиение каждого раунда на три представителя сделало индекс полезным быстрее, не увеличивая его общего бюджета. Это именно то, почему синтетические тесты и реальная, сложная библиотека одинаково важны.
Программа извлечения работает в последовательных пакетах, атомарно фиксирует прогресс, приостанавливается при перегреве и пропускает фоновое извлечение в режиме экономии энергии. Сначала используются миниатюры Apple Photos, которые уже находятся на устройстве; изображения, доступные только через iCloud, могут быть обработаны позже, когда будет доступно сетевое соединение. Immich использует ту же визуальную цепочку через существующий клиент миниатюр.
Сходство само по себе не создает историю.
Функция определения расстояния может найти две визуально похожие фотографии, но Constellations предназначена для поиска связи между местами, а не для обнаружения дубликатов. Кандидатские фотографии должны находиться в местах, расположенных не менее чем на 150 километра друг от друга. Система также учитывает характерные мотивы, необычное освещение, сезон и повторяющиеся календарные события, прежде чем установить связь.
«Отличительные» характеристики оказались самым сложным аспектом. Ранняя модель оценки отдавала предпочтение признакам, присутствующим в обоих местах. В библиотеке разработки это приводило к сотням связей, в основном связанных с ночным временем и обычными сезонами. Эти признаки были технически общими, но не вызывали особого удивления. Теперь движок оценивает различия: признак имеет значение, когда он необычайно силен в обоих местах по сравнению с общей библиотекой пользователя.
Это изменило вопрос с «Оба места содержат ночные фотографии?» на «Оба места необычно часто встречаются в ночное время в этой библиотеке?». Общие сигналы затухают на фоне, в то время как повторяющиеся кадры в «синий час», дверные проемы, гавани, зимний свет или повторяющиеся праздничные недели могут приобрести значение.
Визуальные кандидаты используют несколько представителей для каждого места, а не только одну «счастливую пару». Идентификаторы потоков выводятся на основе их местоположения и семьи, поэтому одна и та же связь сохраняет свою идентификацию после повторной оценки. Состояние «сохранен», «отклонен» и «просмотрен» сохраняется при настройке, и отклоненный поток не появится снова просто потому, что движок был запущен повторно.
Расположение на небе также предварительно вычисляется и является детерминированным. Географические позиции служат исходными точками, сила связей тянет связанные места друг к другу, а небольшая случайная помеха предотвращает точные совпадения. Живой интерфейс может плавно переходить между географией, похожей на глобус, и сформированной созвездием, используя одно значение перехода; он не выполняет ресурсоемкую физическую симуляцию каждый кадр.
Кинематографический режим «Match Cut» использует механизм внимания Vision для плавного перемещения камеры вокруг важной части каждого примера. Вместо простого выравнивания центров изображений, дверь растворяется в другой двери. Режим «Reduce Motion» убирает дрожание и сокращает время перехода, а центральное кадрирование остается элегантным запасным вариантом, когда информация о внимании недоступна.
Почему сейчас важно создать набор для тестирования?
Производительность при работе с большими библиотеками достигла такого уровня, что интуиции уже недостаточно. Изменение может ускорить работу одного экрана, но при этом может замедлить импорт, создание воспоминаний или работу с созвездиями, поскольку все они зависят от одних и тех же географических и фото-пайплайнов.
Новый набор тестов включает два режима:
- Логический модуль запускает детерминированные функциональные компоненты на небольших, средних и стрессовых сборках, включая уровень фотографий 82,000, основанный на самом большом отчете из реального мира, доступном во время разработки.
- Интерфейс отображает типичные экраны, в то время как собственные инструменты производительности Mapsake регистрируют время выполнения операций, ошибки и использование памяти.
Ориентиры используют оптимизацию для выпуска с включенным тестированием. Отладочные сборки намеренно исключены, потому что неоптимизированный Swift создает числа, которые не имеют отношения к выпущенному приложению. Результаты симулятора и физического устройства также имеют отдельные базовые показатели, чтобы различное оборудование не сравнивалось, как если бы оно было одной и той же средой.
Этот набор функций включает в себя справочник, геометрию карты, импорт, метаданные фотографий, достижения, Passport, Friends, резервные копии, штампы, Constellations, воспоминания и Photo Explorer. Живые сети, качество камеры, системная перечисление фотографий и CloudKit остаются интеграционными тестами, поскольку предположение о детерминированности этих входных данных сделало бы результаты менее достоверными.
Результаты бенчмарка могут быть ошибочными.
Разработка этого набора приложений потребовала больше времени, чем простое измерение кода приложения с помощью секундомера. В первой тестовой среде для выбора координат использовалась обычная функция хеширования; Swift намеренно рандомизирует эту хеш-функцию между процессами, что приводит к изменению геометрии работы примерно на 30% от одного запуска к другому. Теперь в тестовой среде используется фиксированный генератор, и набор проверяет сгенетированную форму перед принятием результата.
В одном из ранних сценариев использовалось название import.merge для измерения количества новых записей. Предназначенным путем было безопасное слияние в существующую карту. Тест был быстрым и воспроизводимым, но проверял не то. Исправление тестовых данных изменило базовый уровень до начала любых оптимизаций.
В измерениях пользовательского интерфейса была аналогичная проблема. Счетчики производительности накапливались с момента запуска, поэтому жест переключения на вкладку мог наследовать задержки от анимации запуска и казаться медленнее, чем он был. Теперь каждый жест очищает свой предварительный снимок, а затем выполняет только работу в контексте этого сценария.
Записывает среду выполнения, операционную систему, уровень оборудования, сборку и тепловое состояние. Результаты эмуляции никогда не имеют приоритет над базовыми показателями устройства. Нестандартные значения температуры по-прежнему полезны для диагностики, но они помечаются, а не приводят к сбою в процессе регрессионного тестирования. Регрессионный тест должен превышать как относительный порог, так и небольшой абсолютный предел, чтобы избежать ложных срабатываний из-за шума в наносекундах.
Эти детали – не бюрократические процедуры, связанные с эталоном. Они определяют ценность этого числа.
Система проверки точности обнаружила ошибку в карте.
Наиболее важный тест в первом проходе производительности не измерял скорость. Он сравнивал оптимизированное преобразование фотографий в местоположение с намеренно упрощенной эталонной версией с большим количеством границ.
Эта защита не сработала до того, как оптимизация изменила движок. Фотографии, находящиеся внутри перекрывающихся административных полигонов (Берлин внутри Бранденбурга, Сеул внутри провинции Кёнгидо и Киев внутри окружающей области), могли быть назначены в соответствии со случайным порядком итерации словаря. Одно и то же местоположение могло быть разрешено по-разному после запуска.
И эталонный, и рабочий движок теперь сортируют перекрывающиеся кандидаты по площади полигона, благодаря чему наиболее конкретный административный объект выбирается детерминированно. Пространственные оптимизации стали допустимы только после того, как 82,000 тестовых фотографий дали нулевое число расхождений, а результаты прогретого и холодного путей совпали.
Это скрытое преимущество инженерной оптимизации с проверками на эквивалентность: оно может выявить проблему корректности, которую обычная проверка времени не обнаружит.
Какие изменения произошли с первоначальными единицами измерения.
Первоначальный стресс-тест выявил несколько общих узких мест. Первый этап оптимизации добавил индексированное тестирование пересечений геометрии, постоянный кэш географических ячеек, мемоизированное разрешение местоположения, снимки общих фотографий и инкрементные обновления аннотаций Atlas.
В симуляторе время определения местоположения на карте для фотографии 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 получают выгоду от того, что построены на одних и тех же фундаментальных технологиях. Это также относится к импорту, функциям «Тогда и сейчас», картам данных и историям о местах.
Код для тестирования производительности исключен из архивов App Store, но он остается в репозитории: выполняйте этот набор тестов при каждом изменении критически важных участков кода, сравнивайте результаты с базовыми значениями и сохраняйте результаты. Теперь производительность – это то, что проект может тестировать, а не просто надеяться заметить.
Эти числа также сохраняют информацию о незавершенной работе. На более позднем этапе, при тестировании пользовательского интерфейса на реальном устройстве, были обнаружены серьезные проблемы с перегревом, а также большой пик использования памяти при переключении между вкладками и почти секунда задержки при открытии Constellations в реальной библиотеке. Эти данные являются диагностическими, а не результатом чистого сравнения производительности, но их отображение более полезно, чем объявление приложения «готовым».
Что объединяет эти три проекта.
Photo Explorer, Constellations и набор тестов начинались с одного и того же ограничения: большая библиотека путешествий должна стать более полезной, не покидая устройство и не замедляя работу остальной части приложения.
Photo Explorer преобразует известные метаданные в вопросы и коллекции. Constellations преобразует репрезентативные сигналы изображений в визуальную историю. Набор тестов обеспечивает соответствие обоим компонентам общим базовым механизмам.
Работа над этой функцией видна в результате поиска, звездном небе и сквозном переходе. Инженерная работа видна в основном в том, чего не происходит: запуск не ждет загрузки всех фотографий 82,000, фильтр не создает пять копий одного и того же массива, а быстрая пространственная индексация не меняет тихо, к какому городу относится фотография.
Это направление, в котором я хочу, чтобы работа по повышению производительности развивалась в Mapsake. Скорость – это не этап очистки после амбициозных идей. Это один из инструментов, который делает эти идеи безопасными для сохранения.