Laden...

Performance: == Oder Equals()

Erstellt von tkrasinger vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.510 Views
T
tkrasinger Themenstarter:in
574 Beiträge seit 2008
vor 15 Jahren
Performance: == Oder Equals()

Hab wieder mal ein paar ganz einfache Tests gemacht (Release Mode):

using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            TestClass test = new TestClass();
            test.Run();
            Console.Read();
        }
        public class TestClass
        {
            protected List<string> _lst = new List<string>();
            public void Run()
            {

                for (int i = 0; i < 1000000; i++)
                {
                    _lst.Add("Item:" + i.ToString());
                }

                FindItem_ByContains("Item:33");
                FindItem_ByForeach("Item:33");
                FindItem_ByForeachWithEquals("Item:33");
                Console.WriteLine("");
                FindItem_ByContains("Item:3333");
                FindItem_ByForeach("Item:3333");
                FindItem_ByForeachWithEquals("Item:3333");
                Console.WriteLine("");
                FindItem_ByContains("Item:33333333");
                FindItem_ByForeach("Item:33333333");
                FindItem_ByForeachWithEquals("Item:33333333");
                Console.WriteLine("");
                FindItem_ByContains("Item:888888");
                FindItem_ByForeach("Item:888888");
                FindItem_ByForeachWithEquals("Item:888888");
                Console.WriteLine("");
                FindItem_ByContains("Item:2");
                FindItem_ByForeach("Item:2");
                FindItem_ByForeachWithEquals("Item:2");
                Console.WriteLine("");
                FindItem_ByContains("x");
                FindItem_ByForeach("x");
                FindItem_ByForeachWithEquals("x");
            }

            public bool FindItem_ByContains(string item)
            {
                Stopwatch sw = new Stopwatch();
                sw.Start();
                bool found = _lst.Contains(item);
                sw.Stop();
                Console.WriteLine("FindItem_ByContains: " + item + " " + found + " in " + sw.ElapsedMilliseconds + "ms (" + sw.ElapsedTicks + ")");
                return found;
            }
            public bool FindItem_ByForeach(string item)
            {
                Stopwatch sw = new Stopwatch();
                sw.Start();
                bool found = false;
                foreach (string x in _lst)
                {
                    if (x == item)
                    {
                        found = true;
                        break;
                    }
                }
                sw.Stop();
                Console.WriteLine("FindItem_ByForeach: " + item + " " + found + " in " + sw.ElapsedMilliseconds + "ms (" + sw.ElapsedTicks + ")");
                return found;
            }

            public bool FindItem_ByForeachWithEquals(string item)
            {
                Stopwatch sw = new Stopwatch();
                sw.Start();
                bool found = false;
                foreach (string x in _lst)
                {
                    if (item.Equals(x))
                    {
                        found = true;
                        break;
                    }
                }
                sw.Stop();
                Console.WriteLine("FindItem_ByForeachWithEquals: " + item + " " + found + " in " + sw.ElapsedMilliseconds + "ms (" + sw.ElapsedTicks + ")");
                return found;
            }
        }
    }
}

Dabei sind mir ein paar interessante Sachen aufgefallen die bei mir einige Fragen aufgetan haben:

Das das ForEach mit dem == langsamer ist als der Rest war zu erwarten, was mich erstaunt ist, dass das ForEach mit dem Equals() teilweise (nicht immer!) schneller ist als das Contains.
Weiß wer, wie das Contains intern implementiert ist?

Gibt es diesbezüglich Richtlinien oder Empfehlungen was in Fällen dieser Art zu verwenden ist? Kann man sagen Equals() ist generell besser als == ?

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo tkrasinger,

Weiß wer, wie das Contains intern implementiert ist?

ja, der Reflector!

Gibt es diesbezüglich Richtlinien oder Empfehlungen was in Fällen dieser Art zu verwenden ist? Kann man sagen Equals() ist generell besser als == ?

Ja, es gibt Empfehlungen, aber die haben nichts mit der Performance zu tun. Tendenziell ist Equals besser, weil operator== eine statische Methode ohne dynamische Bindung ist. Es wird also anhand des statischen Typs entschieden, welche Methode verwendet wird. Aber natürlich sollte immer die zu dem tatsächlichen Objekttyp (dynamischer Typ) passende Methode verwendet werden. Das ist bei Equals der Fall. Das Problem bei Equals ist, dass es nicht verwendet werden kann, wenn der linke Operand null ist.

Zu Equals und dem Verhältnis von Equals zu Operator== siehe: MSDN: Object.Equals-Methode (Object).

herbivore

S
248 Beiträge seit 2008
vor 15 Jahren

Hallo tkrasinger,

Guidelines for Implementing Equals and the Equality Operator ==

könnte dir weiterhelfen.

Spo

3.971 Beiträge seit 2006
vor 15 Jahren

Hallo

  1. Wenn du in einer (großen) Liste ein Element suchst, ist es besser du verwendest ein Dictionary. Hast du eine Liste, die sich nicht mehr nach dem initalisieren verändert, kannst du die Liste alternativ auch sortieren und anschließend mit BinarySearch schnell ein Element suchen.

  2. Geschwindigkeitsmessungen führt man nicht über einen einzelnen Aufruf der entsprechenden Funktion aus, sondern über viele Aufrufe, um das Ergebnis so genau wie möglich zu erhalten.

  3. Es ist wichtig, wie == und object.Equals(obj) implementiert ist. Sind beide nicht implementiert, rufen beide intern object.ReferenceEquals(obj1, obj2) auf, was quasi nur den Objektzeiger vergleicht. (Wichtig, nur bei Verweistypen, Werttypen verhalten sich anders.). Der Vergleich des Objektzeigers ist wohl die performanteste.

In den meisten Fällen ruft == die Equals-Methode auf. Die Equals-Methode hat aber den Nachteil, das sie virtual ist, und somit die CLR erstmal prüfen muss, welche eigtl. Funktion aus welcher Klasse sie aufrufen muss, was wiederum Performance kostet. Deshalb wäre eine statische Equals(obj1, obj2) in zeitkritischen Anwendungen besser.

Beachte bitte auch die Nachteile von ==, beispielsweise == bei Interfaces

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...