Skip to content

Commit

Permalink
decided to make the cache only non-static
Browse files Browse the repository at this point in the history
  • Loading branch information
Sairahcaz committed Nov 20, 2022
1 parent 9a9ee65 commit e763408
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 66 deletions.
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

This package provides you with a simple PHP trait, which adds [memoization](https://en.wikipedia.org/wiki/Memoization) to your classes! It's inspired by spaties once package, but it is up to **100% faster**!

Note: As this is a trait it only runs in class contexts and not statically.

## Installation

``` bash
Expand Down Expand Up @@ -44,21 +46,20 @@ The `memoize` method will only run **once per combination** of `use` variables t
For lower php versions, it will run **once per combination** of argument values the ***containing method*** receives.

```php
class MyClass
$myClass = new class()
{
/**
* It also works in static context!
*/
public static function getNumberForLetter($letter)
use HasMemoization;

public function getNumberForLetter($letter)
{
return self::memoize(function () use ($letter) {
return $this->memoize(function () use ($letter) {
return $letter . rand(1, 10000000);
});
}
}
```

So calling `MyClass::getNumberForLetter('A')` will always return the same result, but calling `MyClass::getNumberForLetter('B')` will return something else.
So calling `$myClass->getNumberForLetter('A')` will always return the same result, but calling `$myClass->getNumberForLetter('B')` will return something else.

As described above, spaties once package uses the arguments of the ***containing method*** for the **once per combination** idea.
We think this feels a bit unintuitive and in certain circumstances will affect performance. So we use the `use` variables of the closure as the **once per combination** key. As a fallback for php8.0 and lower or if you like/need to, we also let you fully self define your **once per combination** key in a second optional parameter of the closure.
Expand Down
30 changes: 15 additions & 15 deletions src/HasMemoization.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,41 @@ trait HasMemoization
*
* @var array
*/
protected static $memoizationCache = [];
protected $memoizationCache = [];

/**
* specifies if memoization should be applied
*
* @var bool
*/
protected static $memoizationEnabled = true;
protected $memoizationEnabled = true;

/**
* @return void
*/
public static function enableMemoization()
public function enableMemoization()
{
self::$memoizationEnabled = true;
$this->memoizationEnabled = true;
}

/**
* @return void
*/
public static function disableMemoization()
public function disableMemoization()
{
self::$memoizationEnabled = false;
$this->memoizationEnabled = false;
}

/**
* @return bool
*/
public static function isEnabledMemoization(): bool
public function isEnabledMemoization(): bool
{
if (isset($_ENV['MEMOIZATION_GLOBALLY_DISABLED'])) {
return $_ENV['MEMOIZATION_GLOBALLY_DISABLED'];
}

return self::$memoizationEnabled;
return $this->memoizationEnabled;
}

/**
Expand All @@ -52,9 +52,9 @@ public static function isEnabledMemoization(): bool
* @return array|mixed
* @throws \ReflectionException
*/
public static function memoize(callable $callback, array $customCombiArgs = [])
public function memoize(callable $callback, array $customCombiArgs = [])
{
if (!self::isEnabledMemoization()) {
if (!$this->isEnabledMemoization()) {
return $callback();
}

Expand All @@ -75,16 +75,16 @@ public static function memoize(callable $callback, array $customCombiArgs = [])
$combiArgs = $customCombiArgs;
}

$hash = self::getMemoCacheHash($combiArgs, $prefix);
$hash = $this->getMemoCacheHash($combiArgs, $prefix);

if (!array_key_exists($hash, self::$memoizationCache)) {
self::$memoizationCache[$hash] = $callback();
if (!array_key_exists($hash, $this->memoizationCache)) {
$this->memoizationCache[$hash] = $callback();
}

return self::$memoizationCache[$hash];
return $this->memoizationCache[$hash];
}

private static function getMemoCacheHash(array $arguments, string $prefix): string
private function getMemoCacheHash(array $arguments, string $prefix): string
{
$normalizedArguments = array_map(function ($argument) {
return is_object($argument) ? spl_object_hash($argument) : $argument;
Expand Down
48 changes: 4 additions & 44 deletions tests/MemoTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,29 +102,6 @@ public function getNull()
expect($testClass->getRandomNumber())->toBe($firstNumber);
});

it('will run callback once on static method', function () {
$object = new class() {
use HasMemoization;

public static function getNumber()
{
return self::memoize(function () {
return rand(1, 10000000);
});
}
};
$class = get_class($object);

$firstResult = $class::getNumber();

expect($firstResult)->toBeGreaterThanOrEqual(1);
expect($firstResult)->toBeLessThanOrEqual(10000000);

foreach (range(1, 100) as $i) {
expect($class::getNumber())->toBe($firstResult);
}
});

it('can enable and disable the cache', function () {
$testClass = new class() {
use HasMemoization;
Expand All @@ -137,15 +114,15 @@ public function getNumber()
}
};

expect($testClass::isEnabledMemoization())->toBeTrue();
expect($testClass->isEnabledMemoization())->toBeTrue();
expect($testClass->getNumber())->toBe($testClass->getNumber());

$testClass::disableMemoization();
$testClass->disableMemoization();
expect($testClass->isEnabledMemoization())->toBeFalse();
expect($testClass->getNumber())->not()->toBe($testClass->getNumber());

$testClass::enableMemoization();
expect($testClass::isEnabledMemoization())->toBeTrue();
$testClass->enableMemoization();
expect($testClass->isEnabledMemoization())->toBeTrue();
expect($testClass->getNumber())->toBe($testClass->getNumber());
});
//
Expand Down Expand Up @@ -223,21 +200,4 @@ public function getNumber()

// dump($diff1, $diff2);
expect($diff1)->toBeLessThan($diff2);
});

it('will run statically without class context', function () {
function getNumber() {
return MemoHelper::memoize(function () {
return rand(1, 10000000);
});
}

$firstResult = getNumber();

expect($firstResult)->toBeGreaterThanOrEqual(1);
expect($firstResult)->toBeLessThanOrEqual(10000000);

foreach (range(1, 100) as $i) {
expect(getNumber())->toBe($firstResult);
}
});

0 comments on commit e763408

Please sign in to comment.