Skip to content

Instantly share code, notes, and snippets.

@ralphschindler
Last active October 21, 2017 12:55
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ralphschindler/746bbd557656a849aa0c to your computer and use it in GitHub Desktop.
Save ralphschindler/746bbd557656a849aa0c to your computer and use it in GitHub Desktop.
Anonymous Proxy Pattern (Ralph Schindler)

README

Problem & Solution

Problem: you want to set protected properties of an object, or a set of objects as efficiently and without much convention as possible.

Solution in 5.4 is the "Anonymous Proxy", see the by-anonymous-proxy.php file.

Performance

How fast is it? Given around 70000 objects with 10 properties each on my system here are the results, (the number next to the title is the peak memory usage):

$ time php by-method.php; \
time php by-reflection.php; \
time php by-proxy.php; \
time php by-closure-proxy.php; \
time php by-anonymous-proxy.php 

By Method: 102015224

real	0m1.311s
user	0m1.265s
sys	    0m0.043s

By Reflection 102029416

real	0m1.337s
user	0m1.284s
sys	    0m0.052s

By Proxy 102023728

real	0m0.629s
user	0m0.582s
sys	    0m0.044s

By Closure Proxy 102018288

real	0m0.940s
user	0m0.892s
sys	    0m0.047s

By Anonymous Proxy 102024992

