Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@bwaidelich
Created November 6, 2013 11:34
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bwaidelich/7334680 to your computer and use it in GitHub Desktop.
Save bwaidelich/7334680 to your computer and use it in GitHub Desktop.
A simple script to compare performance of magic __call methods to real implementations
<?php
class MagicMethodFixture {
/**
* @var array
*/
protected $configurations;
public function __construct() {
$this->configurations = array(
'foo' => 'bar',
'Bar' => 'baz'
);
}
/**
* @param string $configurationKey
* @return mixed
*/
public function get($configurationKey) {
return $this->configurations[$configurationKey];
}
/**
* @param string $methodName
* @param array $arguments
* @return mixed
*/
public function __call($methodName, array $arguments) {
if (substr($methodName, 0, 3) === 'get') {
$configurationKey = lcfirst(substr($methodName, 3));
return $this->configurations[$configurationKey];
} elseif (substr($methodName, 0, 3) === 'has') {
$configurationKey = lcfirst(substr($methodName, 3));
return isset($this->configurations[$configurationKey]);
}
trigger_error('Call to undefined method ' . get_class($this) . '::' . $methodName, E_USER_ERROR);
}
}
$iterations = 1000000;
$fixture = new MagicMethodFixture();
echo '<h2>magic __call:</h2>';
$start = microtime(TRUE);
for ($i = 0; $i < $iterations; $i ++) {
$fixture->getFoo();
}
$end = microtime(TRUE);
echo '<p>' . ($end - $start) . ' seconds</p>';
echo '<h2>real implementation:</h2>';
$start = microtime(TRUE);
for ($i = 0; $i < $iterations; $i ++) {
$fixture->get('foo');
}
$end = microtime(TRUE);
echo '<p>' . ($end - $start) . ' seconds</p>';
@bwaidelich
Copy link
Author

The response I get for 1.000.000 iterations (variation: < ∓0.01 seconds)

magic __call:
1.1016759872437 seconds

real implementation:
0.21022200584412 seconds

@Catalin-Ionut
Copy link

Catalin-Ionut commented Jun 20, 2018

The response for 1.000.000 iterations in php 7.2.5

magic __call:
0.2891480922699 seconds

real implementation:
0.052653789520264 seconds

@maxgalbu
Copy link

maxgalbu commented Dec 9, 2020

The magic and the "not magic" method are not comparable:

  • magic does lcfirst() and substr() then return something from a map
  • non magic only returns something from a map

Of course you will get more time spent in the "magic" version. A fair test would involve doing thing a lot different.

@bwaidelich
Copy link
Author

This test didn't mean to be fair. I just wanted to find out how much slower a magic getSomething() is compared to a get('something') implementation.

@kemo
Copy link

kemo commented Nov 22, 2022

I created a version that doesn't do string manipulations or use call_user_func inside of __call to make this more fair:

https://gist.github.com/kemo/b180bba7eec7626e02e7755ac5bb96f1

Still, __call is ~5 times slower even on PHP 8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment