RegionAnalyzer::analyze()   F
last analyzed

Complexity

Conditions 18
Paths 1600

Size

Total Lines 115
Code Lines 85

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 18
eloc 85
nc 1600
nop 1
dl 0
loc 115
rs 0.7
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file is part of the reliforp/reli-prof package.
5
 *
6
 * (c) sji <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Reli\Lib\PhpProcessReader\PhpMemoryReader\RegionAnalyzer;
15
16
use Reli\Lib\PhpProcessReader\PhpMemoryReader\MemoryLocation\MemoryLocations;
17
use Reli\Lib\PhpProcessReader\PhpMemoryReader\MemoryLocation\ZendArrayMemoryLocation;
18
use Reli\Lib\PhpProcessReader\PhpMemoryReader\MemoryLocation\ZendArrayTableMemoryLocation;
19
use Reli\Lib\PhpProcessReader\PhpMemoryReader\MemoryLocation\ZendArrayTableOverheadMemoryLocation;
20
use Reli\Lib\PhpProcessReader\PhpMemoryReader\MemoryLocation\ZendClassEntryMemoryLocation;
21
use Reli\Lib\PhpProcessReader\PhpMemoryReader\MemoryLocation\ZendMmChunkMemoryLocation;
22
use Reli\Lib\PhpProcessReader\PhpMemoryReader\MemoryLocation\ZendObjectMemoryLocation;
23
use Reli\Lib\PhpProcessReader\PhpMemoryReader\MemoryLocation\ZendOpArrayHeaderMemoryLocation;
24
use Reli\Lib\PhpProcessReader\PhpMemoryReader\RegionAnalyzer\Result\RegionalMemoryLocations;
25
use Reli\Lib\PhpProcessReader\PhpMemoryReader\RegionAnalyzer\Result\RegionAnalyzerResult;
26
use Reli\Lib\PhpProcessReader\PhpMemoryReader\RegionAnalyzer\Result\RegionsSummary;
27
use Reli\Lib\Process\MemoryLocation;
28
29
final class RegionAnalyzer
30
{
31
    public function __construct(
32
        private MemoryLocations $chunk_memory_locations,
33
        private MemoryLocations $huge_memory_locations,
34
        private MemoryLocations $vm_stack_memory_locations,
35
        private MemoryLocations $compiler_arena_memory_locations,
36
    ) {
37
    }
38
39
    public function analyze(MemoryLocations $memory_locations): RegionAnalyzerResult
40
    {
41
        $heap_memory_total = 0;
42
        $huge_memory_total = 0;
43
        $heap_memory_usage = 0;
44
        $huge_memory_usage = 0;
45
        $vm_stack_memory_total = 0;
46
        $compiler_arena_memory_total = 0;
47
        $vm_stack_memory_usage = 0;
48
        $compiler_arena_memory_usage = 0;
49
        $possible_allocation_overhead_total = 0;
50
        $possible_array_overhead_total = 0;
51
        $per_class_objects = [];
52
53
        $regional_memory_locations = RegionalMemoryLocations::createDefault();
54
55
        foreach ($this->chunk_memory_locations->memory_locations as $memory_location) {
56
            $heap_memory_total += $memory_location->size;
57
        }
58
59
        foreach ($this->huge_memory_locations->memory_locations as $memory_location) {
60
            $huge_memory_total += $memory_location->size;
61
        }
62
63
        foreach ($this->vm_stack_memory_locations->memory_locations as $vm_stack_memory_location) {
64
            $vm_stack_memory_total += $vm_stack_memory_location->size;
65
            $chunk = $this->chunk_memory_locations->getContainingMemoryLocation($vm_stack_memory_location);
66
            if (!is_null($chunk)) {
67
                assert($chunk instanceof ZendMmChunkMemoryLocation);
68
                $overhead = $chunk->getOverhead($vm_stack_memory_location);
69
                if (!is_null($overhead)) {
70
                    $possible_allocation_overhead_total += $overhead->size;
71
                }
72
            }
73
        }
74
75
        foreach ($this->compiler_arena_memory_locations->memory_locations as $memory_location) {
76
            $compiler_arena_memory_total += $memory_location->size;
77
            $chunk = $this->chunk_memory_locations->getContainingMemoryLocation($memory_location);
78
            if (!is_null($chunk)) {
79
                assert($chunk instanceof ZendMmChunkMemoryLocation);
80
                $overhead = $chunk->getOverhead($memory_location);
81
                if (!is_null($overhead)) {
82
                    $possible_allocation_overhead_total += $overhead->size;
83
                }
84
            }
85
        }
86
87
        $filtered_locations = $this->filterOverlappingLocations($memory_locations);
88
89
        foreach ($filtered_locations as $memory_location) {
90
            $chunk = $this->chunk_memory_locations->getContainingMemoryLocation($memory_location);
91
            if (!is_null($chunk)) {
92
                if ($this->vm_stack_memory_locations->contains($memory_location)) {
93
                    $vm_stack_memory_usage += $memory_location->size;
94
                    $regional_memory_locations->locations_in_vm_stack->add($memory_location);
95
                } elseif ($this->compiler_arena_memory_locations->contains($memory_location)) {
96
                    $compiler_arena_memory_usage += $memory_location->size;
97
                    $regional_memory_locations->locations_in_compiler_arena->add($memory_location);
98
                } else {
99
                    $heap_memory_usage += $memory_location->size;
100
                    assert($chunk instanceof ZendMmChunkMemoryLocation);
101
                    if (!$memory_location instanceof ZendArrayTableMemoryLocation) {
102
                        $overhead = $chunk->getOverhead($memory_location);
103
                        if (!is_null($overhead)) {
104
                            $possible_allocation_overhead_total += $overhead->size;
105
                        }
106
                    }
107
                }
108
                $regional_memory_locations->locations_in_zend_mm_heap->add($memory_location);
109
                if ($memory_location instanceof ZendObjectMemoryLocation) {
110
                    $per_class_objects[$memory_location->class_name] ??= [
111
                        'count' => 0,
112
                        'total_size' => 0,
113
                    ];
114
                    $per_class_objects[$memory_location->class_name]['count']++;
115
                    $per_class_objects[$memory_location->class_name]['total_size'] += $memory_location->size;
116
                }
117
            } elseif ($this->huge_memory_locations->contains($memory_location)) {
118
                $huge_memory_usage += $memory_location->size;
119
                $regional_memory_locations->locations_in_zend_mm_heap->add($memory_location);
120
            } else {
121
                $regional_memory_locations->locations_outside_of_zend_mm_heap->add($memory_location);
122
            }
123
            if ($memory_location instanceof ZendArrayTableOverheadMemoryLocation) {
124
                $possible_array_overhead_total += $memory_location->size;
125
            }
126
        }
127
128
        uasort(
129
            $per_class_objects,
130
            fn (array $a, array $b) => $b['total_size'] <=> $a['total_size']
131
        );
132
133
        $heap_memory_usage += $possible_allocation_overhead_total;
134
        $heap_memory_usage += $vm_stack_memory_total;
135
        $heap_memory_usage += $compiler_arena_memory_total;
136
137
        $summary = new RegionsSummary(
138
            $heap_memory_total + $huge_memory_total,
139
            $heap_memory_usage + $huge_memory_usage,
140
            $heap_memory_total,
141
            $heap_memory_usage,
142
            $huge_memory_total,
143
            $huge_memory_usage,
144
            $vm_stack_memory_total,
145
            $vm_stack_memory_usage,
146
            $compiler_arena_memory_total,
147
            $compiler_arena_memory_usage,
148
            $possible_allocation_overhead_total,
149
            $possible_array_overhead_total,
150
        );
151
        return new RegionAnalyzerResult(
152
            $summary,
153
            $regional_memory_locations,
154
        );
155
    }
156
157
    /** @return array<MemoryLocation> */
158
    private function filterOverlappingLocations(MemoryLocations $memory_locations): array
159
    {
160
        $locations = $memory_locations->memory_locations;
161
162
        usort($locations, function (MemoryLocation $a, MemoryLocation $b) {
163
            return $a->address <=> $b->address;
164
        });
165
166
        $filtered_locations = [];
167
        foreach ($locations as $location) {
168
            $last_key = array_key_last($filtered_locations);
169
            if (is_null($last_key)) {
170
                $filtered_locations[] = $location;
171
                continue;
172
            }
173
            $filtered_last = $filtered_locations[$last_key];
174
            if (empty($filtered_locations) || $location->address >= ($filtered_last->address + $filtered_last->size)) {
175
                $filtered_locations[] = $location;
176
            } elseif (
177
                $filtered_last instanceof ZendClassEntryMemoryLocation
178
                and $location instanceof ZendArrayMemoryLocation
179
            ) {
180
                continue;
181
            } elseif (
182
                $filtered_last instanceof ZendArrayTableOverheadMemoryLocation
183
            ) {
184
                $filtered_locations[$last_key] = $location;
185
            } elseif (
186
                $filtered_last instanceof ZendObjectMemoryLocation
187
                and $location instanceof ZendOpArrayHeaderMemoryLocation
188
                and $filtered_last->class_name === \Closure::class
189
            ) {
190
                continue;
191
            } else {
192
//                var_dump([$filtered_last, $location]);
193
            }
194
        }
195
196
        return $filtered_locations;
197
    }
198
}
199