Skip to content
This repository has been archived by the owner on Jul 12, 2019. It is now read-only.

Commit

Permalink
Merge pull request #5 from Ocramius/feature/#4-static-cached-instance…
Browse files Browse the repository at this point in the history
…s-map

#4 - static cached instances map
  • Loading branch information
Ocramius committed Jun 15, 2014
2 parents f0cedfc + 4bf0f60 commit 7e9bbf6
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 100 deletions.
74 changes: 50 additions & 24 deletions src/Instantiator/Instantiator.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,47 +32,33 @@ final class Instantiator implements InstantiatorInterface
/**
* @var CallbackLazyMap of {@see \Closure} instances
*/
private $cachedInstantiators;
private static $cachedInstantiators;

/**
* @var CallbackLazyMap of objects that can directly be cloned
*/
private $cachedCloneables;
private static $cachedCloneables;

/**
* Constructor.
*/
public function __construct()
{
$that = $this;

$this->cachedInstantiators = new CallbackLazyMap(function ($className) use ($that) {
return $that->buildFactory($className);
});

$cachedInstantiators = $this->cachedInstantiators;

$this->cachedCloneables = new CallbackLazyMap(function ($className) use ($that, $cachedInstantiators) {
$reflection = new ReflectionClass($className);

if ($reflection->hasMethod('__clone')) {
return null;
}

/* @var $factory Closure */
$factory = $cachedInstantiators->$className;

return $factory();
});
// initialize static state, if not done before
self::$cachedInstantiators = $this->getInstantiatorsMap();
self::$cachedCloneables = $this->getCloneablesMap();
}

