Skip to content

Commit

Permalink
Merge pull request #10532 from sj-i/improve-memory-usage
Browse files Browse the repository at this point in the history
Reduce memory consumption of caching and parallel processing without igbinary
  • Loading branch information
orklah committed Jan 8, 2024
2 parents afc2df4 + 1a3bba3 commit 8e577c8
Show file tree
Hide file tree
Showing 17 changed files with 131 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/Psalm/Aliases.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

namespace Psalm;

use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait;

final class Aliases
{
use UnserializeMemoryUsageSuppressionTrait;

/**
* @var array<lowercase-string, string>
*/
Expand Down
39 changes: 39 additions & 0 deletions src/Psalm/CodeLocation.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,32 @@ class CodeLocation
public const CATCH_VAR = 6;
public const FUNCTION_PHPDOC_METHOD = 7;

private const PROPERTY_KEYS_FOR_UNSERIALIZE = [
'file_path' => 'file_path',
'file_name' => 'file_name',
'raw_line_number' => 'raw_line_number',
"\0" . self::class . "\0" . 'end_line_number' => 'end_line_number',
'raw_file_start' => 'raw_file_start',
'raw_file_end' => 'raw_file_end',
"\0*\0" . 'file_start' => 'file_start',
"\0*\0" . 'file_end' => 'file_end',
"\0*\0" . 'single_line' => 'single_line',
"\0*\0" . 'preview_start' => 'preview_start',
"\0" . self::class . "\0" . 'preview_end' => 'preview_end',
"\0" . self::class . "\0" . 'selection_start' => 'selection_start',
"\0" . self::class . "\0" . 'selection_end' => 'selection_end',
"\0" . self::class . "\0" . 'column_from' => 'column_from',
"\0" . self::class . "\0" . 'column_to' => 'column_to',
"\0" . self::class . "\0" . 'snippet' => 'snippet',
"\0" . self::class . "\0" . 'text' => 'text',
'docblock_start' => 'docblock_start',
"\0" . self::class . "\0" . 'docblock_start_line_number' => 'docblock_start_line_number',
"\0*\0" . 'docblock_line_number' => 'docblock_line_number',
"\0" . self::class . "\0" . 'regex_type' => 'regex_type',
"\0" . self::class . "\0" . 'have_recalculated' => 'have_recalculated',
'previous_location' => 'previous_location',
];

public function __construct(
FileSource $file_source,
PhpParser\Node $stmt,
Expand Down Expand Up @@ -136,6 +162,19 @@ public function __construct(
$this->docblock_line_number = $comment_line;
}

/**
* Suppresses memory usage when unserializing objects.
*
* @see \Psalm\Storage\UnserializeMemoryUsageSuppressionTrait
*/
public function __unserialize(array $properties): void
{
foreach (self::PROPERTY_KEYS_FOR_UNSERIALIZE as $key => $property_name) {
/** @psalm-suppress PossiblyUndefinedStringArrayOffset */
$this->$property_name = $properties[$key];
}
}

/**
* @psalm-suppress PossiblyUnusedMethod Part of public API
* @return static
Expand Down
2 changes: 2 additions & 0 deletions src/Psalm/Internal/MethodIdentifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use InvalidArgumentException;
use Psalm\Storage\ImmutableNonCloneableTrait;
use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait;

use function explode;
use function is_string;
Expand All @@ -18,6 +19,7 @@
final class MethodIdentifier
{
use ImmutableNonCloneableTrait;
use UnserializeMemoryUsageSuppressionTrait;

public string $fq_class_name;
/** @var lowercase-string */
Expand Down
1 change: 1 addition & 0 deletions src/Psalm/Storage/Assertion.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
abstract class Assertion
{
use ImmutableNonCloneableTrait;
use UnserializeMemoryUsageSuppressionTrait;

abstract public function getNegation(): Assertion;

Expand Down
1 change: 1 addition & 0 deletions src/Psalm/Storage/AttributeArg.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
final class AttributeArg
{
use ImmutableNonCloneableTrait;
use UnserializeMemoryUsageSuppressionTrait;
/**
* @var ?string
* @psalm-suppress PossiblyUnusedProperty It's part of the public API for now
Expand Down
1 change: 1 addition & 0 deletions src/Psalm/Storage/AttributeStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
final class AttributeStorage
{
use ImmutableNonCloneableTrait;
use UnserializeMemoryUsageSuppressionTrait;
/**
* @var string
*/
Expand Down
1 change: 1 addition & 0 deletions src/Psalm/Storage/ClassConstantStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ final class ClassConstantStorage
/** @psalm-suppress MutableDependency Mutable by design */
use CustomMetadataTrait;
use ImmutableNonCloneableTrait;
use UnserializeMemoryUsageSuppressionTrait;

public ?CodeLocation $type_location;

Expand Down
1 change: 1 addition & 0 deletions src/Psalm/Storage/ClassLikeStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
final class ClassLikeStorage implements HasAttributesInterface
{
use CustomMetadataTrait;
use UnserializeMemoryUsageSuppressionTrait;

/**
* @var array<string, ClassConstantStorage>
Expand Down
2 changes: 2 additions & 0 deletions src/Psalm/Storage/EnumCaseStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

final class EnumCaseStorage
{
use UnserializeMemoryUsageSuppressionTrait;

/**
* @var int|string|null
*/
Expand Down
1 change: 1 addition & 0 deletions src/Psalm/Storage/FileStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
final class FileStorage
{
use CustomMetadataTrait;
use UnserializeMemoryUsageSuppressionTrait;

/**
* @var array<lowercase-string, string>
Expand Down
1 change: 1 addition & 0 deletions src/Psalm/Storage/FunctionLikeParameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
final class FunctionLikeParameter implements HasAttributesInterface, TypeNode
{
use CustomMetadataTrait;
use UnserializeMemoryUsageSuppressionTrait;

/**
* @var string
Expand Down
1 change: 1 addition & 0 deletions src/Psalm/Storage/FunctionLikeStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
abstract class FunctionLikeStorage implements HasAttributesInterface
{
use CustomMetadataTrait;
use UnserializeMemoryUsageSuppressionTrait;

/**
* @var CodeLocation|null
Expand Down
2 changes: 2 additions & 0 deletions src/Psalm/Storage/Possibilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

final class Possibilities
{
use UnserializeMemoryUsageSuppressionTrait;

/**
* @var list<Assertion> the rule being asserted
*/
Expand Down
1 change: 1 addition & 0 deletions src/Psalm/Storage/PropertyStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
final class PropertyStorage implements HasAttributesInterface
{
use CustomMetadataTrait;
use UnserializeMemoryUsageSuppressionTrait;

/**
* @var ?bool
Expand Down
24 changes: 24 additions & 0 deletions src/Psalm/Storage/UnserializeMemoryUsageSuppressionTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Psalm\Storage;

/**
* Suppresses memory usage when unserializing objects.
*
* Workaround for the problem that objects retrieved with `\unserialize()`
* build unnecessary dynamic property tables, resulting in larger memory
* consumption.
*
* @see https://github.com/php/php-src/issues/10126
* @psalm-immutable
*/
trait UnserializeMemoryUsageSuppressionTrait
{
public function __unserialize(array $properties): void
{
/** @psalm-suppress MixedAssignment */
foreach ($properties as $key => $value) {
$this->$key = $value;
}
}
}
3 changes: 3 additions & 0 deletions src/Psalm/Type/Atomic.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Psalm\Internal\Type\TypeAlias;
use Psalm\Internal\Type\TypeAlias\LinkableTypeAlias;
use Psalm\Internal\TypeVisitor\ClasslikeReplacer;
use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait;
use Psalm\Type;
use Psalm\Type\Atomic\TArray;
use Psalm\Type\Atomic\TArrayKey;
Expand Down Expand Up @@ -82,6 +83,8 @@
*/
abstract class Atomic implements TypeNode
{
use UnserializeMemoryUsageSuppressionTrait;

public function __construct(bool $from_docblock = false)
{
$this->from_docblock = $from_docblock;
Expand Down
46 changes: 46 additions & 0 deletions src/Psalm/Type/Union.php
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,52 @@ final class Union implements TypeNode
*/
public $different = false;

private const PROPERTY_KEYS_FOR_UNSERIALIZE = [
"\0" . self::class . "\0" . 'types' => 'types',
'from_docblock' => 'from_docblock',
'from_calculation' => 'from_calculation',
'from_property' => 'from_property',
'from_static_property' => 'from_static_property',
'initialized' => 'initialized',
'initialized_class' => 'initialized_class',
'checked' => 'checked',
'failed_reconciliation' => 'failed_reconciliation',
'ignore_nullable_issues' => 'ignore_nullable_issues',
'ignore_falsable_issues' => 'ignore_falsable_issues',
'ignore_isset' => 'ignore_isset',
'possibly_undefined' => 'possibly_undefined',
'possibly_undefined_from_try' => 'possibly_undefined_from_try',
'explicit_never' => 'explicit_never',
'had_template' => 'had_template',
'from_template_default' => 'from_template_default',
"\0" . self::class . "\0" . 'literal_string_types' => 'literal_string_types',
"\0" . self::class . "\0" . 'typed_class_strings' => 'typed_class_strings',
"\0" . self::class . "\0" . 'literal_int_types' => 'literal_int_types',
"\0" . self::class . "\0" . 'literal_float_types' => 'literal_float_types',
'by_ref' => 'by_ref',
'reference_free' => 'reference_free',
'allow_mutations' => 'allow_mutations',
'has_mutations' => 'has_mutations',
"\0" . self::class . "\0" . 'id' => 'id',
"\0" . self::class . "\0" . 'exact_id' => 'exact_id',
'parent_nodes' => 'parent_nodes',
'propagate_parent_nodes' => 'propagate_parent_nodes',
'different' => 'different',
];

/**
* Suppresses memory usage when unserializing objects.
*
* @see \Psalm\Storage\UnserializeMemoryUsageSuppressionTrait
*/
public function __unserialize(array $properties): void
{
foreach (self::PROPERTY_KEYS_FOR_UNSERIALIZE as $key => $property_name) {
/** @psalm-suppress PossiblyUndefinedStringArrayOffset */
$this->$property_name = $properties[$key];
}
}

/**
* @param TProperties $properties
* @return static
Expand Down

0 comments on commit 8e577c8

Please sign in to comment.