Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce memory consumption of caching and parallel processing without igbinary #10532

Merged
merged 1 commit into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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