Frage

Vor kurzem hatte ich in einem Datensatz gespeichert einige sehr Verarbeitung schwere Sachen mit Daten zu tun. Es war schwer genug, dass ich mit einem Werkzeug am Ende, einige Engpässe in meinem Code zu identifizieren. Als ich die Engpässe analysierte, stellte ich fest, dass, obwohl DataSet Lookups nicht schrecklich langsam waren (sie sind nicht der Engpass waren), war es langsamer als ich erwartet hatte. Ich habe immer angenommen, dass Datasets eine Art von HashTable Stil Implementierung verwendet, die Lookups O (1) (oder zumindest das ist, was ich denke, HashTables sind) machen würde. Die Geschwindigkeit meines Lookups schien, als dies deutlich langsamer zu sein.

Ich habe mich gefragt, ob jemand, der etwas über die Implementierung von .NET DataSet Klasse weiß kümmern würde zu teilen, was sie wissen.

Wenn ich etwas tun, wie folgt aus:

DataTable dt = new DataTable();
if(dt.Columns.Contains("SomeColumn"))
{
    object o = dt.Rows[0]["SomeColumn"];
}

Wie würden schnell die Lookup-Zeit für die Contains(...) Methode sein, und der Wert für die Beschaffung in Object o zu speichern? Ich hätte gedacht, es sehr schnell sein wie ein HashTable (unter der Annahme, was ich über HashTables verstehen ist richtig), aber es scheint nicht, wie es ...

Ich schrieb, dass Code aus dem Speicher, so dass manche Dinge nicht „syntaktisch korrekt“.

War es hilfreich?

Lösung

Reflector die Schritte für DataRow [ "Spaltenname"] sind:

  1. Holen Sie sich das Datacolumn von Spaltennamen. Verwendet die Zeile des Datacolumncollection [ „Spaltenname“]. Intern speichert Datacolumncollection seine Datacolumns in einem Hastable. O (1)
  2. Holen Sie sich das Zeilenindex des DataRow. Der Index wird in einem internen Elemente gespeichert. O (1)
  3. Holen Sie den Wert des Datacolumn auf den Index mit Datacolumn [index]. Datacolumn speichert seine Daten in einem System.Data.Common.DataStorage (intern, abstract) Mitglied:

    Rückkehr dataColumnInstance._storage.Get (Record);

    Eine Probe konkrete Implementierung ist System.Data.Common.StringStorage (intern, versiegelt). StringStorage (und die anderen konkreten DataStorages ich geprüft) speichern ihre Werte in einem Array. Holen (Record) einfach schnappt sich das Objekt im Wert Array an der Record. O (1)

Also insgesamt sind Sie O (1), aber das nicht das Hashing und Funktionsaufruf bedeutet während der Betrieb ohne Kosten. Es bedeutet nur, es nicht mehr als die Anzahl der DataRows oder Datacolumns erhöht kostet.

Interessant, dass Datastorage ein Array für Werte verwendet. Kann mir nicht vorstellen, das ist einfach neu zu erstellen, wenn Sie Zeilen hinzufügen oder entfernen.

Andere Tipps

Eigentlich ist es ratsam, integer zu verwenden, wenn Referenzierung Spalte, die eine Menge in Bezug auf die Leistung verbessern können. Um die Dinge überschaubar, könnten Sie Integer-Konstante deklarieren. Anstatt also von dem, was Sie getan haben, könnten Sie tun

const int SomeTable_SomeColumn = 0;

DataTable dt = new DataTable();
if(dt.Columns.Contains(SomeTable_SomeColumn))
{
    object o = dt.Rows[0][SomeTable_SomeColumn];
}

Ich stelle mir vor, dass alle Lookups O (n) wäre, so glaube ich nicht, dass sie jede Art von Hash-Tabelle verwenden würde, aber eigentlich eher ein Array verwenden würde für Zeilen und Spalten zu finden.

Eigentlich glaube ich, die Spaltennamen in einem Hashtable gespeichert sind. Sollte O (1) oder konstanter Nachschlag für Groß- und Lookups. Wenn es durch jeden suchen hat, dann wäre es natürlich sein O (n).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top