• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 221
  • Last Modified:

Performance (and readability)

I have a large number of test condition that I need to evaluate based upon 2 values (one is a double, the other is an int).  For example, here is what I have now...

if ( strcmp(myString, "CONDX") == 0 )
     if (( fVal >=3.0 && score >= 344 ) ||
         ( fVal >= 4.5 && score >= 294) ||
         ( fVal >=6.0 && score >= 240 ) ||
         // 20 more conditionals go here... )
     {
     }
else if ( strcmp(myString, "LIMTD") = 0 )
     if (( fVal >=3.0 && score >= 487 ) ||
         ( fVal >= 4.5 && score >= 428) ||
         ( fVal >=6.0 && score >= 294 ) ||
         // 20 more conditionals go here... )
     {
     }

There is no formula that can be applied between fVal and score.
The breaks for fVal are ALWAYS the same (3, 4.5, 6, etc - for all 23 comparisons).

Is there  a more elegant way to write this?  Is the performance of this approach fairly fast (this comparison is done ALOT).
0
GlennJ
Asked:
GlennJ
  • 3
  • 3
  • 2
  • +2
1 Solution
 
griesshCommented:
Hi GlennJ,

Depending on the implementation of your compiler and the right optimization settings you should be OK. A 'good' compiler will stop evaluating the conditions once it found a TRUE in the list.
For readability ... Instead of hardcoding these values in if statements I would create arrays with pairs of fVal and score and just loop through the array elements (that would also ensure that you only run as many tests as needed)
if (strcmp(myString, cond) == 0 )
{
  i=0
  while (i<endLoop)
     if (fvail >=val[1][i] && score >=ascore[2][i])
     {
         // do something
         i=endLoop;
     }
     endLoop++;
  }

======
Werner
0
 
griesshCommented:
should say:
if (fvail >=val[1][i] && score >=val[2][i])

... but that's just an idea.
0
 
burtdavCommented:
/* You'll get best performance out of the hard-code you have (it's part of the C standard, not compiler-specific, to do short-circuit evaluation); you'll get best performance if you evaluate the most commonly true conditions first.

gnessh's idea of storing your condition values in arrays is a good one, though, as long as performance here is not too critical (I don't imagine it would be a bottleneck) - it will improve legibility.
*/

const int MAX_STR_IDX = 2;
const int MAX_BOUND_IDX = 23;
char *str[MAX_STR_IDX] = [
   "CONDX",
   "LIMTD"
];
double fValBound[MAX_FVAL_IDX] = [3.0, 4.5, 6.0, ...];
int scoreBound[MAX_STR_IDX][MAX_FVAL_IDX] = [
   [344, 294, 240, ...],
   [487, 428, 294, ...]
];

/* you can improve performance a little by sorting both sets of parallel arrays above by likelihood of each case
*/

int i, j, conditionMet;
for (i = 0; i < MAX_STR_IDX && strcmp(myString, str[i]); i++);
if (!strcmp(myString, str[i])) {
   for (j = 0, conditionMet = 0; j < MAX_BOUND_IDX && conditionMet == 0; j++) {
      if (fVal >= fValBound[i][j] && score >= scoreBound[i][j]) {
         conditionMet = 1;
      }
   }
   if (conditionMet) {
      /* here is where your conditional code goes */
      /* note that the variable i contains the index of the string that myString matched, if you need that. */
   }
}
0
Problems using Powershell and Active Directory?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

 
griesshCommented:
... shame on me ... you are right about the short-circuit evaluation
0
 
burtdavCommented:
If I wasn't certain I was right, I'd say so.
But, no shame on you for a simple slip-up, griessh.
:)
0
 
guynumber5764Commented:
It looks like there might be also be a performance gain by preconverting fVal to an int before evaluation so that you can make all your comparisons int-to-int.  The benefit gained (if any) will ultimately depend on how deep into the conditional you go each time.

int iVal = 10 * fVal;
if ( strcmp(myString, "CONDX") == 0 )
     if ((iVal >=30 && score >= 344 ) ||
         ( iVal >= 45 && score >= 294) ||
         ( iVal >=60 && score >= 240 ) ||
         // 20 more conditionals go here... )
     {
    etc.

If you want more speed, arrange your conditional so the most common cases are first.  If you want more maintainability, use the arrays suggested above and leave the conditionals in natural order.
0
 
burtdavCommented:
/* For speed and maintainability, with a bit of extra effort, you could sort the arrays at run-time (once, just after they're initialised), based on another parallel array which would contain the order (say, little numbers for common cases and big ones for rare cases) like so:
*/

int priority[MAX_BOUND_IDX] = [3, 1, 2, ...];
0
 
bookiCommented:
GlennJ,

Could you please post the entire if elseif conditionals..

b.
0
 
bookiCommented:
GlennJ,

Sorry, you can ignore my last post..  the only way I can think of to make the test faster is to use a lookup table.  Granted this is probably overkill as the gains will likely total an insignificant percantage of the runtime and such a table would require a significant chunk of memory.

b.
0
 
ozoCommented:
Or you could binary search
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Worried about phishing attacks?

90% of attacks start with a phish. It’s critical that IT admins and MSSPs have the right security in place to protect their end users from these phishing attacks. Check out our latest feature brief for tips and tricks to keep your employees off a hackers line!

  • 3
  • 3
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now