real	0m1.149s
user	0m1.094s
sys	    0m0.053s
<?php
$objs = include 'object-array.php';
class DynamicProxy {
protected $class = '';
protected $valuesToObjectClosure = null;
protected $valuesFromObjectClosure = null;
public function __construct($class) {
$this->class = $class;
$this->valuesToObjectClosure = function ($values) {
foreach ($values as $name => $value) {
$this->$name = $value;
}
};
$this->valuesFromObjectClosure = function () {
return get_object_vars($this);
};
}
public function setValuesToObject(array $values, $object) {
$proxy = $this->valuesToObjectClosure->bindTo($object, $this->class);
$proxy($values);
}
public function getObjectValues($object) {
$proxy = $this->valuesFromObjectClosure->bindTo($object, $this->class);
return $proxy();
}
}
$proxy = new DynamicProxy('Foo');
foreach ($objs as $x => $obj) {
$proxy->setValuesToObject(array(
'p1' => $x . ' ==== aaaaaaaaaaaaaaaaaaaaaaa',
'p2' => $x . ' ==== bbbbbbbbbbbbbbbbbbbbbbb',
'p3' => $x . ' ==== ccccccccccccccccccccccc',
'p4' => $x . ' ==== ddddddddddddddddddddddd',
'p5' => $x . ' ==== eeeeeeeeeeeeeeeeeeeeeee',
'p6' => $x . ' ==== fffffffffffffffffffffff',
'p7' => $x . ' ==== ggggggggggggggggggggggg',
'p8' => $x . ' ==== hhhhhhhhhhhhhhhhhhhhhhh',
'p9' => $x . ' ==== iiiiiiiiiiiiiiiiiiiiiii',
'p10' => $x . ' ==== jjjjjjjjjjjjjjjjjjjjjjj',
),
$obj
);
}
// var_dump($proxy->getObjectValues($obj));
echo PHP_EOL . 'By Anonymous Proxy ' . memory_get_peak_usage() . PHP_EOL;
<?php
$objs = include 'object-array.php';
$proxy = function($values) {
$this->p1 = $values['p1'];
$this->p2 = $values['p2'];
$this->p3 = $values['p3'];
$this->p4 = $values['p4'];
$this->p5 = $values['p5'];
$this->p6 = $values['p6'];
$this->p7 = $values['p7'];
$this->p8 = $values['p8'];
$this->p9 = $values['p9'];
$this->p10 = $values['p10'];
};
foreach ($objs as $x => $obj) {
$objProxy = $proxy->bindTo($obj, 'Foo');
$objProxy(array(
'p1' => $x . ' ==== aaaaaaaaaaaaaaaaaaaaaaa',
'p2' => $x . ' ==== bbbbbbbbbbbbbbbbbbbbbbb',
'p3' => $x . ' ==== ccccccccccccccccccccccc',
'p4' => $x . ' ==== ddddddddddddddddddddddd',
'p5' => $x . ' ==== eeeeeeeeeeeeeeeeeeeeeee',
'p6' => $x . ' ==== fffffffffffffffffffffff',
'p7' => $x . ' ==== ggggggggggggggggggggggg',
'p8' => $x . ' ==== hhhhhhhhhhhhhhhhhhhhhhh',
'p9' => $x . ' ==== iiiiiiiiiiiiiiiiiiiiiii',
'p10' => $x . ' ==== jjjjjjjjjjjjjjjjjjjjjjj',
)
);
}
echo PHP_EOL . 'By Closure Proxy ' . memory_get_peak_usage() . PHP_EOL;
<?php
$objs = include 'object-array.php';
foreach ($objs as $x => $obj) {
$obj->setP1($x . ' ==== aaaaaaaaaaaaaaaaaaaaaaa');
$obj->setP2($x . ' ==== bbbbbbbbbbbbbbbbbbbbbbb');
$obj->setP3($x . ' ==== ccccccccccccccccccccccc');
$obj->setP4($x . ' ==== ddddddddddddddddddddddd');
$obj->setP5($x . ' ==== eeeeeeeeeeeeeeeeeeeeeee');
$obj->setP6($x . ' ==== fffffffffffffffffffffff');
$obj->setP7($x . ' ==== ggggggggggggggggggggggg');
$obj->setP8($x . ' ==== hhhhhhhhhhhhhhhhhhhhhhh');
$obj->setP9($x . ' ==== iiiiiiiiiiiiiiiiiiiiiii');
$obj->setP10($x . ' ==== jjjjjjjjjjjjjjjjjjjjjjj');
}
echo PHP_EOL . 'By Method: ' . memory_get_peak_usage() . PHP_EOL;
<?php
$objs = include 'object-array.php';
class FooProxy extends Foo {
public function setValues(array $values, Foo $foo) {
$foo->p1 = $values['p1'];
$foo->p2 = $values['p2'];
$foo->p3 = $values['p3'];
$foo->p4 = $values['p4'];
$foo->p5 = $values['p5'];
$foo->p6 = $values['p6'];
$foo->p7 = $values['p7'];
$foo->p8 = $values['p8'];
$foo->p9 = $values['p9'];
$foo->p10 = $values['p10'];
}
}
$fooProxy = new FooProxy;
foreach ($objs as $x => $obj) {
$fooProxy->setValues(array(
'p1' => $x . ' ==== aaaaaaaaaaaaaaaaaaaaaaa',
'p2' => $x . ' ==== bbbbbbbbbbbbbbbbbbbbbbb',
'p3' => $x . ' ==== ccccccccccccccccccccccc',
'p4' => $x . ' ==== ddddddddddddddddddddddd',
'p5' => $x . ' ==== eeeeeeeeeeeeeeeeeeeeeee',
'p6' => $x . ' ==== fffffffffffffffffffffff',
'p7' => $x . ' ==== ggggggggggggggggggggggg',
'p8' => $x . ' ==== hhhhhhhhhhhhhhhhhhhhhhh',
'p9' => $x . ' ==== iiiiiiiiiiiiiiiiiiiiiii',
'p10' => $x . ' ==== jjjjjjjjjjjjjjjjjjjjjjj',
),
$obj
);
}
echo PHP_EOL . 'By Proxy ' . memory_get_peak_usage() . PHP_EOL;
<?php
$objs = include 'object-array.php';
$ref = new ReflectionClass('Foo');
$props = $ref->getProperties();
foreach ($props as $index => $prop) {
$props[$prop->getName()] = $prop;
$prop->setAccessible(true);
unset($props[$index]);
}
foreach ($objs as $x => $obj) {
$props['p1']->setValue($obj, $x . ' ==== aaaaaaaaaaaaaaaaaaaaaaa');
$props['p2']->setValue($obj, $x . ' ==== bbbbbbbbbbbbbbbbbbbbbbb');
$props['p3']->setValue($obj, $x . ' ==== ccccccccccccccccccccccc');
$props['p4']->setValue($obj, $x . ' ==== ddddddddddddddddddddddd');
$props['p5']->setValue($obj, $x . ' ==== eeeeeeeeeeeeeeeeeeeeeee');
$props['p6']->setValue($obj, $x . ' ==== fffffffffffffffffffffff');
$props['p7']->setValue($obj, $x . ' ==== ggggggggggggggggggggggg');
$props['p8']->setValue($obj, $x . ' ==== hhhhhhhhhhhhhhhhhhhhhhh');
$props['p9']->setValue($obj, $x . ' ==== iiiiiiiiiiiiiiiiiiiiiii');
$props['p10']->setValue($obj, $x . ' ==== jjjjjjjjjjjjjjjjjjjjjjj');
}
echo PHP_EOL . 'By Reflection ' . memory_get_peak_usage() . PHP_EOL;
<?php
class Foo {
protected $p1;
public function setP1($p1) { $this->p1 = $p1; }
protected $p2;
public function setP2($p2) { $this->p2 = $p2; }
protected $p3;
public function setP3($p3) { $this->p3 = $p3; }
protected $p4;
public function setP4($p4) { $this->p4 = $p4; }
protected $p5;
public function setP5($p5) { $this->p5 = $p5; }
protected $p6;
public function setP6($p6) { $this->p6 = $p6; }
protected $p7;
public function setP7($p7) { $this->p7 = $p7; }
protected $p8;
public function setP8($p8) { $this->p8 = $p8; }
protected $p9;
public function setP9($p9) { $this->p9 = $p9; }
protected $p10;
public function setP10($p10) { $this->p10 = $p10; }
}
$objs = array();
for ($i = 0; $i <= 70000; $i++) {
$objs[$i] = new Foo;
}
return $objs;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment