2016-01-19 14 views
5

In breve: è veloce/economico? Ha senso memorizzare un valore da NSUserDefaults in memoria per un accesso più veloce?L'accesso a NSUserDefaults su iOS è considerato economico?

Più lungo: ad esempio, ho un numero significativo di valori da memorizzare e leggere da NSUserDefaults; con la necessità di accedere (leggere) quei valori frequentemente.

Nello snippet seguente, inizializzo una proprietà privata memorizzata e la mantengo sincronizzata con il valore NSUserDefaults corrispondente, quindi quando ho bisogno di leggerlo, leggo la proprietà.

Se la lettura dei valori predefiniti direttamente è effettivamente veloce, rimuoverei la proprietà privata, ovviamente. Ma non ne sono sicuro. È veloce?

private var _loggedIn = NSUserDefaults.standardUserDefaults().boolForKey("loggedIn") 
public var loggedIn: Bool { 
    get { 
     return _loggedIn 
    } 
    set { 
     _loggedIn = newValue 
     NSUserDefaults.standardUserDefaults().setBool(newValue, forKey: "loggedIn") 
     NSUserDefaults.standardUserDefaults().synchronize() 
    } 
} 

Precisazione per i lettori futuri: la questione è di circa leggendo, non scrivere/sincronizzazione, che è (come evidenziato nelle risposte) non veloce né economico.

.synchronize() viene chiamato nel setter per un motivo valido: nel mio caso specifico è importante averlo sincronizzato subito, quindi sacrifico le prestazioni per l'integrità logica. In generale, è necessario considerare se è necessario chiamarlo o lasciare che il sistema scelga il tempo appropriato per la scrittura.

.. Infatti, ora che lo guardo, vedo mantenere la proprietà archiviata così come è nello snippet, fornirà l'integrità logica (purché l'accesso da altri posti avvenga tramite il getter, e non direttamente da userDefaults). Quindi posso evitare anche synchronizing qui.

+3

L'accesso è economico, la sincronizzazione può essere sommata se lo si fa rapidamente –

risposta

5

Leggere è economico. C'è una memorizzazione generosa nella cache e tutto avviene nella RAM. La mutazione è relativamente economica, ma il sistema dovrà comunque memorizzare i contenuti nella memoria non volatile (un file .plist sul flash) a intervalli regolari.

La sincronizzazione esplicita non è economica. Mangia tempo e più energia.

Quindi per le letture va bene, ma con molte scritture lo farei comunque in un contenitore separato e serializzerò solo se necessario.

+1

Ecco perché il metodo 'synchronize' non dovrebbe essere chiamato ogni singola scrittura su' NSUserDefaults' a meno di casi eccezionali. Il sistema operativo gestirà tali scritture sul disco per te. – GoRoS

+0

Sì, non è quasi mai necessario chiamare 'synchronize()' manualmente. –

+1

@JonShier mi sono imbattuto in situazioni molto strane, causate dalla mancata sincronizzazione (credo che fosse iOS 6). Ho passato molto tempo prima che capissi la causa - stupido, lo so, ma ancora. Da allora sono in difesa con la scrittura in default. – user1244109

2

È improbabile che abbia un impatto significativo sulle prestazioni, ma è possibile eseguire il profilo utilizzando gli strumenti per garantire che l'impatto sulle prestazioni sia trascurabile.

1

Ho eseguito alcuni test sulle prestazioni con strumenti come @mipadi ha suggerito l'anno scorso e la mia conclusione è stata che non vi è alcuna differenza sostanziale.

Come ho sottolineato in un commento sopra, è molto importante rilevare quali di quelle NSUserDefaults scrivono che vogliamo essere fatte subito. Solo in quei casi particolari utilizzare il metodo synchronize, altrimenti lasciare iOS per gestire tale lavoro per ottenere prestazioni migliori.

+0

Potrebbe non esserci un notevole impatto sulle prestazioni poiché il sistema è efficacemente nella cache e scrive in coalescenza, ma un'attività regolare di I/O può consumare più energia di nessun I/O. – Mirek

+0

@Mirek alla fine devi scegliere l'impegno tra memoria o I/O perché ognuno ha i suoi lati positivi e negativi. Cosa succede se memorizziamo tali informazioni nella cache senza salvarle su disco e l'app viene improvvisamente uccisa dall'utente? Le informazioni sarebbero andate perse. D'altra parte, se usassimo un contenitore separato e lo serializzassimo nei valori predefiniti, avremmo solo molti più dati e sarebbe quasi lo stesso della scrittura a coalescenza del sistema operativo. – GoRoS

0

Va tutto bene a meno che non si utilizzi NSUserDefaults come database. synchronize() scriverà il file plist completo, quindi se si memorizzano megabyte di dati, e quindi si sincronizza molto, le prestazioni e/o la durata della batteria ne risentiranno.

Ma controllare questa domanda così: How often are NSUserDefaults synchronised?

Un dettaglio interessante è che le impostazioni predefinite dall'utente verranno scritti quando l'applicazione termina.Qualcuno potrebbe sperimentare cosa succede se il tuo programma si blocca subito dopo aver cambiato NSUserdefaults; se quello conta come "termine".

+0

Gli arresti non vengono conteggiati come terminazione per 'NSUserDefaults'. Tuttavia, aggiungendo 'synchronize()' nel caso in cui l'app si arresti in modo anomalo è una cattiva pratica. Devi solo assicurarti che l'app non si arresti. –