2016-01-19 4 views
5

Kurz gesagt: ist es schnell/billig? Ist es sinnvoll, einen Wert aus NSUserDefaults im Speicher für einen schnelleren Zugriff zu speichern?Wird der Zugriff auf NSUserDefaults auf iOS als billig angesehen?

Länger: sagen, ich habe erhebliche Anzahl von Werten gespeichert und von NSUserDefaults gelesen werden; mit der Notwendigkeit, auf diese Werte häufig zuzugreifen (zu lesen).

Im folgenden Ausschnitt initialisiere ich eine private gespeicherte Eigenschaft und lasse sie mit dem entsprechenden NSUserDefaults-Wert synchronisieren - also wenn ich sie lesen muss, lese ich die Eigenschaft.

Wenn das Lesen von den Standards direkt in der Tat schnell ist, würde ich das Privateigentum offensichtlich entfernen. Aber ich bin mir nicht sicher. Ist es schnell?

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() 
    } 
} 

Klarstellung für künftige Leser: die Frage wird über lesen, nicht schreiben/Synchronisierung, die (wie in den Antworten darauf) nicht schnell noch billig.

.synchronize() wird im Setter aus einem gültigen Grund aufgerufen - in meinem speziellen Fall ist es wichtig, dass es sofort synchronisiert wird, also opfere ich Leistung für die logische Integrität. In den meisten Fällen sollten Sie überlegen, ob Sie sie anrufen müssen oder ob das System eine angemessene Zeit für das Schreiben auswählen soll.

..In der Tat, jetzt, dass ich es sehe, ich sehe die gespeicherte Eigenschaft zu halten, wie es im Schnipsel ist, wird Logikintegrität bieten (solange Zugriff von anderen Orten geschieht über den Getter, und nicht direkt aus userDefaults). So kann ich auch synchronizing hier vermeiden.

+3

Zugriff ist billig, Synchronisierung kann summieren, wenn Sie es schnell tun –

Antwort

5

Lesen ist billig. Es gibt eine großzügige Zwischenspeicherung und alles passiert im RAM. Mutieren ist relativ billig, aber das System muss den Inhalt immer noch in nichtflüchtigem Speicher (eine .plist-Datei auf dem Flash) in regelmäßigen Abständen speichern.

Explizite Synchronisierung ist nicht billig. Es isst Zeit und mehr Energie.

Also für liest es ist in Ordnung, aber mit einer Menge Schreibvorgänge würde ich es immer noch in einem separaten Container und serialisieren nur nach Bedarf.

+1

Deshalb sollte 'synchronize' Methode nicht jedes einzelne Schreiben an die' NSUserDefaults' aufgerufen werden, es sei denn, einige Ausnahmefälle. Das Betriebssystem wird diese Schreibvorgänge für Sie auf der Festplatte behandeln. – GoRoS

+0

Ja, fast nie müssen Sie 'synchronize()' manuell aufrufen. –

+1

@JonShier ich selbst bin in eine sehr seltsame Situationen gerannt, die durch nicht synchronisieren verursacht wurde (es war iOS 6 glaube ich). Ich habe viel Zeit verbracht, bevor ich die Ursache herausgefunden habe - dumm, ich weiß, aber immer noch. Seither bin ich defensiv und schreibe Standardwerte. – user1244109

2

Es ist unwahrscheinlich, dass dies zu erheblichen Leistungseinbußen führt. Sie können sich jedoch selbst anhand von Instrumenten profilieren, um sicherzustellen, dass die Auswirkungen auf die Leistung vernachlässigbar sind.

1

Ich habe einige Leistungstests mit Instrumenten gemacht, wie @mipadi das vergangene Jahr vorgeschlagen hat, und meine Schlussfolgerung war, dass es keinen wesentlichen Unterschied gibt.

Wie ich in einem Kommentar oben erwähnt habe, ist es sehr wichtig zu erkennen, welche dieser NSUserDefaults schreibt, die wir sofort gemacht werden wollen. Verwenden Sie einfach in diesen speziellen Fällen synchronize Methode, sonst lassen Sie iOS, um diese Arbeit zu bearbeiten, um eine bessere Leistung zu erzielen.

+0

Es kann nicht zu spürbaren Leistungseinbußen kommen, da das System Schreibvorgänge effektiv zwischenspeichert und zusammenführt, aber dennoch kann eine normale E/A-Aktivität mehr Energie verbrauchen als keine E/A. – Mirek

+0

@Mirek am Ende müssen Sie die Verpflichtung zwischen Speicher oder I/O wählen, weil jeder seine positiven und negativen hat. Was passiert, wenn wir diese Informationen zwischenspeichern, ohne sie auf der Festplatte zu speichern, und die App plötzlich vom Benutzer getötet wird? Die Info wäre verloren. Wenn wir andererseits einen separaten Container verwenden und ihn serverseitig serialisieren, hätte er nur viel mehr Daten und wäre fast identisch mit dem zusammengewachsenen Schreiben des Betriebssystems. – GoRoS

0

Es ist alles in Ordnung, wenn Sie NSUserDefaults als Datenbank verwenden. synchronize() schreibt die komplette plist-Datei. Wenn Sie also Megabytes an Daten speichern und dann viel synchronisieren, leidet die Leistung und/oder die Akkulaufzeit.

Aber prüfen diese Frage, wie gut: How often are NSUserDefaults synchronised?

Ein interessantes Detail ist, dass wird der Benutzer standardmäßig geschrieben werden, wenn die Anwendung beendet wird.Jemand könnte experimentieren, was passiert, wenn Ihr Programm direkt nach dem Ändern von NSUserdefaults abstürzt; wenn das als "Kündigung" gilt.

+0

Abstürze zählen nicht als Beendigung für 'NSUserDefaults'. Das Hinzufügen von 'synchronize()' für den Fall, dass Ihre App abstürzt, ist jedoch eine schlechte Übung. Sie sollten nur sicherstellen, dass Ihre App nicht abstürzt. –

Verwandte Themen