2012-05-28 20 views
6

Ich programmiere eine Wohnung & Haus Vermietung Website. Da es nie mehr als 10.000 Mietobjekte gibt, ist es kein Problem, sie alle in den Speicher zu laden. Wenn ein Benutzer nun nach einem bestimmten suchen möchte, kann er sehr viele Filter für Preis, Zimmer, Rolltreppe usw. definieren.V8-ähnliche Hashtable für C#?

Jede Eigenschaft hat einen ganz anderen Satz von Attributen. Eine Eigenschaft kann ein Attribut haben, das eine andere Eigenschaft nicht hat. Also, eine Klasse in C# zu erstellen, die alle Attribute hat, während nur ein paar von ihnen verwendet werden, ist keine gute Idee für mich. Ich entschied mich stattdessen für ein Wörterbuch.

Ein paar Benchmarks später, fand ich heraus, dass das Wörterbuch etwa 40 mal langsamer Zugriff auf Attribute als eine Klasse ist. Ich habe auch einen Benchmark für node.js gemacht, der gerade Objekte als Dictionarys verwendet hat. Das war absolut interessant, weil das exakt gleiche Programm in node.js sogar besser lief als das C# -Beispiel mit einer nativen Klasse.

In der Tat habe ich die folgenden Ergebnisse:

C# Wörterbuch: ~ 820ms C# Klasse: ~ 26ms Node.js Objekt: ~ 24ms

Jede Benchmark gesucht 1'000'000 Objekte durch die gleiche Kriterien.

Ich weiß, dass die Node.js-Version ist so schnell wegen der V8-Engine von Google. Weißt du, ob es eine C# -Klasse gibt, die ähnliche Techniken wie die V8-Engine verwendet und fast die gleiche Leistung erzielt?

C# Wörterbuch Benchmark

namespace Test { 
    class Program { 
     static void Main(string[] args) { 

      PropertyList p = new PropertyList(); 
      long startTime = DateTime.Now.Ticks; 
      for (int i = 0; i < 100; i++) { 
       p.Search(); 
      } 
      Console.WriteLine((DateTime.Now.Ticks - startTime)/10000); 
     } 
    } 

    class PropertyList { 
     List<Property> properties = new List<Property>(); 
     public PropertyList() { 
      for (int i = 0; i < 10000; i++) { 
       Property p = new Property(); 
       p["Strasse"] = "Oberdorfstrasse"; 
       p["StrassenNr"] = 6; 
       p["Plz"] = 6277; 
       p["Ort"] = "Lieli"; 
       p["Preis"] = 600; 
       p["Fläche"] = 70; 
       p["Zimmer"] = 2; 
       p["Lift"] = true; 
       p["Verfügbarkeit"] = 7; 
       p["Keller"] = false; 
       p["Neubau"] = true; 
       p["ÖV"] = false; 

       properties.Add(p); 
      } 
     } 
     public void Search() { 
      int found = 0; 

      for (int i = 0; i < properties.Count; i++) { 
       Property p = properties[i]; 
       if ((string)p["Strasse"] == "Oberdorfstrasse" && 
        (int)p["StrassenNr"] == 6 && 
        (int)p["Plz"] == 6277 && 
        (string)p["Ort"] == "Lieli" && 
        (int)p["Preis"] >= 500 && (int)p["Preis"] <= 1000 && 
        (int)p["Fläche"] >= 10 && (int)p["Fläche"] <= 200 && 
        (int)p["Zimmer"] == 2 && 
        (bool)p["Lift"] == true && 
        (int)p["Verfügbarkeit"] >= 2 && (int)p["Verfügbarkeit"] <= 8 && 
        (bool)p["Keller"] == false && 
        (bool)p["Neubau"] == true && 
        (bool)p["ÖV"] == true 
       ) { 
        found++; 
       } 
      } 
     } 
    } 

    class Property { 
     private Dictionary<string, object> values = new Dictionary<string, object>(); 

     public object this[string key] { 
      get { 
       return values[key]; 
      } 
      set { 
       values[key] = value; 
      } 
     } 
    } 
} 

C# Klasse Benchmark

namespace Test { 
    class Program { 
     static void Main(string[] args) { 

      SpecificPropertyList p2 = new SpecificPropertyList(); 

      long startTime2 = DateTime.Now.Ticks; 
      for (int i = 0; i < 100; i++) { 
       p2.Search(); 
      } 

      Console.WriteLine((DateTime.Now.Ticks - startTime2)/10000); 

     } 
    } 

