Laden...

Performance bei bedingten Zuweisungen an bool Variablen

Erstellt von T-Man vor 18 Jahren Letzter Beitrag vor 18 Jahren 4.922 Views
T
T-Man Themenstarter:in
210 Beiträge seit 2006
vor 18 Jahren
Performance bei bedingten Zuweisungen an bool Variablen

Hallo Leute,

ich würde gerne wissen, welcher der beiden folgenden Code-Blöcke perfomanter ist:

bool b;
if (<condition>) b = true;
bool b;
b = <condition>;

Kann mir das jemand so sagen, oder kann mir jemand sagen, wie man das herausfindet? Ich vermute ja, daß Variante 1 perfomanter ist...

Gruß,
T-Man

3.003 Beiträge seit 2006
vor 18 Jahren

Zuerst einmal machen beide Anweisungen NICHT dasselbe. In Fall 1 kann b bei <condition> == false uninitialisiert bleiben, was in Fall zwei nicht passiert.

Um aus Fall 1 einen gleichwertigen zu machen, wird der Code zu:


bool b;
b = <condition>?true:false;

In beiden Fällen wird <condition> vor der Zuweisung ausgewertet. Ich gehe davon aus, dass der Compiler aus Fall 2 etwas nach dem obigen Schema macht, beides also gleich performant ist.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

T
T-Man Themenstarter:in
210 Beiträge seit 2006
vor 18 Jahren

Wird b denn nicht automatisch mit false initialisiert?
Wenn nicht, muß die deklaration von

bool b;

in

bool b = false;

geändert werden.

3.003 Beiträge seit 2006
vor 18 Jahren

Wenn du b bei der Deklaration initialisieren musst, bist du für <condition> == true unperformanter, da du zwei Zuweisungen hast. Ich habe oben das extra so formuliert, dass man sieht, wie ähnlich sich die beiden Ausdrücke sind, wenn man mit if...else arbeitet.

laTino
PS: soweit ich weiss, macht C# nichts anderes als andere Programmiersprachen: bei der Deklaration einer Variablen wird der benötigte Speicherplatz anhand des Variablentyps bestimmt und reserviert, jedoch noch nicht vergeben. Woher sollte der Compiler auch wissen, ob eine nicht initialisierte Variable true oder false ist, bzw. welchen Wert er im Fall einer fehlenden Initialisierung zuweisen soll...

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

T
T-Man Themenstarter:in
210 Beiträge seit 2006
vor 18 Jahren

Ich habe den Code sehr gekürzt. Eigentlich sieht es in etwa folgendermaßen aus:

bool add = false;
switch(<switch-condition>)
{
  case a: add = <condition a>; break;
  case b: add = <condition b>; break;
  case c: add = <condition c>; break;
  ...
  ...
}
if (add) ...;

Die Alternative ist:

bool add = false;
switch(<switch-condition>)
{
  case a: if (<condition a>) add = true; break;
  case b: if (<condition b>) add = true; break;
  case c: if (<condition c>) add = true; break;
  ...
  ...
}
if (add) ...;

Bei Variante 1 gibt es in jedem Fall eine Zuweisung. Die Wert ist aber zur Compilezeit noch unklar. Bei Variante 2 gibt es nicht immer eine Zuweisung und wenn, dann ist der Wert schon zur Compilezeit klar.

X
40 Beiträge seit 2005
vor 18 Jahren

Woher sollte der Compiler auch wissen, ob eine nicht initialisierte Variable true oder false ist, bzw. welchen Wert er im Fall einer fehlenden Initialisierung zuweisen soll...

Z.B. aus der C-Sharp Language Specification 😉

10.4.4 Field initialization
The initial value of a field, whether it be a static field or an instance field, is the default value (§5.2) of the
field’s type. It is not possible to observe the value of a field before this default initialization has occurred, and a
field is thus never “uninitialized”. The example

  
using System;  
class Test  
{  
    static bool b;  
    int i;  
    static void Main() {  
         Test t = new Test();   
         Console.WriteLine("b = {0}, i = {1}", b, t.i);  
    }  
}  
  

produces the output
b = False, i = 0
because b and i are both automatically initialized to default values.

T
T-Man Themenstarter:in
210 Beiträge seit 2006
vor 18 Jahren

@x86fanboy:

Gilt das denn auch für lokale Variablen in Methoden? Die werden schließlich auf dem Stack und nicht im Heap erzeugt...

Gruß,
T-Man

S
8.746 Beiträge seit 2005
vor 18 Jahren

Der generiert Assemblercode (if-else vs. ?) ist leicht unterschiedlich, dürfte aber praktisch gleich schnell sein. Reine Geschmackssache.

