Aggiornamento di ingegneria.
Photo Explorer, Constellations e un Mapsake più veloce.
Due funzionalità fotografiche ambiziose hanno sollevato la stessa domanda: Mapsake poteva fare molto più lavoro senza diventare più lento? Una nuova suite di benchmark per simulatore e dispositivo ha trasformato la risposta in un lavoro di ingegneria misurabile.
Una versione di nuove funzionalità e una versione di ingegneria.
Questo aggiornamento introduce due delle esperienze fotografiche più ambiziose di Mapsake: Esplora foto, che rende ricercabile un'ampia libreria di mappe, e Costellazioni, che scopre fili visivi tra luoghi distanti.
Include anche la funzionalità meno visibile del rilascio: una suite di benchmark delle prestazioni permanente. Questa suite ha immediatamente trovato i percorsi condivisi più lenti, ha reso le correzioni misurabili e ha fornito all'app un modo per rilevare quando i lavori futuri li rendono più lenti.
Il risultato offre più della semplice funzionalità. Mapsake è significativamente più veloce per convertire vaste librerie di foto in luoghi, per trovare città vicine e per pianificare una costellazione.
Photo Explorer cerca nel registro dei viaggi, non nella galleria fotografica.
Photo Explorer inizia con i metadati compatti che Mapsake gestisce già per le foto cartografate. Questi includono la posizione, la data, la fonte, la fotocamera, le note, l'altitudine, la velocità, i preferiti, gli screenshot, le modifiche e l'organizzazione aggiunta all'interno dell'app.
L'indice rimane sul dispositivo. Una ricerca può essere diretta (Giappone, 2024, iPhone, preferiti) o formulata in modo più naturale, come "foto preferite dall'Italia dell'anno scorso". Lo strato di query converte il linguaggio supportato in un insieme strutturato di filtri, mentre il vocabolario deterministico e la correzione degli errori forniscono un fallback affidabile.
La ricerca è solo un modo per accedere alla libreria. Le raccolte mostrano gruppi utili senza dover digitare; l'area della mappa limita i risultati geograficamente; la sequenza temporale li raggruppa per data; le ricerche salvate e recenti facilitano la ripetizione delle domande. I preferiti, le valutazioni, i tag, le etichette e le note si trovano in un componente locale in modo che l'organizzazione di una foto non alteri o carichi l'originale.
La scelta architettonica importante è che ogni strumento condivide la stessa istantanea indicizzata. Le raccolte, la cronologia, la mappa e la ricerca di testo non ricostruiscono ogni volta un mondo di foto 82,000 da zero.
L'indice è derivato, mentre l'organizzazione personale è duratura.
Photo Explorer aveva bisogno di due tipi di archiviazione con durate di vita molto diverse. I campi di ricerca come i nomi dei luoghi, l'anno di acquisizione, la fotocamera, l'altitudine e la fonte possono essere ricostruiti a partire dai metadati esistenti di Mapsake. Un preferito, una nota privata, una valutazione, un'etichetta o un colore sono stati scritti da una persona e non possono essere trattati come dati di cache temporanei.
Mapsake conserva l'organizzazione creata dall'utente in un piccolo file secondario, idoneo al backup. L'indice di ricerca più grande si trova nella cache, non contiene byte di immagine, è escluso dal backup e può essere rigenerato ogni volta che il suo schema cambia. La scansione di una libreria o l'eliminazione dei dati derivati non cancella il lavoro che qualcuno ha dedicato all'organizzazione.
Questa divisione ha anche reso i backup più onesti. I backup senza perdita di dati in formato JSON e HTML possono contenere note e organizzazione, ma non si trasformano silenziosamente in archivi di foto. Le annotazioni di Apple Photos conservano un identificativo iCloud stabile in modo che un backup ripristinato possa riconnettere la copia locale a un altro dispositivo Apple; gli identificativi delle risorse Immich sono già stabili per loro natura.
L'ambiente di test completo ha prodotto un indice compresso di circa 12.4 MB per 82,000 foto. Una compilazione geografica completa ha richiesto 2.61 secondi sul simulatore di sviluppo, un ripristino successivo dal disco ha richiesto 1.20 secondi, la generazione di raccolte ha richiesto 126 millisecondi e il modello di timeline giornaliero ha richiesto 211 millisecondi. Questi numeri hanno assegnato un budget specifico a ogni parte della funzionalità piuttosto che nascondere tutto dietro una misurazione generica di "ricerca".
Photo Explorer spiega anche perché un elemento è corrispondente. Un risultato può indicare che ha corrisposto a Kyoto, 2024, una fotocamera iPhone, una nota privata o un filtro selezionato. Questa piccola informazione è importante quando una query combina il linguaggio naturale con diversi controlli esatti: l'utente non deve mai indovinare cosa il motore di ricerca intendeva.
Il linguaggio di ricerca è un'interfaccia, non una licenza per improvvisare.
Ogni query supportata diventa in definitiva una struttura di filtro validata. Il percorso diretto riconosce luoghi, date, fonti, modelli di fotocamera, note, preferiti, valutazioni, tag, altitudine, velocità, schermate e foto modificate. Un correttore ortografico limitato può correggere le parole di intento e il vocabolario indicizzato noto, ma non riscrive note private arbitrarie.
Sui dispositivi che supportano i modelli di base on-device di Apple, il testo inviato può essere interpretato anche nella stessa struttura limitata. Solo la query e l'anno corrente vengono forniti a questo modello di sistema. I pixel della foto, gli indici dei metadati, le note sulla posizione e l'organizzazione personale non vengono mai forniti. Gli intervalli non validi e i valori sconosciuti vengono rifiutati e l'analizzatore deterministico rimane la soluzione di riserva.
L'interfaccia mostra l'interpretazione e offre un modo per tornare alle parole originali. Questo è un luogo in cui l'ingegnosità è utile solo quando rimane verificabile. "Foto a 3,000 metri dell'anno scorso" dovrebbero sembrare conversazionali, ma dovrebbero comunque comportarsi come un insieme preciso di filtri.
Constellations cerca ripetizioni a distanza.
"Then & Now" chiede se qualcuno è tornato nello stesso posto. "Constellations" pone quasi la domanda opposta: quali idee visive ha ripetuto in luoghi lontani?
L'indice locale estrae un insieme compatto di segnali visivi e motivi dalle foto di viaggio idonee. Il pianificatore cerca caratteristiche che siano distintive di un'immagine piuttosto che semplicemente comuni ovunque, quindi collega i candidati da destinazioni diverse. Porte, coste, skyline, forme di montagne, colori, stagioni e composizione possono diventare il vocabolario di un thread.
Questi thread sono organizzati in un cielo tridimensionale. L'utente può navigare al suo interno, aprire una costellazione, mantenere o scartare una connessione e riprodurre un filmato di taglio in cui le foto correlate si dissolvono da un luogo all'altro. Le schede di condivisione e il reel utilizzano gli stessi dati di thread salvati.
L'estrazione e la pianificazione avvengono sul dispositivo. Mapsake non invia una libreria di viaggi a un servizio di analisi delle immagini. I processi in background possono approfondire l'indice nel tempo senza che il primo avvio debba attendere che l'intera libreria venga caricata.
L'indice visivo è stato progettato per essere rielaborato a basso costo.
Per ogni voce idonea, Mapsake esegue una piccola decodifica dell'immagine e deriva diversi segnali: un'impronta di funzionalità Vision, etichette di classificazione grezze, una tavolozza di colori compatta e una classe di luce stimata in base alla posizione, all'ora e all'altitudine solare. L'impronta delle funzionalità è una descrizione numerica utilizzata per la somiglianza; non è una copia dell'immagine e non può essere visualizzata come tale.
L'indice memorizza identificatori di classificatori grezzi anziché sostituirli immediatamente con motivi orientati al prodotto. Questa scelta ha dato i suoi frutti durante i test con librerie reali. La prima lista di motivi includeva etichette che sembravano ragionevoli, ma che in realtà non erano presenti nella tassonomia supportata da Vision. Poiché le etichette grezze erano ancora disponibili, la ricostruzione di "Torri e ponti", "Barche e porti" e di gruppi di motivi successivi è stata una valutazione rapida piuttosto che un'altra scansione di migliaia di elementi originali.
L'indicizzazione inizia con foto rappresentative anziché leggere strettamente la libreria dalla più recente alla più vecchia. Le foto sono raggruppate in celle di posizione approssimative e giorni di posizione, con preferenza per immagini statiche utili e spaziatura tra le sequenze. Il pianificatore quindi attraversa i luoghi in cicli. Questo fornisce una copertura geografica ampia nelle prime fasi, mentre i processi in background aggiungono gradualmente profondità.
La prima versione sceglieva una foto per luogo in ogni round. I dati reali dei dispositivi hanno rivelato il difetto: la maggior parte dei luoghi rimaneva al di sotto del minimo di tre foto utilizzato dal motore dei thread, quindi migliaia di risorse indicizzate potevano comunque non produrre candidati. La suddivisione di ogni round in tre rappresentanti ha reso l'indice utile prima senza aumentare il suo budget totale. Questo è esattamente il motivo per cui sia gli ambienti di test sintetici che una libreria reale e disordinata sono importanti.
L'estrattore funziona in batch sequenziali, esegue le modifiche in modo atomico, mette in pausa in caso di stress termico e salta l'estrazione in background in modalità a basso consumo. Le miniature di Apple Foto che si trovano già sul dispositivo vengono provate per prime; le immagini disponibili solo su iCloud possono attendere un passaggio successivo con connessione di rete. Immich utilizza la stessa pipeline visiva del suo client di miniature esistente.
La somiglianza da sola non racconta una storia.
Una distanza di funzionalità può trovare due fotografie visivamente simili, ma Constellations è progettato per trovare una connessione tra i luoghi piuttosto che un rilevatore di duplicati. Le foto candidate devono appartenere a destinazioni situate a una distanza di almeno 150 chilometri. Il motore considera anche motivi distintivi, luce insolita, stagione e rituali di calendario ricorrenti prima di ammettere una connessione.
“Distintivo” è diventata la parte difficile. Un vecchio modello di valutazione premiava i segnali presenti in entrambi i luoghi. Nella libreria di sviluppo, questo ha generato centinaia di connessioni dominate dalla notte e dalle stagioni comuni. Questi segnali erano tecnicamente condivisi, ma non affatto sorprendenti. Il motore ora valuta la rilevanza: un segnale è importante quando è insolitamente forte in entrambi i luoghi rispetto alla libreria della persona nel suo complesso.
Questo ha cambiato la domanda da "Entrambi i luoghi contengono foto notturne?" a "Entrambi i luoghi hanno una quantità insolitamente alta di foto notturne per questa libreria?". I segnali comuni scompaiono sullo sfondo, mentre le riprese ripetute durante la "blue hour", le viste delle porte, i porti, la luce invernale o una settimana festiva ricorrente possono diventare significative.
I candidati visivi usano più rappresentanti per ogni luogo anziché affidarsi a un’unica coppia fortunata. Gli identificatori dei thread derivano dai luoghi e dalla famiglia, quindi la stessa connessione conserva la propria identità dopo un nuovo calcolo del punteggio. Gli stati conservato, ignorato e visto sopravvivono così alle regolazioni, e un thread ignorato non riappare solo perché il motore è stato eseguito di nuovo.
La disposizione del cielo è anch'essa precalcolata e deterministica. Le posizioni geografiche definiscono i nodi, la forza della connessione attrae i luoghi connessi l'uno verso l'altro, e un piccolo jitter casuale evita le sovrapposizioni esatte. L'interfaccia in diretta può animare tra una geografia simile a un globo e la costellazione finale con un singolo valore di transizione; non esegue una simulazione fisica che consuma batteria ad ogni fotogramma.
Il montaggio utilizza l'attenzione di saliency di Vision per posizionare il movimento fluido della telecamera attorno alla parte importante di ogni esempio. Una porta si dissolve in un'altra porta invece di allineare ciecamente due centri di immagine. "Riduci il movimento" rimuove il movimento di deriva e accorcia la transizione, mentre un ritaglio centrale è il metodo di fallback elegante quando la saliency non è disponibile.
Perché creare una suite di benchmark ora?
Le prestazioni di una libreria di grandi dimensioni avevano raggiunto un punto in cui l'intuizione non era più sufficiente. Una modifica potrebbe rendere uno schermo più veloce, rallentando al contempo, silenziosamente, le importazioni, i ricordi o le costellazioni, poiché tutti dipendono dagli stessi processi geografici e fotografici.
La nuova suite ha due percorsi:
- Un motore di logica esegue test di funzionalità deterministiche su set di dati piccoli, medi e di stress, incluso un livello di foto 82,000 basato sul rapporto del mondo reale più grande disponibile durante lo sviluppo.
- Un componente dell'interfaccia utente mostra schermate rappresentative mentre la strumentazione delle prestazioni di Mapsake registra i tempi di esecuzione, i problemi e la memoria.
I benchmark utilizzano l'ottimizzazione della versione di rilascio con la possibilità di testare abilitata. Le build di debug sono intenzionalmente escluse perché Swift non ottimizzato produce numeri che non sono rilevanti per l'app pubblicata. I risultati del simulatore e del dispositivo fisico mantengono anche linee di base separate in modo che l'hardware diverso non venga confrontato come se fosse lo stesso ambiente.
La suite copre il gazetteer, la geometria della mappa, le importazioni, i metadati delle foto, i risultati, Passport, Amici, backup, timbri, costellazioni, ricordi e Photo Explorer. Le reti in diretta, la qualità della fotocamera, l'enumerazione del sistema di foto e CloudKit rimangono test di integrazione perché fingere che questi input siano deterministici renderebbe i risultati meno onesti.
Un benchmark può essere facilmente sbagliato
La creazione della suite ha richiesto più impegno di quanto semplicemente integrare un cronometro nel codice dell'app. L'ambiente di test iniziale utilizzava una funzione hash semplice per selezionare le coordinate; Swift randomizza deliberatamente questo hash tra i processi, modificando la geometria di circa 30 percento da un'esecuzione all'altra. Gli ambienti di test utilizzano ora un generatore fisso, e la suite convalida la forma generata prima di accettare un risultato.
Uno scenario iniziale chiamato import.merge misurava le nuove inserzioni. Il percorso di produzione che doveva rappresentare era una fusione idempotente in un atlante esistente. Il benchmark era veloce e ripetibile, ma stava testando la cosa sbagliata. La correzione della configurazione ha modificato la linea di base prima di qualsiasi tentativo di ottimizzazione.
Le misurazioni dell'interfaccia utente presentavano una trappola simile. I contatori delle prestazioni venivano accumulati dall'avvio, quindi un gesto di scheda poteva ereditare rallentamenti dall'animazione di avvio e sembrare più lento di quanto non fosse. Ora, ogni interazione cancella la sua istantanea precedente e quindi elabora solo il lavoro all'interno del contesto di tale scenario.
L'ambiente di esecuzione registra il sistema operativo, il livello hardware, la versione, lo stato termico e lo stato termico. Il risultato di una simulazione non viene mai privilegiato rispetto a una linea di base del dispositivo. Le esecuzioni termiche non nominali rimangono utili diagnostiche, ma sono annotate invece di causare un fallimento della regressione. Una regressione deve superare sia una soglia relativa che un piccolo valore assoluto in modo che il rumore di pochi millisecondi non diventi un'emergenza falsa.
Questi dettagli non fanno parte della burocrazia relativa al benchmark. Sono ciò che rende questo numero significativo.
I controlli di correttezza hanno rilevato un bug reale nella mappa
Il test più utile nella prima fase delle prestazioni non misurava la velocità. Ha confrontato la derivazione di foto in luoghi ottimizzata con una riferimento semplice e congelata su coordinate ricche di confini.
Questa protezione è fallita prima che l'ottimizzazione avesse anche modificato il motore. Le foto all'interno di poligoni amministrativi sovrapposti (Berlino all'interno della Brandeburgo, Seoul all'interno della Gyeonggi e Kyiv all'interno della sua regione circostante) potrebbero essere assegnate in base all'ordine di iterazione casuale di un dizionario. La stessa coordinata potrebbe essere risolta in modo diverso dopo un avvio.
Sia il motore di riferimento che quello di produzione ordinano ora i candidati sovrapposti in base all'area del poligono, consentendo alla caratteristica amministrativa più specifica di vincere in modo deterministico. Solo dopo che le foto di riferimento 82,000 non hanno prodotto differenze, con percorsi caldi e freddi concordi, le scorciatoie spaziali sono diventate accettabili.
Questo è il vantaggio silenzioso dell'ingegneria delle prestazioni con le verifiche di equivalenza: può scoprire un problema di correttezza che un normale lavoro di temporizzazione non vedrebbe mai.
Cosa è cambiato nelle prime misurazioni.
Il test di stress iniziale ha rivelato diversi colli di bottiglia condivisi. La prima ottimizzazione ha aggiunto la rilevazione di geometria indicizzata, una cache geografica persistente, la risoluzione di luoghi memorizzata, snapshot condivisi di foto e aggiornamenti incrementali delle annotazioni di Atlas.
Sul simulatore, la creazione iniziale di una mappa foto 82,000 è stata ridotta di 34.5 secondi a 8.0 secondi. Un'azione comune dopo una modifica del filtro o all'apertura di "Luoghi" è 2.8 secondi. La pianificazione delle costellazioni al livello fotografico di 10,000 è fallita. 3.3 secondi a 0.9 secondi. Il tempo di cambio della scheda è diminuito del 31 percento e gli errori del paginatore di Passport sono diminuiti del 47 percento.
Il passaggio successivo ha sostituito le ripetute scansioni di bande di latitudine SQLite con un indice di città più vicina pigro e ordinato per latitudine e una cache di record limitata. Nella simulazione del benchmark, un batch di città più vicina di dimensioni medie è passato da 2.11 secondi a 5.2 millisecondi. Su un iPhone fisico, lo stesso motore condiviso è fallito. 3.06 secondi a 6.35 millisecondi, mentre la pianificazione delle costellazioni con livelli di stress è diminuita di 5.60 secondi a 65.9 millisecondi.
Questa seconda iterazione ha migliorato anche la derivazione delle foto 82,000 da 7.96 secondi a circa 1.00 secondi. sul simulatore, con un avvio a caldo di 984 millisecondi. I miglioramenti sono stati ottenuti perché la ricerca della città più vicina si trova sotto gli import, Then & Now, la derivazione della mappa e le costellazioni piuttosto che appartenere a un singolo schermo.
Si tratta di carichi di lavoro di benchmark controllati, non di una promessa che ogni dispositivo o libreria produrrà lo stesso numero. Il loro valore risiede nella comparabilità: configurazioni fisse, stato termico registrato, risultati definitivi e meccanismi in grado di rilevare una regressione significativa.
Più veloce perché il lavoro è diventato più riutilizzabile.
I miglioramenti più significativi non sono derivati dalla rimozione di funzionalità o dall'aggiunta di un indicatore di caricamento. Sono derivati dall'interruzione del lavoro ripetuto:
- La geometria della regione restringe ora i poligoni candidati prima di eseguire test di punti costosi.
- Una cache geografica di celle, legata alla build, ricorda le aree risolte attraverso le esecuzioni.
- La ricerca della città più vicina utilizza un indice spaziale numerico invece di ricostruire un ordinamento del database per ogni coordinata.
- Le interfacce basate su foto condividono un'istantanea filtrata e immutabile.
- I perni e le bandiere dell'atlante vengono aggiornati in base all'identificativo anziché essere rimossi e ricreati.
Photo Explorer e Constellations beneficiano entrambi di questa stessa base. Questo vale anche per le importazioni, Then & Now, le mappe dei dati e le storie dei luoghi.
Il codice di riferimento è escluso dagli archivi dell'App Store, ma la pratica rimane nel repository: esegui la suite attorno alle modifiche a un percorso critico, confrontala con la baseline corretta e mantieni il risultato. Le prestazioni sono ora qualcosa che il progetto può testare, non solo qualcosa che può sperare di notare.
I numeri preservano anche il lavoro incompleto. Un'implementazione successiva dell'interfaccia utente per i dispositivi fisici ha raggiunto uno stato termico critico e ha comunque registrato un picco di memoria significativo durante il cambio di scheda e quasi un secondo di ritardo all'apertura di Constellations rispetto alla libreria reale. Queste letture sono diagnostiche piuttosto che un confronto di regressione pulito, ma mantenerle visibili è più utile che dichiarare che l'app è "completata".
Cosa hanno in comune questi tre progetti.
Photo Explorer, Constellations e la suite di test sono iniziati tutti con lo stesso vincolo: una vasta libreria di foto doveva diventare più utile senza lasciare il dispositivo o rendere il resto dell'app più pesante.
Photo Explorer trasforma i metadati noti in domande e raccolte. Constellations trasforma i segnali di immagine rappresentativi in una storia visiva. La suite di test garantisce che entrambi funzionino con gli stessi motori sottostanti.
La funzionalità è visibile in un risultato di ricerca, un cielo stellato e un effetto di transizione. Il lavoro di ingegneria è principalmente visibile in ciò che non accade: un caricamento non attende che vengano caricate tutte le foto di 82,000, un filtro non ricrea cinque copie dello stesso array e un indice spaziale rapido non modifica silenziosamente la città a cui appartiene una foto.
Questa è la direzione che voglio dare al lavoro di ottimizzazione in Mapsake. La velocità non è una fase di pulizia dopo idee ambiziose. È uno degli strumenti che rendono queste idee sicure da mantenere.