2012-05-28 62 views
6

我正在編程一個公寓&房屋租賃網站。由於租用的房屋數量不會超過10'000個,因此將所有房屋都裝入內存並不成問題。現在,當用戶想要搜索特定的一個時,他可以爲價格,房間,自動扶梯等定義非常多的過濾器。用於C#的V8樣式散列表?

每個屬性都有一組非常不同的屬性。一個屬性可能具有另一個屬性不具有的屬性。所以,在C#中創建一個具有所有屬性的類,而僅使用其中一些屬性對我來說不是一個好主意。我決定用字典來代替。

稍後我發現一些基準測試,字典在訪問屬性方面比Class慢約40倍。我還爲node.js做了一個基準測試,它只是將對象用作dictionarys。這是非常有趣的,因爲node.js中的完全相同的程序比使用本地類的C#示例表現得更好。

其實我得到的結果如下:

C#詞典:〜820ms C#類:〜26ms Node.js的對象:〜24MS

每個基準搜索1'000'000對象由相同的標準。

我知道由於Google的V8引擎,Node.js版本非常快。你知道是否有一個C#類使用類似V8引擎的技術,並獲得幾乎相同的性能?

C#字典基準

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#類基準

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的基準

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

是你在'發佈'模式下的c#測試嗎? – Adrian

+1

看到你的C#和JavaScript代碼都會很有趣。 –

+0

由於結果不太可能,您的代碼很可能存在缺陷。請展示給我們。 – usr

回答

4

好吧,C#速度較慢的原因是V8針對這種情況進行了優化(大量字典具有完全相同的成員)。

你有點濫用C#在這裏。而不是字典,只需使用具有自動屬性的普通類即可。 C#會比V8更快,因爲它比V8更快(因爲你正在發揮自己的實力而不是它的弱點)。

這就是爲什麼你的「特定對象」基準測試是最快的。

+0

您可能是對的,但仍然是,node.js對象是動態的,而C#則不是。我真的不能爲用戶想要添加的每個可能的屬性創建一個類。所以我將不得不使用具有用戶可以定義的所有屬性的類。我想這會導致內存問題...我不關心兩個benachmarks之間的性能差異,但由於node.js更靈活,我需要在C#中的一些替代。 –

+0

有多少房產?少於100?爲每個定義一個屬性。少於1000?爲每一個索引分配一個索引並將屬性值存儲在一個對象[]中(每個屬性都有一個固定的索引)。 – usr

+0

此外,由於哈希,字符串鍵比整數鍵貴得多。你可以使用整數鍵嗎? – usr