Skip to content

Commit

Permalink
Merge pull request #9889 from dkarlovi/feat/cache.gz
Browse files Browse the repository at this point in the history
feat: cache.gz
  • Loading branch information
orklah committed Jun 12, 2023
2 parents b9f5c05 + 8d11974 commit 715a91d
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 859 deletions.
8 changes: 8 additions & 0 deletions src/Psalm/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
use function file_get_contents;
use function flock;
use function fopen;
use function function_exists;
use function get_class;
use function get_defined_constants;
use function get_defined_functions;
Expand Down Expand Up @@ -331,6 +332,9 @@ class Config
/** @var bool */
public $use_igbinary = false;

/** @var bool */
public $use_gzip = true;

/**
* @var bool
*/
Expand Down Expand Up @@ -1192,6 +1196,10 @@ private static function fromXmlAndPaths(
$config->use_igbinary = version_compare($igbinary_version, '2.0.5') >= 0;
}

if ($config->use_gzip) {
$config->use_gzip = function_exists('gzinflate');
}

if (!isset($config_xml['findUnusedBaselineEntry'])) {
$config->config_warnings[] = '"findUnusedBaselineEntry" will be defaulted to "true" in Psalm 6.'
. ' You should explicitly enable or disable this setting.';
Expand Down
92 changes: 92 additions & 0 deletions src/Psalm/Internal/Cache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

namespace Psalm\Internal;

use Psalm\Config;
use Psalm\Internal\Provider\Providers;

use function file_exists;
use function file_put_contents;
use function gzdeflate;
use function gzinflate;
use function igbinary_serialize;
use function igbinary_unserialize;
use function serialize;
use function unlink;
use function unserialize;

use const LOCK_EX;

/**
* @internal
*/
class Cache
{
private Config $config;

public bool $use_igbinary;

public function __construct(Config $config)
{
$this->config = $config;
$this->use_igbinary = $config->use_igbinary;
}

/**
* @return array|object|string|null
*/
public function getItem(string $path)
{
if (!file_exists($path)) {
return null;
}

$cache = Providers::safeFileGetContents($path);
if ($this->config->use_gzip) {
$inflated = @gzinflate($cache);
if ($inflated !== false) {
$cache = $inflated;
}
}

if ($this->config->use_igbinary) {
/** @var object|false $unserialized */
$unserialized = igbinary_unserialize($cache);
} else {
/** @var object|false $unserialized */
$unserialized = @unserialize($cache);
}

return $unserialized !== false ? $unserialized : null;
}

public function deleteItem(string $path): void
{
if (file_exists($path)) {
unlink($path);
}
}

/**
* @param array|object|string $item
*/
public function saveItem(string $path, $item): void
{
if ($this->config->use_igbinary) {
$serialized = igbinary_serialize($item);
} else {
$serialized = serialize($item);
}

if ($this->config->use_gzip) {
$serialized = gzdeflate($serialized);
}

file_put_contents($path, $serialized, LOCK_EX);
}

public function getCacheDirectory(): ?string
{
return $this->config->getCacheDirectory();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class FileReferenceCacheProvider extends InternalFileReferenceCacheProvider

public function __construct(Config $config)
{
$this->config = $config;
parent::__construct($config);
}

public function getCachedFileReferences(): ?array
Expand Down
49 changes: 10 additions & 39 deletions src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,40 @@
namespace Psalm\Internal\Provider;

use Psalm\Config;
use Psalm\Internal\Cache;
use Psalm\Storage\ClassLikeStorage;
use RuntimeException;
use UnexpectedValueException;

use function array_merge;
use function dirname;
use function file_exists;
use function file_put_contents;
use function filemtime;
use function get_class;
use function hash;
use function igbinary_serialize;
use function igbinary_unserialize;
use function is_dir;
use function is_null;
use function mkdir;
use function serialize;
use function strtolower;
use function unlink;
use function unserialize;

use const DIRECTORY_SEPARATOR;
use const LOCK_EX;
use const PHP_VERSION_ID;

/**
* @internal
*/
class ClassLikeStorageCacheProvider
{
private Config $config;
private Cache $cache;

private string $modified_timestamps = '';

private const CLASS_CACHE_DIRECTORY = 'class_cache';

public function __construct(Config $config)
{
$this->config = $config;
$this->cache = new Cache($config);

$storage_dir = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'Storage' . DIRECTORY_SEPARATOR;

Expand All @@ -64,7 +59,7 @@ public function __construct(Config $config)
$this->modified_timestamps .= ' ' . filemtime($dependent_file_path);
}

$this->modified_timestamps .= $this->config->computeHash();
$this->modified_timestamps .= $config->computeHash();
}

public function writeToCache(ClassLikeStorage $storage, string $file_path, string $file_contents): void
Expand All @@ -80,11 +75,7 @@ public function writeToCache(ClassLikeStorage $storage, string $file_path, strin
}

$cache_location = $this->getCacheLocationForClass($fq_classlike_name_lc, $file_path, true);
if ($this->config->use_igbinary) {
file_put_contents($cache_location, igbinary_serialize($storage), LOCK_EX);
} else {
file_put_contents($cache_location, serialize($storage), LOCK_EX);
}
$this->cache->saveItem($cache_location, $storage);
}

public function getLatestFromCache(
Expand Down Expand Up @@ -118,31 +109,11 @@ private function getCacheHash(?string $_unused_file_path, ?string $file_contents
return PHP_VERSION_ID >= 8_01_00 ? hash('xxh128', $data) : hash('md4', $data);
}

/**
* @psalm-suppress MixedAssignment
*/
private function loadFromCache(string $fq_classlike_name_lc, ?string $file_path): ?ClassLikeStorage
{
$cache_location = $this->getCacheLocationForClass($fq_classlike_name_lc, $file_path);

if (file_exists($cache_location)) {
if ($this->config->use_igbinary) {
$storage = igbinary_unserialize(Providers::safeFileGetContents($cache_location));

if ($storage instanceof ClassLikeStorage) {
return $storage;
}

return null;
}

$storage = unserialize(Providers::safeFileGetContents($cache_location));

if ($storage instanceof ClassLikeStorage) {
return $storage;
}

return null;
$storage = $this->cache->getItem($this->getCacheLocationForClass($fq_classlike_name_lc, $file_path));
if ($storage instanceof ClassLikeStorage) {
return $storage;
}

return null;
Expand All @@ -153,7 +124,7 @@ private function getCacheLocationForClass(
?string $file_path,
bool $create_directory = false
): string {
$root_cache_directory = $this->config->getCacheDirectory();
$root_cache_directory = $this->cache->getCacheDirectory();

if (!$root_cache_directory) {
throw new UnexpectedValueException('No cache directory defined');
Expand Down Expand Up @@ -186,6 +157,6 @@ private function getCacheLocationForClass(
return $parser_cache_directory
. DIRECTORY_SEPARATOR
. $file_path_sha
. ($this->config->use_igbinary ? '-igbinary' : '');
. ($this->cache->use_igbinary ? '-igbinary' : '');
}
}

0 comments on commit 715a91d

Please sign in to comment.