Avatar billede www.jakub.dk Nybegynder
07. april 2005 - 15:10 Der er 31 kommentarer og
1 løsning

Hvad er mest effektivt?

Hej alle.

Jeg har følgende spørgsmål:

Hvad er mest effektivt af disse 2:

string test = "1";
//Metode 1
int res = int.Parse(test);
if (res == 1) return true:

// Eller metode 2:
if (test.Equals("1")) return true;

Variablen test vil altid være et tal.

I må gerne komme med forslag til hvordan jeg kan teste dette.
Avatar billede arne_v Ekspert
07. april 2005 - 15:35 #1
metode 2 er jeg ret sikker på
Avatar billede arne_v Ekspert
07. april 2005 - 15:36 #2
long t1 = DateTime.Now.Ticks;
                for(int i = 0; i < REP; i++)
                {
                    // kald metode 1
                }
                long t2 = DateTime.Now.Ticks;
                long t3 = DateTime.Now.Ticks;
                for(int i = 0; i < REP; i++)
                {
                    // kalde metode 2
                }
                long t4 = DateTime.Now.Ticks;
Avatar billede www.jakub.dk Nybegynder
07. april 2005 - 15:46 #3
Ja det havde jeg også på fornemmelsen. Takker... Kom med svar.
Avatar billede www.jakub.dk Nybegynder
07. april 2005 - 15:51 #4
Der sker dog nogle mærklige ting og sager når jeg kører det et par gange.
Avatar billede arne_v Ekspert
07. april 2005 - 16:43 #5
svar

hvad ?
Avatar billede md_craig Nybegynder
07. april 2005 - 17:10 #6
Jeg ville angribe det lidt anderledes... her er lidt kode... :P
_____________________________________________________________________________________

using System;
using System.Timers;

namespace ConsoleApplication2
{
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    class Class1
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            string tmp = "1";

            DateTime CurrTime;
            TimeSpan elapsed;

            CurrTime = DateTime.Now;
            for(int i = 0; i < 1000000; i++)
            {
                Class1.meta(tmp);
            }
            elapsed = DateTime.Now.Subtract(CurrTime);
            Console.WriteLine(elapsed.TotalMilliseconds.ToString());

            CurrTime = DateTime.Now;
            for(int i = 0; i < 1000000; i++)
            {
                Class1.metb(tmp);
            }
            elapsed = DateTime.Now.Subtract(CurrTime);
            Console.WriteLine(elapsed.TotalMilliseconds.ToString());

            CurrTime = DateTime.Now;
            for(int i = 0; i < 1000000; i++)
            {
                Class1.metc(tmp);
            }
            elapsed = DateTime.Now.Subtract(CurrTime);
            Console.WriteLine(elapsed.TotalMilliseconds.ToString());

            Console.WriteLine(Class1.metc(tmp));
        }

        static bool meta(string tmp)
        {
            int res = int.Parse(tmp);
            if (res == 1) return true;
            return false;
        }

        static bool metb(string tmp)
        {
            if (tmp.Equals("1")) return true;
            return false;
        }

        static bool metc(string tmp)
        {
            if (tmp == "1") return true;
            return false;
        }
    }
}
Avatar billede md_craig Nybegynder
07. april 2005 - 17:15 #7
og her er tiderne hvis du lige ændre 1000000 til 10000000

Metode a: 2703,125 ms
Metode b: 281,25 ms
Metode c: 171,875 ms

Det viser sig faktisk at metode c er bedst...

Altså

string tmp = "1"...

Og husk på at string godt kan evalueres sådan i C# ;)
Avatar billede md_craig Nybegynder
07. april 2005 - 17:15 #8
tmp == "1"
Avatar billede arne_v Ekspert
07. april 2005 - 17:34 #9
using System;

class MainClass
{
    private const int REP = 10000000;
    public static bool meta(string tmp)
    {
        int res = int.Parse(tmp);
        if (res == 1)
            return true;
        else
            return false;
    }
    public static bool metb(string tmp)
    {
        if (tmp.Equals("1"))
            return true;
        else
            return false;
    }

    public static bool metc(string tmp)
    {
        if (tmp == "1")
            return true;
        else
            return false;
    }
   
    public static void Print(string desc, long t1, long t2)
    {
        Console.WriteLine(String.Format("{0} : {1:0.00}", desc, (t2 - t1)/10000000.0));
    }

    public static void Test(string s)
    {
        long t1 = DateTime.Now.Ticks;
        for(int i = 0; i < REP; i++)
        {
            meta(s);
        }
        long t2 = DateTime.Now.Ticks;
        Print("parse and ==", t1, t2);
        long t3 = DateTime.Now.Ticks;
        for(int i = 0; i < REP; i++)
        {
            metb(s);
        }
        long t4 = DateTime.Now.Ticks;
        Print("equals", t3, t4);
        long t5 = DateTime.Now.Ticks;
        for(int i = 0; i < REP; i++)
        {
            metc(s);
        }
        long t6 = DateTime.Now.Ticks;
        Print("==", t5, t6);
    }

    public static void Main(string[] args)
    {
        Test("1");
        Test("123456789");
        Test("1");
        Test("123456789");
    }
}
Avatar billede arne_v Ekspert
07. april 2005 - 17:34 #10
parse and == : 2,72
equals : 0,23
== : 0,19
parse and == : 3,72
equals : 0,20
== : 0,31
parse and == : 2,70
equals : 0,23
== : 0,17
parse and == : 3,73
equals : 0,20
== : 0,31
Avatar billede arne_v Ekspert
07. april 2005 - 17:35 #11
pussig forskel på "1" og "123456789"
Avatar billede arne_v Ekspert
07. april 2005 - 17:37 #12
Man kan iøvrigt kodem dem som:

    public static bool meta(string tmp)
    {
        int res = int.Parse(tmp);
        return (res == 1);
    }
    public static bool metb(string tmp)
    {
        return tmp.Equals("1");
    }

    public static bool metc(string tmp)
    {
        return (tmp == "1");
    }
   
[uden at det gør nogen forskel på hastighed]
Avatar billede arne_v Ekspert
07. april 2005 - 17:38 #13
Tallene var iøvrigt for debug - for release er de:

parse and == : 1,94
equals : 0,17
== : 0,05
parse and == : 2,92
equals : 0,14
== : 0,17
parse and == : 1,92
equals : 0,17
== : 0,05
parse and == : 2,94
equals : 0,13
== : 0,19
Avatar billede md_craig Nybegynder
07. april 2005 - 17:51 #14
arne_v >

Prøv envidere bare med 2... det sjove er at når den evaluere False er Equals hurtigere end "==" men evaluere den true er "==" hurtigere...

Rimelig spøjst ja... ?:/
Avatar billede www.jakub.dk Nybegynder
07. april 2005 - 17:54 #15
Ja det kunne være rart at vide... Så skal man nok bruge den som passer bedst ind i applikationen. Jeg regner med at i min app så evalurer den true 95% af tiden, så skal jeg vel bruge '=='.

Jeg synes a I var lige gode om det, så md_craig smid lige også et svar.
Avatar billede arne_v Ekspert
07. april 2005 - 17:58 #16
Konklusionen i den her slags tilfælde må være at det er lige meget.

Når true eller false kan gøre forskellen, så kan der også være
forskel på .NET 1.1 og .NET 2.0 eller på Intel og AMD eller en masse
andre ting.