    class SpecificPropertyList { 
     List<SpecificProperty> properties = new List<SpecificProperty>(); 
     public SpecificPropertyList() { 
      for (int i = 0; i < 10000; i++) { 
       SpecificProperty p = new SpecificProperty(); 
       p.Strasse = "Oberdorfstrasse"; 
       p.StrassenNr = 6; 
       p.Plz = 6277; 
       p.Ort = "Lieli"; 
       p.Preis = 600; 
       p.Fläche = 70; 
       p.Zimmer = 2; 
       p.Lift = true; 
       p.Verfügbarkeit = 7; 
       p.Keller = false; 
       p.Neubau = true; 
       p.ÖV = false; 

       properties.Add(p); 
      } 
     } 
     public void Search() { 
      int found = 0; 

      for (int i = 0; i < properties.Count; i++) { 
       SpecificProperty p = properties[i]; 
       if (p.Strasse == "Oberdorfstrasse" && 
        p.StrassenNr == 6 && 
        p.Plz == 6277 && 
        p.Ort == "Lieli" && 
        p.Preis >= 500 && p.Preis <= 1000 && 
        p.Fläche >= 10 && p.Fläche <= 200 && 
        p.Zimmer == 2 && 
        p.Lift == true && 
        p.Verfügbarkeit >= 2 && p.Verfügbarkeit <= 8 && 
        p.Keller == false && 
        p.Neubau == true && 
        p.ÖV == true 
       ) { 
        found++; 
       } 
      } 
     } 
    } 

    class SpecificProperty { 
     public string Strasse; 
     public int StrassenNr; 
     public int Plz; 
     public string Ort; 
     public int Preis; 
     public int Fläche; 
     public int Zimmer; 
     public bool Lift; 
     public int Verfügbarkeit; 
     public bool Keller; 
     public bool Neubau; 
     public bool ÖV; 
    } 
} 

Node.js Benchmark

var properties = []; 

for(var i = 0; i < 10000; i++){ 
    var p = { 
     Strasse:"Oberdorfstrasse", 
     StrassenNr:6, 
     Plz:6277, 
     Ort:"Lieli", 
     Preis:600, 
     Fläche:70, 
     Zimmer:2, 
     Lift:true, 
     Verfügbarkeit:7, 
     Keller:false, 
     Neubau:true, 
     ÖV:false 
    }; 
    properties.push(p); 
} 



function search(){ 
    var found = 0; 
    for(var i = 0; i < properties.length; i++){ 
     var p = properties[i]; 
     if(p.Strasse == "Oberdorfstrasse" && p.StrassenNr == 6 && p.Plz == 6277 && p.Ort == "Lieli" && 
      p.Preis >= 500 && p.Preis <= 1000 && 
      p.Fläche>= 10 && p.Fläche <= 100 && 
      p.Zimmer == 2 && 
      p.Verfügbarkeit >= 2 && p.Verfügbarkeit <= 8 && 
      p.Keller == false && p.Neubau == true && p.ÖV == false 
     ){ 
      found++; 
     } 
    } 
} 
var startTime = new Date().getTime(); 
for(var i = 0; i < 100; i++){ 
    search(); 
} 
console.log(new Date().getTime()-startTime); 
+0

war dein C# -Test im "Release" -Modus? – Adrian

+1

Es wäre interessant, sowohl Ihren C# - als auch JavaScript-Code zu sehen. –

+0

Es ist wahrscheinlich, dass Ihr Code fehlerhaft ist, weil das Ergebnis sehr unwahrscheinlich ist. Bitte zeigen Sie es uns. – usr

Antwort

4

Ok, der Grund dafür, dass C# langsamer ist, ist, dass V8 für genau dieses Szenario optimiert ist (viele Wörterbücher haben genau die gleichen Mitglieder).

Sie missbrauchen C# hier. Verwenden Sie anstelle eines Wörterbuchs eine normale Klasse mit Autoeigenschaften. C# wird dann viel schneller sein, sogar schneller als V8 (weil Sie zu seiner Stärke spielen und nicht zu seiner Schwäche).

Und deshalb ist Ihr "specific object" Benchmark der schnellste.

+0

Sie haben wahrscheinlich Recht, aber immer noch sind die node.js Objekte dynamisch, während die C# Einsen nicht sind. Ich kann wirklich keine Klasse für jede mögliche Eigenschaft erstellen, die ein Benutzer hinzufügen möchte. Also müsste ich eine Klasse verwenden, die alle Attribute hat, die ein Benutzer definieren kann. Ich denke, das würde zu Speicherproblemen führen ... Ich interessiere mich nicht für den Leistungsunterschied zwischen diesen beiden Werten, aber da die node.js viel flexibler ist, brauche ich eine Alternative in C#. –

+0

Wie viele Eigenschaften gibt es? Weniger als 100? Definieren Sie für jede eine Eigenschaft. Weniger als 1000? Weisen Sie jedem einen Index zu und speichern Sie die Eigenschaftswerte in einem Objekt [] (jede Eigenschaft hat einen festen Index). – usr

+0

Außerdem sind Zeichenfolgenschlüssel aufgrund von Hashwerten wesentlich teurer als ganzzahlige Schlüssel. Können Sie Integer-Schlüssel verwenden? – usr