2010-11-24 6 views
1

Angenommen, ich verwende C++. Jetzt habe ich den folgenden Code:Wie kann die Leistung optimiert werden, ohne dass das DRY-Prinzip (Do not-Repeat-Yourself) in diesem Szenario verletzt wird?

int flag; 
// ... 
while (!TimeToExitLoop()) { 
    Func(); 
} 

Die while Schleife eine große Anzahl von Malen ausgeführt werden, und Func ist eine zeitkritische Funktion wie folgt aus:

void Func() { 
    // some big stuff ... 
    if (flag > 1) { 
     // logic 1 ... 
    } 
    else { 
     // logic 2 ... 
    } 
} 

Auch der Wert von flag wird nicht innerhalb der while Schleife geändert werden. Daher ist es besser, die bedingte if Anweisung aus der while Schleife zu bewegen, und definiert zwei separate Funktionen für die beiden Bedingungen wie folgen aus:

int flag; 
// ... 
if (flag > 1) { 
    while (!TimeToExitLoop()) { 
     Func_FlagBiggerThanOne(); 
    } 
} 
else { 
    while (!TimeToExitLoop()) { 
     Func_FlagNoBiggerThanOne(); 
    } 
} 

jedoch, die in der Wiederholung der „großen Sachen“ führen in Func von Func_FlagBiggerThanOne und Func_FlagNoBiggerThanOne:

void Func_FlagBiggerThanOne() { 
    // big stuff ... 
    // logic 1 ... 
} 

void Func_FlagNoBiggerThanOne() { 
    // big stuff ... 
    // logic 2 ... 
} 

die die Einmalige Repeat-Yourself-Prinzip verstoßen wird. Wir können dieses "große Zeug" nicht in irgendeiner Funktion verwenden, weil das Aufrufen dieser Funktion zeitaufwendiger ist als die ursprüngliche if-Anweisung. Eine der Lösungen besteht darin, ein Makro für diese großen Dinge zu definieren, aber was ist, wenn "logisch 1" und "logisch 2" die Variablen verwenden, die in "großen Dingen" definiert sind? Obwohl das Makro immer noch funktioniert, was zu einem hässlichen Code führen kann, könnte der Leser des Programms denken: "Wo zum Teufel sind diese Variablen definiert?"

+0

Verwenden Sie einen Compiler/Linker, der die Bedingung aus der Schleife entfernen kann ... aber dieser Compiler/Linker muss ziemlich sein funky wenn 'Func' in einer anderen Datei ist, weil' flag' anscheinend global ist. – lijie

+1

«Wir können dieses" große Zeug "nicht in irgendeiner Funktion verwenden, weil das Aufrufen dieser Funktion zeitaufwändiger ist als die ursprüngliche if-Anweisung. » Kannst du es nicht inline? – Zecc

+0

Ich denke, ein guter Programmierer sollte vom Compiler/Linker nichts annehmen. Auch, Zecc, ich denke, inline wird nicht funktionieren, weil das Zeug sehr "groß" ist. –

Antwort

0

Wir können nicht setzen, dass „große Sachen“ in eine Funktion, weil Aufruf, dass Funktion mehr Zeit sein wird als die ursprünglichen raubend if-Anweisung.

Ich habe eine Lieblings Old English Idiom: "Penny Weisse Pfund töricht" (von denen ich schuldig bin). Ein anderer Weg, um es zu sagen ist "verschwinde nicht die kleinen Sachen". Ich wünschte, ich könnte das ursprüngliche Zitat auf SO finden: "einen Haarschnitt bekommen, um Gewicht zu verlieren".

Machen Sie den Code sauber, und wenn Sie vernünftigerweise DRY folgen können, tun Sie dies. Dann tun Sie Ihre Leistungsoptimierung. This is how I do it. Ich wäre sehr überrascht, wenn die Kosten für den Aufruf dieser Funktion oder die Kosten der IF-Anweisung sogar auf das Radar steigen würden.

+0

Danke, Mike. Ich habe gerade Ihren Link "So mache ich es" gelesen. In meinem Projekt habe ich die von Ihnen vorgeschlagenen Schritte verfolgt. Jetzt scheint ich eine Wand getroffen zu haben. Die Kosten für den Aufruf einer Funktion in 'Func' sind laut meinem Experiment in der Tat zeitaufwendig. Ich habe noch nicht den Effekt getestet, den IF aus 'Func' heraus zu bewegen. Jetzt lasse ich es einfach dort, um den Code sauber zu halten. Aber ich bin neugierig, was ich tun soll, wenn ich bis zum Äußersten gehen will. Angenommen, die WHILE-Schleife wird 10 · 10 mal ausgeführt, dann kostet die IF-Anweisung etwa 5 Sekunden auf einer 2 GHz-CPU. –

+1

Oh ... wenn die IF-Anweisung insgesamt 5 Sekunden dauert, werden die "großen Sachen" viel mehr Zeit brauchen. Es ist also wirklich nicht wert, viel Zeit damit zu verbringen, den IF aus 'Func' herauszuholen. Der einzige Grund dafür ist Perfektionismus und Neugier. –

+0

@Zhixiang: Ich denke, das stimmt. Es ist besser, relativ zu denken als absolut. Wenn du das "große Zeug" so gut abgestimmt hast, dass es nicht mehr groß ist und das IF und 'Func' einen großen Anteil haben, dann ist dein Code" schneller als ein verbrühter Hund "und du bist großartig Coder :-) –

0

Ich denke nur an eine Lösung. Die Hauptidee ist #ifdef zu verwenden:

#define FUNC() do { \ 
    // big stuff ... 
#ifdef FLAG_BIGGER_THAN_ONE \ 
    // logic 1 ... \ 
#else \ 
    // logic 2 ... \ 
#endif \ 
} while(0) 

So können wir die Hauptlogik wie folgt schreiben:

int flag;    
// ...    
if (flag > 1) {    
    while (!TimeToExitLoop()) { 
#define FLAG_BIGGER_THAN_ONE    
     FUNC(); 
#undef FLAG_BIGGER_THAN_ONE    
    }    
}    
else {    
    while (!TimeToExitLoop()) {    
     FUNC();    
    }    
} 

, jedoch nur als Mike vorgeschlagen, „es besser ist, relativ gesehen zu denken, anstatt Wenn die "großen Sachen" nicht gestimmt werden können, ist eine solche Optimierung nutzlos.

+0

Eigentlich funktioniert dieser Weg nicht. Das Makro FUNC() kann nicht kompiliert werden. –