/**
* {@inheritDoc}
*/
public function instantiate($className)
{
if ($cloneable = $this->cachedCloneables->$className) {
if ($cloneable = self::$cachedCloneables->$className) {
return clone $cloneable;
}

$factory = $this->cachedInstantiators->$className;
$factory = self::$cachedInstantiators->$className;

/* @var $factory Closure */
return $factory();
Expand Down Expand Up @@ -154,4 +140,44 @@ private function isPhpVersionWithBrokenSerializationFormat()
{
return PHP_VERSION_ID === 50429 || PHP_VERSION_ID === 50513 || PHP_VERSION_ID === 50600;
}

/**
* Builds or fetches the instantiators map
*
* @return CallbackLazyMap
*/
private function getInstantiatorsMap()
{
$that = $this; // PHP 5.3 compat

return self::$cachedInstantiators = self::$cachedInstantiators
?: new CallbackLazyMap(function ($className) use ($that) {
return $that->buildFactory($className);
});
}

/**
* Builds or fetches the cloneables map
*
* @return CallbackLazyMap
*/
private function getCloneablesMap()
{
$cachedInstantiators = $this->getInstantiatorsMap();

return self::$cachedCloneables = self::$cachedCloneables
?: new CallbackLazyMap(function ($className) use ($cachedInstantiators) {
$reflection = new ReflectionClass($className);

// not cloneable if it implements `__clone`
if ($reflection->hasMethod('__clone')) {
return null;
}

/* @var $factory Closure */
$factory = $cachedInstantiators->$className;

return $factory();
});
}
}
97 changes: 21 additions & 76 deletions tests/InstantiatorPerformance/InstantiatorPerformanceEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,120 +31,65 @@ class InstantiatorPerformanceEvent extends AthleticEvent
/**
* @var \Instantiator\Instantiator
*/
private $cleanInstantiator;

/**
* @var \Instantiator\Instantiator
*/
private $warmedUpInstantiator;
private $instantiator;

/**
* {@inheritDoc}
*/
protected function setUp()
{
$this->cleanInstantiator = new Instantiator();
$this->warmedUpInstantiator = new Instantiator();
$this->instantiator = new Instantiator();

$this->warmedUpInstantiator->instantiate(__CLASS__);
$this->warmedUpInstantiator->instantiate('ArrayObject');
$this->warmedUpInstantiator->instantiate('InstantiatorTestAsset\\SimpleSerializableAsset');
$this->warmedUpInstantiator->instantiate('InstantiatorTestAsset\\SerializableArrayObjectAsset');
$this->warmedUpInstantiator->instantiate('InstantiatorTestAsset\\UnCloneableAsset');
$this->instantiator->instantiate(__CLASS__);
$this->instantiator->instantiate('ArrayObject');
$this->instantiator->instantiate('InstantiatorTestAsset\\SimpleSerializableAsset');
$this->instantiator->instantiate('InstantiatorTestAsset\\SerializableArrayObjectAsset');
$this->instantiator->instantiate('InstantiatorTestAsset\\UnCloneableAsset');
}

/**
* @iterations 20000
* @baseline
* @group simple-class
* @group instantiation
*/
public function testInstantiateSelfWithoutWarmup()
public function testInstantiateSelf()
{
$this->cleanInstantiator->instantiate(__CLASS__);
$this->instantiator->instantiate(__CLASS__);
}

/**
* @iterations 20000
* @group simple-class
*/
public function testInstantiateSelfWithWarmup()
{
$this->warmedUpInstantiator->instantiate(__CLASS__);
}

/**
* @iterations 20000
* @baseline
* @group internal-class
*/
public function testInstantiateInternalClassWithoutWarmup()
{
$this->cleanInstantiator->instantiate('ArrayObject');
}

/**
* @iterations 20000
* @group internal-class
* @group instantiation
*/
public function testInstantiateInternalClassWitWarmup()
{
$this->warmedUpInstantiator->instantiate('ArrayObject');
}

/**
* @iterations 20000
* @baseline
* @group serializable-class
*/
public function testInstantiateSimpleSerializableAssetClassWithoutWarmup()
{
$this->cleanInstantiator->instantiate('InstantiatorTestAsset\\SimpleSerializableAsset');
$this->instantiator->instantiate('ArrayObject');
}

/**
* @iterations 20000
* @group serializable-class
* @group instantiation
*/
public function testInstantiateSimpleSerializableAssetClassWithWarmup()
public function testInstantiateSimpleSerializableAssetClass()
{
$this->warmedUpInstantiator->instantiate('InstantiatorTestAsset\\SimpleSerializableAsset');
$this->instantiator->instantiate('InstantiatorTestAsset\\SimpleSerializableAsset');
}

/**
* @iterations 20000
* @baseline
* @group internal-serializable-class
*/
public function testInstantiateSerializableArrayObjectAssetWithoutWarmup()
{
$this->cleanInstantiator->instantiate('InstantiatorTestAsset\\SerializableArrayObjectAsset');
}

/**
* @iterations 20000
* @group internal-serializable-class
*/
public function testInstantiateSerializableArrayObjectAssetWithWarmup()
{
$this->warmedUpInstantiator->instantiate('InstantiatorTestAsset\\SerializableArrayObjectAsset');
}

/**
* @iterations 20000
* @baseline
* @group un-cloneable-class
* @group instantiation
*/
public function testInstantiateUnCloneableAssetWithoutWarmup()
public function testInstantiateSerializableArrayObjectAsset()
{
$this->cleanInstantiator->instantiate('InstantiatorTestAsset\\UnCloneableAsset');
$this->instantiator->instantiate('InstantiatorTestAsset\\SerializableArrayObjectAsset');
}

/**
* @iterations 20000
* @group un-cloneable-class
* @group instantiation
*/
public function testInstantiateUnCloneableAssetWithWarmup()
public function testInstantiateUnCloneableAsset()
{
$this->warmedUpInstantiator->instantiate('InstantiatorTestAsset\\UnCloneableAsset');
$this->instantiator->instantiate('InstantiatorTestAsset\\UnCloneableAsset');
}
}

0 comments on commit 7e9bbf6

Please sign in to comment.