static void Main(string[] args)
{
00000000 push ebp
00000001 mov ebp,esp
00000003 push edi
00000004 push esi
00000005 push ebx
00000006 sub esp,44h
00000009 xor eax,eax
0000000b mov dword ptr [ebp-48h],eax
0000000e mov dword ptr [ebp-10h],eax
00000011 xor eax,eax
00000013 mov dword ptr [ebp-1Ch],eax
00000016 mov dword ptr [ebp-3Ch],ecx
00000019 cmp dword ptr ds:[008C886Ch],0
00000020 je 00000027
00000022 call 769D1146
00000027 xor edi,edi
00000029 xor esi,esi
0000002b xor ebx,ebx
0000002d nop
bool a = true;
0000002e mov edi,1

        bool b;  

        if (a) b= true;  

00000033 test edi,edi
00000035 sete al
00000038 movzx eax,al
0000003b mov ebx,eax
0000003d test ebx,ebx
0000003f jne 00000049
00000041 mov esi,1
00000046 nop
00000047 jmp 0000004B
else
b = false;
00000049 xor esi,esi

        bool c;  
        b = (a)?true:false;  

0000004b test edi,edi
0000004d jne 00000057
0000004f nop
00000050 xor edx,edx
00000052 mov dword ptr [ebp-50h],edx
00000055 jmp 0000005E
00000057 mov dword ptr [ebp-50h],1
0000005e movzx eax,byte ptr [ebp-50h]
00000062 mov esi,eax

}

X
40 Beiträge seit 2005
vor 18 Jahren

Original von T-Man
@x86fanboy:

Gilt das denn auch für lokale Variablen in Methoden?

Nein.

T
T-Man Themenstarter:in
210 Beiträge seit 2006
vor 18 Jahren

Da es keine automatische Initialisierung gibt muß also in jedem fall eine Zuweisung erfolgen.

Es bieten sich somit die folgenden beiden Varianten:

bool add;
switch (...)
{
  case a: add = <contition a>; break;
  case b: add = <contition b>; break;
  ...
  default: add = false; break;
}
if (add) ...;
bool add = false;
switch (...)
{
  case a: if (<contition a>) add = true; break;
  case b: if (<contition b>) add = true; break;
  ...
}
if (add) ...;

In Variante 1 hat man auf jeden Fall genau eine Zuweisung. Der Wert, der zugewiesen wird, ist nicht zur Compilezeit klar.
In Variante 2 hat man 1 oder 2 Zuweisungen, bei beiden ist jedoch schon zur Compilezeit der Wert, der zugewiesen wird, klar.

Was ist nun perfomanter?

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo T-Man,

die Performace sollte hier überhaupt keine Rolle spielen.

Vom Stil her ist


bool b;
b = <condition>;

oder


bool b = <condition>;

besser. Nebenbei ist es auch die schnellere Variante.

herbivore

T
T-Man Themenstarter:in
210 Beiträge seit 2006
vor 18 Jahren

@herbivore:

So wie Du es vorschlägst, geht es in meinem Fall ja leider nicht. Hatte den den Code im ersten Beitrag viel zu sehr gekürzt...

Gruß,
T-Man

3.003 Beiträge seit 2006
vor 18 Jahren

Original von x86fanboy
Z.B. aus der C-Sharp Language Specification 😉

10.4.4 Field initialization
[..]

Hey, danke. Wieder was gelernt...könnte enorm praktisch sein hin und wieder.

LaTino
(erste "richtige" Sprache war C. C# erstaunt mich immer noch, was die Masse an Dingen angeht, die dem Entwickler abgenommen werden...)

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo T-Man,

warum soll es so nicht gehen?

herbivore

T
T-Man Themenstarter:in
210 Beiträge seit 2006
vor 18 Jahren

Original von herbivore
Hallo T-Man,

warum soll es so nicht gehen?

herbivore Hast Du Dir mein Beispiel mit dem switch angesehen? (Mein vorletzter Beitrag.) Ich kann nicht direkt bei der Initialisierung schon den richtigen Wert zuweisen...

Gruß,
T-Man

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo T-Man,

das ist mir klar. Ich habe ja auch "oder" geschrieben, gell. 🙂

herbivore

T
T-Man Themenstarter:in
210 Beiträge seit 2006
vor 18 Jahren

@herbivore:

Du meinst also, daß

bool add;
switch (...)
{
  case a: add = <contition a>; break;
  case b: add = <contition b>; break;
  ...
  default: add = false; break;
}
if (add) ...;

eleganter und perfomanter als

bool add = false;
switch (...)
{
  case a: if (<contition a>) add = true; break;
  case b: if (<contition b>) add = true; break;
  ...
}
if (add) ...;

ist? Eleganter finde ich es auch, aber ist es tatsächlich perfomanter?

Gruß,
T-Man

6.862 Beiträge seit 2003
vor 18 Jahren

Original von T-Man

In Variante 1 hat man auf jeden Fall genau eine Zuweisung. Der Wert, der zugewiesen wird, ist nicht zur Compilezeit klar.
In Variante 2 hat man 1 oder 2 Zuweisungen, bei beiden ist jedoch schon zur Compilezeit der Wert, der zugewiesen wird, klar.

Was ist nun perfomanter?

Selbst wenn der Wert zur Compilezeit klar ist, weiß er nicht welchen Wert er zur Laufzeit zuweisen muss, von daher ist das Argument nichtig. Und ehrlich gesagt, wenn du an solchen Stelle versuchst zu optimieren, dann läuft aber beim Rest schon was falsch.

Baka wa shinanakya naoranai.

Mein XING Profil.