Sagen wir, dass ich ein Wörterbuch (in .NET) mit Schlüsseln von 1 bis 100 habe. Ich kenne von meinen historischen Daten, dass 99% der Zeit ich Greifen Sie auf dieses Wörterbuch zu, um die Daten für die Schlüssel 5, 37, 88 abzurufen. Gibt es eine Möglichkeit, dieses Diktat so zu organisieren, dass es sehr schnell mit diesen 3 Schlüsseln ist, sogar auf Kosten von mehr Zeitverschwendung bei der Suche nach den verbleibenden 97 Schlüssel? Oder gibt es vielleicht eine andere Datenstruktur, die dieses Wissen nutzen könnte, um die durchschnittliche Zugriffszeit auf Daten zu verbessern?Wie man eine Wörterbuchleistung mit Geschäftslogikwissen "helfe"
Antwort
In einer vernünftigen Implementierung eines Wörterbuchs werden die Kosten einer Suche von den Kosten eines Speicherzugriffs dominiert. Ihre Hardware wird dies für Sie optimieren und die am häufigsten verwendeten Elemente in den schnellsten Cache-Ebenen belassen. 100 Gegenstände passen in Ihren schnellsten Cache, es sei denn, Sie haben einen winzigen Computer.
Das heißt, wenn Sie eine Hash-Tabelle mit separaten Verkettung verwenden, können Sie diese Elemente an den Anfang ihrer Ketten verschieben. Dies stellt sicher, dass das Nachschlagen dieser Elemente O (1) Worst Case garantiert wird, während für mindestens ein Element in Ihrem Wörterbuch die Suche mit hoher Wahrscheinlichkeit O (log n/log log n) ist.
Natürlich, wenn Sie nur 100 Schlüssel haben, wird die Verwendung einer Hash-Tabelle anstelle eines Wörterbuchs sicherstellen, dass jeder Schlüssel O (1) Worst-Case-Zugriff hat.
Sie könnten einen kleinen Cache vor dem Wörterbuch verwenden, der schneller sein könnte. Wenn Sie beispielsweise wissen, dass die meisten Ihrer Zugang sind für Artikel 3, 37 und 88, dann könnten Sie haben:
private Dictionary<int, MyDataType> TheDictionary;
private KeyValuePair<int, MyDataType>[] quickLookup;
void InitializeDictionary()
{
TheDictionary = new Dictionary<int, MyDataType>();
// here, initialize the dictionary with the data.
// Now, set up the cache
quickLookup = new KeyValuePair<int, MyDataType>[]
{
new KeyValuePair(3, TheDictionary[3]),
new KeyValuePair(37, TheDictionary[37]),
new KeyValuePair(88, TheDictionary[88])
};
Nun, wenn Sie für einen Artikel suchen möchten, müssen Sie zunächst den Cache überprüfen:
bool TryDictionaryLookup(int key, out MyDataType data)
{
foreach (var kvp in quickLookup)
{
if (kvp.key == key)
{
data = kvp.Value;
return true;
}
}
// didn't find it. Check the dictionary.
return TheDictionary.TryGetValue(key, out data);
}
Dies sollten Sie boost eine kleine Leistung geben, wenn Sie den Cache nur drei Elemente ist. Wenn Sie jedoch mehr als fünf oder sechs Elemente erhalten, wird es wahrscheinlich schlechter abschneiden als das direkte Wörterbuch. Sie müssen einige Zeitpunkte festlegen, um festzustellen, wo der Sweet Spot ist.
Beachten Sie auch, dass, wenn Sie wirklich in diese Art von Mikro-Optimierung sind, haben Sie wahrscheinlich die foreach
mit einer for
Schleife ersetzen sollen:
for (int i = 0; i < quickLookup.Length)
{
if (quickLookup[i].Key == key)
...
...
Das wird den Aufwand für die Erstellung des enumerator beseitigen.
Der Grund, warum diese Technik eine Leistungssteigerung bieten sollte, ist, dass für den Zugriff auf das Wörterbuch ein Hashwert vom Schlüssel berechnet werden muss. Während dies eine schnelle Operation ist, ist es immer noch mehr Aufwand als ein paar Array-Zugriffe. Auch hier sollten Sie dies gründlich mit repräsentativen Daten testen und profilieren, bevor Sie es in Produktion nehmen.
Der C# -Compiler verwendet (zumindest verwendet; ich habe seit einer Weile nicht mehr überprüft) etwas ähnliches beim Generieren von Code für switch
Anweisungen. Wenn die switch
enthält weniger als einige Zahl Fälle (ich denke, es war sechs, das letzte Mal, wenn ich überprüft), dann generiert der Compiler eine Reihe von if/else
Aussagen. Für sechs oder mehr Elemente generiert es ein Wörterbuch mit Schlüsseln und Verzweigungsorten und Code, um den Fallwert in einem Wörterbuch nachzuschlagen und zu dem relevanten Code zu verzweigen.
- 1. Beeinflusst die Länge des Schlüssels die Wörterbuchleistung?
- 2. Bitte helfe bei der Fehlersuche auf UILabel (evict_glyph_entry_from_cache)
- 3. Wie erstellt man eine Datenquelle mit camel?
- 4. Wie man eine "Related Links" mit C#
- 5. Wie man eine byte [] Eigenschaft mit Hibernate?
- 6. Wie vergleicht man eine Zeichenkette mit EOF?
- 7. Wie schneidet man eine Tabelle mit greenDAO
- 8. wie man eine jfiddle mit Flugblatt erstellen
- 9. Wie liest man eine Datei mit javax.lang.model?
- 10. Wie man eine Website mit https
- 11. Wie erstellt man eine Anwendung mit TypeScript?
- 12. Wie man eine UNION mit Lehre macht?
- 13. Wie erstellt man eine Zertifikatskette mit keytool?
- 14. Wie man eine Eingabe mit HTML-Code
- 15. Wie man eine Datei mit Git festlegt?
- 16. Wie man eine Verbindung mit jquery
- 17. Wie aktualisiert man eine Gridview mit Ajax?
- 18. Wie man eine Verbindung mit Hibernate
- 19. Wie man eine Beschreibung mit vim kommentiert?
- 20. Wie erstellt man eine Masterseite mit HTML?
- 21. Wie aktualisiert man eine Tabelle mit jquery
- 22. Wie erstellt man eine ScrollView mit Swift?
- 23. Wie man eine Entity mit JPA abbildet?
- 24. Wie man eine Oauth Anfrage mit PHP
- 25. wie man eine sms sendet mit vs2003
- 26. Wie man eine div-Höhenänderung mit AngularJS
- 27. Wie man eine Zeichenkette mit php
- 28. Wie man eine Fremdschlüsselreferenz mit sqlalchemy erstellt
- 29. Wie man eine wsdl mit zend Seife
- 30. Wie macht man eine Transformationsskalenanimation mit jQuery?