Bare noter dig at Parse er lidt dyrere.
Avatar billede arne_v Ekspert
07. april 2005 - 17:59 #17
(og du har allerede givet mig alle pointene)
Avatar billede md_craig Nybegynder
07. april 2005 - 17:59 #18
Evaluating: (1 = 1) using Equals, time elapsed: 296,875
Evaluating: (1 = 1) using "==", time elapsed: 187,5
Evaluating: (1 = 20) using Equals, time elapsed: 250
Evaluating: (1 = 20) using "==", time elapsed: 359,375
Evaluating: (1 = 2500) using Equals, time elapsed: 250
Evaluating: (1 = 2500) using "==", time elapsed: 359,375
Evaluating: (1 = 23456) using Equals, time elapsed: 250
Evaluating: (1 = 23456) using "==", time elapsed: 359,375
Evaluating: (1 = 789022) using Equals, time elapsed: 250
Evaluating: (1 = 789022) using "==", time elapsed: 343,75
Evaluating: (20 = 1) using Equals, time elapsed: 250
Evaluating: (20 = 1) using "==", time elapsed: 343,75
Evaluating: (20 = 20) using Equals, time elapsed: 296,875
Evaluating: (20 = 20) using "==", time elapsed: 187,5
Evaluating: (20 = 2500) using Equals, time elapsed: 265,625
Evaluating: (20 = 2500) using "==", time elapsed: 359,375
Evaluating: (20 = 23456) using Equals, time elapsed: 250
Evaluating: (20 = 23456) using "==", time elapsed: 343,75
Evaluating: (20 = 789022) using Equals, time elapsed: 265,625
Evaluating: (20 = 789022) using "==", time elapsed: 343,75
Evaluating: (2500 = 1) using Equals, time elapsed: 265,625
Evaluating: (2500 = 1) using "==", time elapsed: 343,75
Evaluating: (2500 = 20) using Equals, time elapsed: 250
Evaluating: (2500 = 20) using "==", time elapsed: 343,75
Evaluating: (2500 = 2500) using Equals, time elapsed: 312,5
Evaluating: (2500 = 2500) using "==", time elapsed: 171,875
Evaluating: (2500 = 23456) using Equals, time elapsed: 250
Evaluating: (2500 = 23456) using "==", time elapsed: 359,375
Evaluating: (2500 = 789022) using Equals, time elapsed: 250
Evaluating: (2500 = 789022) using "==", time elapsed: 343,75
Evaluating: (23456 = 1) using Equals, time elapsed: 265,625
Evaluating: (23456 = 1) using "==", time elapsed: 343,75
Evaluating: (23456 = 20) using Equals, time elapsed: 265,625
Evaluating: (23456 = 20) using "==", time elapsed: 343,75
Evaluating: (23456 = 2500) using Equals, time elapsed: 250
Evaluating: (23456 = 2500) using "==", time elapsed: 359,375
Evaluating: (23456 = 23456) using Equals, time elapsed: 328,125
Evaluating: (23456 = 23456) using "==", time elapsed: 187,5
Evaluating: (23456 = 789022) using Equals, time elapsed: 250
Evaluating: (23456 = 789022) using "==", time elapsed: 359,375
Evaluating: (789022 = 1) using Equals, time elapsed: 250
Evaluating: (789022 = 1) using "==", time elapsed: 343,75
Evaluating: (789022 = 20) using Equals, time elapsed: 250
Evaluating: (789022 = 20) using "==", time elapsed: 343,75
Evaluating: (789022 = 2500) using Equals, time elapsed: 265,625
Evaluating: (789022 = 2500) using "==", time elapsed: 343,75
Evaluating: (789022 = 23456) using Equals, time elapsed: 265,625
Evaluating: (789022 = 23456) using "==", time elapsed: 359,375
Evaluating: (789022 = 789022) using Equals, time elapsed: 312,5
Evaluating: (789022 = 789022) using "==", time elapsed: 187,5
Avatar billede md_craig Nybegynder
07. april 2005 - 18:00 #19
hehe det går nok ;)
Avatar billede www.jakub.dk Nybegynder
07. april 2005 - 18:02 #20
ok takker.

Jeg var lige for hurtig på aftrækkeren.
Avatar billede md_craig Nybegynder
07. april 2005 - 18:07 #21
Det kunne have givet mig fint mening hvis der var forskel på True/False evaluering ved længere strenge end 1 og det var til falses side...

da den ene metode kunne være tvunget igennem hele strengen mens den anden kun var tvunget en del af vejen... (til første ukorekte char)...

Men det her giver som sagt ikke umiddelbart mening...
Og derfor må der som arne_v siger være lige så store chancer for at der er mange andre faktorer spiller ind...
Avatar billede arne_v Ekspert
07. april 2005 - 18:44 #22
Og docs gør det jo ikke mere logisk:

...

