6

私はアパートと家の賃貸サイトをプログラミングしています。賃貸物件は1万物件を超えることはないので、すべてをメモリにロードしても問題ありません。これで、ユーザーが特定のフィルターを検索したいときに、価格、部屋、エスカレーターなどのフィルターを非常に多く定義できます。

すべてのプロパティには、非常に異なる属性のセットがあります。あるプロパティには、別のプロパティにはない属性がある場合があります。したがって、C#ですべての属性を持つクラスを作成し、そのうちのいくつかだけを使用することは、私には良い考えではありません。代わりに辞書を使うことにしました。

いくつかのベンチマークの後、私は、ディクショナリがクラスとして属性にアクセスするのに約40倍遅いことを発見しました。また、オブジェクトを辞書として使用するnode.jsのベンチマークも行いました。node.jsのまったく同じプログラムは、ネイティブクラスを使用したC#の例よりもパフォーマンスが優れていたため、これは非常に興味深いものでした。

実際、次の結果が得られました。

C#ディクショナリ:〜820ms C#クラス:〜26ms Node.jsオブジェクト:〜24ms

各ベンチマークは、同じ基準で1'000'000個のオブジェクトを検索しました。

GoogleのV8エンジンのおかげで、Node.jsのバージョンが非常に高速であることを私は知っています。V8エンジンと同様の技術を使用し、ほぼ同じパフォーマンスを得るC#クラスがあるかどうか知っていますか?

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);
4

1 に答える 1

4

わかりました。C#が遅い理由は、V8がまさにこのシナリオ(まったく同じメンバーを持つ多くの辞書)用に最適化されているためです。

ここでC#を誤用しています。辞書の代わりに、auto-propertiesを持つ通常のクラスを使用してください。C#は、V8よりもはるかに高速になります(弱点ではなく強みを発揮しているため)。

そして、それがあなたの「特定のオブジェクト」ベンチマークが最速である理由です。

于 2012-05-28T12:17:30.707 に答える