0

For example I have a code like this:

void func(const QString& str) 
{
    QString s = str.replace(QRegexp("[abc]+"), " ");
    ......
 }

will the compiler optimize the var QRegep("[abc]+"), just construct it once instead of construct for each time func invoked? Or in other words, do I need to reimplement the coding for performance like this:

void func(const QString& str) 
{
    static const QRegexp sc_re("[abc]+");
    QString s = str.replace(sc_re, " ");
    ......
 }

make the QRegexp as an static const variable.

libgcc
  • 153
  • 3
  • 7
  • I don't see how the compiler could optimize it to construct `QRegexp` only once, since it cannot know what side effects that constructor may have. But, you can always inspect the generated asm for yourself to see - [Compiler Explorer](https://godbolt.org) is *great* for that. – Jesper Juhl Aug 02 '18 at 15:40
  • 4
    "..do I need to reimplement the coding for performance like this: " .. no matter what is the answer to the first part of your question, the answer to this part is a clear No. Dont do premature optimization, write code for clarity and readability, only then measure and profile (and i highly doubt that your profiler will identify that line as a hot spot) – 463035818_is_not_an_ai Aug 02 '18 at 15:42
  • Do you expect to call this millions of times? If so you may want to optimize if not you probably don't want to optimize. – drescherjm Aug 02 '18 at 16:00
  • @JesperJuhl if the compiler is compiling QRegep as well then in theory it could determine side effects (modern compilers are truly amazing in what they do). Not saying this case it would, but its not impossible to imagine that it could – pm100 Aug 02 '18 at 16:13
  • They may do some of the computation at compile-time, but I am not aware of a compiler that automatically does caching the way you suggest. – Marc Glisse Aug 04 '18 at 20:25

1 Answers1

0

will the compiler optimize the var QRegep("[abc]+"), just construct it once instead of construct for each time func invoked?

You are assuming that each invocation of func will construct an identical QRegexp object, but how do you know that? How do you know, for example, that these objects do not contain a serial number, an integer member that is set to the number of QRegexp objects previously constructed? If such a serial number was being used, it would be wrong for the compiler to construct your temporary variable just once.

OK, we can reasonably guess that nothing like that is going on. The point, though, is that we are guessing, and the compiler is not allowed to guess. So a prerequisite for the compiler considering such an optimization would be that the definition of the constructor is available (which is an implementation detail of that class, something you should not make your code dependent on).

If the constructor's definition is available, and if that definition provably produces the same results given the same input (and probably some other technical restrictions that slip my mind at the moment), then a compiler would be allowed to make this optimization.

I do not know if any compilers choose to provide this sort of optimization when it would be both allowed and beneficial (another assumption you've made). Performance testing of the two candidates with and without optimizations enabled should reveal if your particular compiler is likely taking advantage of this.

Or in other words, do I need to reimplement the coding for performance like this:

You almost never need to re-implement for performance. (One exception would be if your code is so inefficient it would take centuries to finish. I'm pretty sure we're not in that ballpark.) A better question is "should". I'll go with that.

In this specific case I would guess "no, that looks like premature optimization". However, that is just a guess, so I'll proceed to general guidelines that you can apply.

You should re-implement for performance only if: 1) the performance gain is noticeable to an end user, or 2) the new code is easier for a programmer to read and understand. In other cases, rely on the compiler to make appropriate optimizations.

In your case, I see the variable name sc_re and think "what is that?" So point 2 is out. That leaves the question of a noticeable performance gain. This usually is not something one can determine by simply asking around. Typically, it involves performance testing, probably of at least two types. One test would time the two candidates in an artificial heavy loop to see how large the performance gain is (if there is one at all). The other test would profile your actual program to see if this code is called often enough for the gain to be noticed by an end user. A good third test would be to give the actual program to an end user and see if they notice the difference.

Of these tests, profiling might be the most productive use of your time. (Programmers are notoriously bad at identifying true performance roadblocks without the aid of a profiler.) If you spend 2 milliseconds in this function every 5 minutes, why spend time trying to improve that? On the other hand, if you spend 1 second in this function each time it is called, the profiler might tell you whether or not this constructor is the main culprit.

JaMiT
  • 14,422
  • 4
  • 15
  • 31