[C#]
public static bool operator ==(
  string a,
  string b
);

...

Remarks
This operator is implemented using the Equals method, which means the comparands are tested for a combination of reference and value equality. The comparison is case-sensitive.

...

Der står faktisk at == kalder Equals !?!?
Avatar billede runesoft Nybegynder
08. april 2005 - 09:25 #23
Jeg tror jeg kan komme med en forklaring på hvorfor == er hurtigere end Equals. Hvad I ikke har taget højde for er at string classen er immutable og derfor kan være implementeret ved at to strenge der indeholder det samme rent faktisk er samme objekt.

Det vil sige at == operatoren med høj sandsynlighed er implementeret ved først at se om de to objekter rent faktisk er samme objekt (som jeg tror den gør). Når de er ens vil der derfor ikke være nogen reel strengsammenligning. Det vil der være hvis de er forskellige.

Jeg tror at I kan komme ud over denne sammenligning af objekter, ved at oprette strengene vha. new String("bla")
Avatar billede md_craig Nybegynder
08. april 2005 - 10:17 #24
Kommentar: runesoft
08/04-2005 09:25:50

Det huer mig ikke at du faktisk har ret...
der har det sQ modeleret det underligt hvis man spørg mig, aner man ikke lægnere hvornår man har ens referencer eller ej, i og med at selv om man laver to nye strings som fx:

string a = "test";
string b = "test";

at så har de pluselig samme reference, dette burde så resultere i at hvis man ændre a, så slår det igennem for b også... men nej... så bliver der endelig alokeret en y på heapen... Tror det er sådan noget man bare ikke skal tænke over når man så programmere ellers får man dårlige nerver.. men det er naturligvis for at spare hukommelse, kunne bare forestille mig det gnaver lidt på ydelsen når man så asigner i og med den skal igennem hele heapen for at se om der skulle være en tilsvarende streng...
Avatar billede md_craig Nybegynder
08. april 2005 - 10:30 #25
Det skal så også lige noteres at en string Constructor faktisk slet ikke tar en string... så det skal implementeres ved et chararray...

så jeg kan ikke lige komme på en måde hvorpå man tester om det er hurtigst at alokere ny hukommelse eller at gennemsøge den...

I og med at hvis man skal alokere ny hokommelse på en string skal der foretages andre operationer som ville gøre sammenligningen unfair...
Avatar billede arne_v Ekspert
08. april 2005 - 10:38 #26
Der er ikke noget underligt i at de folder konstanter sammen. Det gør
de fleste andre sprog også.

string a = "test";
string b = "test";

laver et konstant objekt og lader 2 referencer pege på det samme.

Java og C++ gør helt det samme.

Og ja - det er tilsyneladende det som giver forskelllen.

Jeg kan ikke helt se logikken i at == opfører sig anderledes end Equals - og slet ikke når
dokumentationen siger at == kalder Equals, men sådan er der så meget.
Avatar billede arne_v Ekspert
08. april 2005 - 10:40 #27
Jeg verificerede bare med:

        Test("123456789".Substring(0,1));
        Test("123456789");

og det der sker udenfor det man timer er jo ligemeget.
Avatar billede runesoft Nybegynder
08. april 2005 - 13:51 #28
arne_v: at Equal og == ikke er implementeret ens er vel bare en "feature" i frameworket. Men det forklarer hvorfor ens strenge (objekter) sammenlignes hurtigere end forskellige strenge.

md_craig: At du ikke kan ændre i en streng, må du bare finde dig i. og være opmærksom på at hver gang du prøver at ændre i en streng, oprettes der nye objekter.
Avatar billede arne_v Ekspert
08. april 2005 - 14:29 #29
Jo men når de skriver i docs:
  This operator is implemented using the Equals method

Og jeg har svært ved at se pointen i det test. Fordi i virkelige programmer
må det da være meget sjældent at det er samme objekt.
Avatar billede runesoft Nybegynder
08. april 2005 - 14:56 #30
Implemented using er vel heller ikke det samme som at de er ens?

Generelt er jeg lidt bange for at overskrive "==" operatoren, fordi jeg synes det kan være med til at forvirre om hvad der rent faktisk sker...  er det indholdet der bliver sammenlignet, eller er det objekterne...  Måske er det bare fordi jeg stadig tænker Java en gang imellem ;)
Avatar billede md_craig Nybegynder
08. april 2005 - 18:58 #31
Kommentar: runesoft
08/04-2005 14:56:06

Tja... normalt vil == jo evaluere på referencer, dvs hvad der ligger i stacken, mens Equals evaluere på hvad der ligger i heapen, men hvis man holder sig til at man i c# kan evaluere de datatyper der samtidig er keywords, så går du jo ikke gal.

Normalt ville man jo mene at ValueTypes burde være dem der kunne evalueres med == mes Reference types med equals... men sådan er det ikke 100% åbenbart... desuden ved jeg heller ikke om du vil kunne evaluere Structs med == ??... Structs er jo defineret som e "custom" value type... Enums også med i lidt samme kategori...

2 ting jeg mest har styr på brugen af frem for implementeringen af..

Kommentar: arne_v
08/04-2005 10:38:55

Nu kender jeg ikke så meget til Java eller C++, er undervist i java og der fik vi i sin tid at vide at når du asigner en string sker der det samme som hvis du kaldte dens constructor, det er jo i så fald ikke helt rigtigt så?
Avatar billede arne_v Ekspert
10. april 2005 - 21:42 #32
C# supporterer jo operator overload så == kan kalde en Equals, hvis programmøren vil.

----

Java:

public void m() {
  String a = "test";
  String b = "test";
  ...
}

svarer også mere til:

private final static String TEST = "test";
public void m() {
  String a = TEST;
  String b = TEST;
  ...
}

----

mono String == tester iøvrigt tilsyneladende ikke på samme objekt:

C:\>csc /optimize+ compare2.cs
Microsoft (R) Visual C# .NET Compiler version 7.10.6001.4
for Microsoft (R) .NET Framework version 1.1.4322
Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.


C:\>compare2
parse and == : 1,95
equals : 0,19
== : 0,06
parse and == : 2,98
equals : 0,14
== : 0,20
parse and == : 1,94
equals : 0,19
== : 0,05
parse and == : 2,98
equals : 0,14
== : 0,20

C:\>mcs /optimize+ compare2.cs
Compilation succeeded

C:\>mono compare2.exe
parse and == : 0,39
equals : 0,14
== : 0,16
parse and == : 1,20
equals : 0,16
== : 0,19
parse and == : 0,38
equals : 0,14
== : 0,16
parse and == : 1,20
equals : 0,16
== : 0,16
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester