The function function_exists are called in Drupal very frequently. For example in url():

...
  if (function_exists('language_url_rewrite')) {
    language_url_rewrite($path, $options);
  }
...
  if (function_exists('custom_url_rewrite_outbound')) {
    // Modules may alter outbound links by reference.
    custom_url_rewrite_outbound($path, $options, $original_path);
  }
...

And my little exploration on performance. Code:

function test_time_1() {
  if(function_exists("function_exists")) {
    // Nothing done.
  }
}

function test_time_2() {
  static $yes;
  if(!isset($yes)) $yes = function_exists("function_exists");
  if($yes) {
    // Nothing done.
  }
}

$time_start = microtime(true);
for($i=0;$i<1000000;$i++) {test_time_1();}
$time_1 = microtime(true) - $time_start;

$time_start = microtime(true);
for($i=0;$i<1000000;$i++) {test_time_2();}
$time_2 = microtime(true) - $time_start;

print "time 1: $time_1</br>";
print "time 2: $time_2</br>";

Result:

time 1: 8.3456580638885
time 2: 4.6089758872986

Conclusion: Code with static variable faster then code with permanent calling of function_exists().

May somebody patch a Drupal core?

Comments

nevets’s picture

The use of function_exists is there because the code in question is dynamic. The function is used to dynamically enable/disable certain functionality based on the function checked.

drq’s picture

May function undefine while script's running?

styro’s picture

Did I read that right? A static variable saves less than 4 microseconds per call? ie if a function that uses function_exists() is itself called 250 times, it will save one millisecond? This is glossing over that the 4 microsecond saving was compared to function_exists() being called 1 time vs 1 million times, and the savings on 1 vs 250 times would presumably be a tiny bit lower.

And that is best case - how does the benchmark compare when instead of one function and one static variable being called 250 times, you have 25 functions and 25 static variables being called 10 times each? That way there are now 25 calls to function_exists() instead of just one. Presumably the total savings in that case would be between 1/25th of a millisecond (more likely) and 1 millisecond (less likely).

You'd need to evaluate how often function_exists() is called from each location to really get a handle on what is going on.

Also, how does it cope when the name of the function to be checked is dynamically generated? ie like most Drupal hooks? Would you keep an array of the results?

Actually the module_implements() function used by module_invoke_all() already does this, so you won't get any savings from the workhorse of the hook system.

As the situation moves further from your benchmark and closer to real world Drupal, I can see the benefits getting smaller.

I'm not sure that the modest savings of implementing this across all of Drupal justifies the extra code. But I'm sure that if you can show the benefit of using it in specific cases that get called a lot (like the url() function), the core devs would be interested in a patch. And it would be a much simpler patch :)

--
Anton

drq’s picture

May be, for high loaded project...

styro’s picture

and a lot of high load sites are already doing that kind of profiling. Also I'm not sure what effects things like opcode caches have on this as well.

But as I said, if you can show a noticeable real world benefit (ie not an artificial benchmark) for specific cases, go for it. It would have to be specific common cases though - the static variable check adds its own overhead for functions that are only going to get checked once.

--
Anton