Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save abbadon1334/88bc2fde67ee2e584559ae3ce0ccfe3d to your computer and use it in GitHub Desktop.
Save abbadon1334/88bc2fde67ee2e584559ae3ce0ccfe3d to your computer and use it in GitHub Desktop.
Testing check for class existence and if caching class name is relevant in function of performance check over 10000000 iterations just to minimize errors and first loading of not already loaded existent class Results on PHP 7.3.5 shows that is not needed. https://github.com/atk4/ui/pull/702
<?php
/*
Testing check for class existence and if caching class name is relevant in function of performance
check over 10000000 iterations just to minimize errors and first loading of not already loaded existent class
Results on PHP 7.3.5 below shows that is not needed :)
BENCHMARK CASE CACHE REFLECTION AVG Time(s) Max Time(s) Tot Time(s) StdDev Time AVG MEM(b)
\Profiler N N 0.00000069 0.00246596 6.92156839 0.00000104 53.68750880
\atk4\data\Model N N 0.00000070 0.00699806 6.97353435 0.00000346 53.68750880
\NotExistentNamespace\NotExistentClass N N 0.00000123 0.01234603 12.33240128 0.00000700 53.68751520
\Profiler Y N 0.00000228 0.00243306 22.75917459 0.00000118 53.68791840
\atk4\data\Model Y N 0.00000287 0.04152799 28.73383260 0.00002744 53.68791840
\NotExistentNamespace\NotExistentClass Y N 0.00000310 0.02863598 30.98811865 0.00001597 53.68750880
\Profiler N Y 0.00000089 0.02554202 8.89627051 0.00001268 53.68750880
\atk4\data\Model N Y 0.00000085 0.00770283 8.50388932 0.00000407 53.68750880
\NotExistentNamespace\NotExistentClass N Y 0.00000229 0.02184820 22.92274952 0.00001156 53.68772800
\Profiler Y Y 0.00000257 0.05440784 51.34514070 0.00001765 53.68750480
\atk4\data\Model Y Y 0.00000271 0.01353407 54.10150146 0.00000955 53.68750480
\NotExistentNamespace\NotExistentClass Y Y 0.00000333 0.02629113 66.64919424 0.00001241 53.68740960
*/
//include 'vendor/autoload.php';
include '../bootstrap.php';
new \atk4\data\Model();
class Profiler
{
/** @var float */
private $time_start;
/** @var array<float> */
private $times = [];
/** @var float */
private $memory_start;
/** @var array<float> */
private $memory = [];
public function __destruct()
{
usleep(50000); // give time to php
gc_collect_cycles(); // trigger_gc
}
public function start()
{
$this->time_start = $this->getMicrotime();
$this->memory_start = $this->getMemoryUsage();
}
private function getMicrotime()
{
return (float)microtime(true);
}
private function getMemoryUsage()
{
return (float)memory_get_usage();
}
public function end()
{
$this->times[] = $this->getMicrotime() - $this->time_start;
$this->memory[] = $this->getMemoryUsage() - $this->memory_start;
}
public function getAverageMemory()
{
return array_sum($this->memory) / count($this->memory);
}
public function getTimes()
{
return $this->times;
}
public function getMin()
{
return min($this->times);
}
public function getMax()
{
return max($this->times);
}
public function getStdDev()
{
$fMean = $this->getAverageTime();
$fVariance = 0.0;
foreach ($this->times as $i) {
$fVariance += pow($i - $fMean, 2);
}
$fVariance /= $this->getCount();
return (float)sqrt($fVariance);
}
public function getAverageTime()
{
return $this->getSum() / $this->getCount();
}
public function getSum()
{
return array_sum($this->times);
}
public function getCount()
{
return count($this->times);
}
}
function Bench($name, $use_cache = false, $use_reflection = false, $cycles = 10000000)
{
$classes_array = [];
if ($use_cache) {
// simulate an array with more classes
for ($i = 0; $i < 4; $i++) {
foreach (get_declared_classes() as $class) {
$classes_array[] = $class;
}
}
}
$profile = new Profiler();
if (!$use_cache) {
if ($use_reflection) {
for ($a = 0; $a < $cycles; $a++) {
$profile->start();
try {
new ReflectionClass($name);
} catch (ReflectionException $Exception) {
// NOT EXISTS
}
$profile->end();
}
} else {
for ($a = 0; $a < $cycles; $a++) {
$profile->start();
class_exists($name);
$profile->end();
}
}
} else {
if ($use_reflection) {
for ($a = 0; $a < $cycles; $a++) {
$profile->start();
if (in_array($name, $classes_array)) {
// OK
} else {
try {
new ReflectionClass($name);
$classes_array[$name] = true;
} catch (Throwable $Exception) {
// NOT EXISTS
}
}
$profile->end();
}
}
for ($a = 0; $a < $cycles; $a++) {
$profile->start();
if (in_array($name, $classes_array)) {
// OK
} else {
if (class_exists($name)) {
$classes_array[$name] = true;
}
}
$profile->end();
}
}
$formatNumber = function ($v) {
$v = number_format($v, 8, '.', '');
return str_pad($v, 13, ' ', STR_PAD_LEFT);
};
formatOutput(
$name,
$use_cache ? 'Y' : 'N',
$use_reflection ? 'Y' : 'N',
$formatNumber($profile->getAverageTime()),
$formatNumber($profile->getMax()),
$formatNumber($profile->getSum()),
$formatNumber($profile->getStdDev()),
$formatNumber($profile->getAverageMemory())
);
}
function formatOutput(...$args)
{
$line_format = '% 40s % 12s % 12s % 13s % 13s % 13s % 13s % 13s' . PHP_EOL;
echo sprintf($line_format, ...$args);
}
formatOutput(
'BENCHMARK CASE',
'CACHE',
'REFLECTION',
'AVG Time(s)',
'Max Time(s)',
'Tot Time(s)',
'StdDev Time',
'AVG MEM(b)'
);
$classesToTest = [
"\\Profiler", // already loaded class
"\\atk4\\data\\Model",
"\\NotExistentNamespace\\NotExistentClass", // not exists
];
foreach ([false, true] as $useReflection) {
$use_cache = false;
foreach ($classesToTest as $className) {
Bench($className, $use_cache, $useReflection);
}
$use_cache = true;
foreach ($classesToTest as $className) {
Bench($className, $use_cache, $useReflection);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment