coptimizationfunction-pointersfunction-calls

optimize function pointer checking in loop


I have render function, but users can override it by setting function pointer; in every frame I'm checking if it exists or not, and if not I'm using the default function:

GK_EXPORT
void
gkScenePerLightRenderPath(GkScene *scene) {
  /* ... */

  do {
    /* ... */
    for (i = 0; i < c; i++) {
      modelInst = objs[i];

      if (!scene->renderModelFn)
        gkRenderModel(scene, modelInst);
      else
        scene->renderModelFn(scene, modelInst);
    }
  } while (/* next light */);
}

I thought maybe I could write this as below:

GK_EXPORT
void
gkScenePerLightRenderPath(GkScene *scene) {
  /* ... */
  GkRenderModelFn renderModelFn;

  /* ... */

  if (!scene->renderModelFn)
    renderModelFn = gkRenderModel;
  else
    renderModelFn = scene->renderModelFn;

  do {
    /* ... */
    for (i = 0; i < c; i++) {
      modelInst = objs[i];
      renderModelFn(scene, modelInst);
    }
  } while (/* next light */);
}

Which is better? In second version seems like I'm hiding gkRenderModel so maybe compiler can't apply optimization? If it doesn't matter for compiler assigning gkRenderModel to a pointer then second one seems more optimal because if / else is outside of two loop?


Solution

  • It depends on several factors:

    If it guaranteed to be an external / out-of-line function, and nothing in the loop modifies the object pointed to in the scene pointer, then it is better to put the if statement before the loop, so it only needs to be evaluated once.

    However if there is any possibility that the called function could modify the renderModelFn member of the passed-in scene object, moving the check before the loop would change the behavior.

    Also, calls to function pointers are always out-of-line. So moving the if statement outside the loop would defeat any inlining possibility. In that case it would be preferable to keep the if statement inside the loop.