在这种场景下,如何在不违反DRY(Don’t-Repeat-Yourself)原则的情况下优化性能?

发布于 2024-10-04 22:02:16 字数 1190 浏览 4 评论 0原文

假设我正在使用 C++。现在我有以下代码:

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

while 循环将被执行大量次,而 Func 是一个时间关键函数,如下所示:

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

此外, < code>flag 在 while 循环中不会改变。因此,最好将条件 if 语句移出 while 循环,并为两个条件定义两个单独的函数,如下所示:

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

但是,这将导致通过 Func_FlagBiggerThanOneFunc_FlagNoBiggerThanOne 重复 Func 中的“大东西”:

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

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

这将违反 Don't-Repeat-Yourself 原则。我们不能将“大东西”放在某个函数中,因为调用该函数将比原始的 if 语句更耗时。解决方案之一是为那些大东西定义一个宏,但是如果“逻辑1”和“逻辑2”将使用“大东西”中定义的变量怎么办?尽管宏仍然有效,但这可能会导致代码难看,程序的读者可能会想,“这些变量到底是在哪里定义的?”

Suppose that I'm using C++. Now I have the following code:

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

The while loop will be executed a huge number of times, and Func is a time-critical function like this:

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

Also, the value of flag won't be change within the while loop. Therefore, it is better to move the conditional if statement out of the while loop, and define two separate functions for the two conditions like this:

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

However, that will result in the repetition of the "big stuff" in Func by Func_FlagBiggerThanOne and Func_FlagNoBiggerThanOne:

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

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

which will violate the Don't-Repeat-Yourself principle. We can not put that "big stuff" in some function because invoking that function will be more time consuming than the original if statement. One of the solutions is to define a macro for that big stuff, but what if "logic 1" and "logic 2" will use the variables defined in "big stuff"? Though macro still works, that may result in ugly code, the programme's reader might think, "where the heck are those variables defined?"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

抱着落日 2024-10-11 22:02:16

我们不能把“大东西”放进去
某些功能,因为调用它
函数会比较耗时
比原来的 if 语句。

我有一个最喜欢的古英语习语:“小聪明,大笨蛋”(我一直对此感到内疚)。另一种说法是“不要为小事而烦恼”。
我希望我能找到 SO 的原始引用:“理发来减肥”。

使代码干净,如果你能合理地遵循 DRY,那就这样做。
然后进行性能调整。 我就是这样做的。
如果调用该函数的成本或 IF 语句的成本甚至上升到雷达上,我会感到非常惊讶。

We can not put that "big stuff" in
some function because invoking that
function will be more time consuming
than the original if statement.

I have a favorite Old English idiom: "penny wise pound foolish" (of which I've been guilty). Another way to put it is "don't sweat the small stuff".
I wish I could find the original quote on SO: "getting a haircut to lose weight".

Make the code clean, and if you can reasonably follow DRY, do so.
Then do your performance tuning. This is how I do it.
I would be very surprised if the cost of calling that function, or the cost of the IF statement, even rises onto the radar.

北音执念 2024-10-11 22:02:16

我只是想到一个解决办法。主要思想是使用#ifdef:

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

所以我们可以这样写主要逻辑:

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

但是,正如Mike建议的那样,“最好用相对的方式思考,而不是绝对的。如果“大” stuff”无法调优,这样的优化就没用了。

I just think of a solution. The main idea is to use #ifdef:

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

So we can write the main logic like this:

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

However, just as Mike suggested, "it's better to think in relative terms, rather than absolute. If the "big stuff" can not be tuned, such an optimisation will be useless.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文