|
6 | 6 |
|
7 | 7 | require_once dirname(__DIR__) . '/vendor/autoload.php'; |
8 | 8 |
|
9 | | -use Tests\Enum; |
10 | | -use Tests\DataTransferObjects\Basic; |
11 | | -use Tests\DataTransferObjects\Advanced; |
| 9 | +use ReallifeKip\ImmutableBase\Attributes\ArrayOf; |
| 10 | +use ReallifeKip\ImmutableBase\Objects\DataTransferObject; |
12 | 11 |
|
13 | | -final class defaultBench |
| 12 | +/** @BeforeMethods({"setUp"}) */ |
| 13 | +class defaultBench |
14 | 14 | { |
15 | | - private array $nullableData; |
16 | | - private array $basicData; |
17 | | - private array $advancedDataByArray; |
18 | | - private array $advancedDataByInstance; |
19 | | - private array $modifyBasicData; |
20 | | - private array $modifyAdvancedDataByArray; |
21 | | - private array $modifyAdvancedDataByInstance; |
22 | | - public function __construct() |
23 | | - { |
24 | | - $this->nullableData = [ |
25 | | - 'nullable_str' => null, |
26 | | - 'nullable_int' => null, |
27 | | - 'nullable_array' => null, |
28 | | - 'nullable_object' => null, |
29 | | - 'nullable_float' => null, |
30 | | - 'nullable_bool' => null, |
31 | | - 'nullable_enum' => null |
32 | | - ]; |
33 | | - $this->basicData = [ |
34 | | - 'string' => 'string', |
35 | | - 'int' => 1, |
36 | | - 'array' => [1,2,3], |
37 | | - 'object' => (object)[1,2,3], |
38 | | - 'float' => 1.1, |
39 | | - 'bool' => true, |
40 | | - 'enum' => Enum::ONE |
41 | | - ] + $this->nullableData; |
42 | | - $this->advancedDataByArray = $this->basicData + [ |
43 | | - 'basic' => $this->basicData, |
44 | | - 'arrayOfBasics' => [ |
45 | | - $this->basicData, |
46 | | - $this->basicData |
47 | | - ], |
48 | | - 'union' => 'string', |
49 | | - 'unionNullable' => 'string', |
50 | | - ]; |
51 | | - $this->advancedDataByInstance = $this->basicData + [ |
52 | | - 'basic' => new Basic($this->basicData), |
53 | | - 'arrayOfBasics' => [ |
54 | | - new Basic($this->basicData), |
55 | | - new Basic($this->basicData) |
56 | | - ], |
57 | | - 'union' => 'string', |
58 | | - 'unionNullable' => 'string', |
| 15 | + private array $simpleData; |
| 16 | + private array $nestedData; |
| 17 | + private array $collectionData_100; |
| 18 | + private array $collectionData_1000; |
| 19 | + private array $recursiveData_10; |
| 20 | + private array $recursiveData_50; |
| 21 | + private string $jsonString; |
| 22 | + |
| 23 | + public function setUp(): void |
| 24 | + { |
| 25 | + $this->simpleData = [ |
| 26 | + 'name' => 'Kip', |
| 27 | + 'age' => 30, |
| 28 | + 'active' => true, |
| 29 | + 'score' => 99.5 |
59 | 30 | ]; |
60 | | - $this->modifyBasicData = [ |
61 | | - 'string' => 'string_', |
62 | | - 'int' => 2, |
63 | | - 'array' => [4,5,6], |
64 | | - 'object' => (object)[4,5,6], |
65 | | - 'float' => 2.2, |
66 | | - 'bool' => false, |
67 | | - 'enum' => Enum::TWO, |
68 | | - 'nullable_str' => 'string_', |
69 | | - 'nullable_int' => 2, |
70 | | - 'nullable_array' => [1,2,3], |
71 | | - 'nullable_object' => (object)[1,2,3], |
72 | | - 'nullable_float' => 2.2, |
73 | | - 'nullable_bool' => false, |
74 | | - 'nullable_enum' => Enum::TWO, |
| 31 | + |
| 32 | + $this->nestedData = [ |
| 33 | + 'simple' => $this->simpleData, |
| 34 | + 'type' => 'A' |
75 | 35 | ]; |
76 | | - $this->modifyAdvancedDataByArray = $this->modifyBasicData + [ |
77 | | - 'basic' => $this->modifyBasicData, |
78 | | - 'arrayOfBasics' => [ |
79 | | - $this->modifyBasicData, |
80 | | - $this->modifyBasicData |
81 | | - ], |
82 | | - 'union' => 123, |
83 | | - 'unionNullable' => null |
| 36 | + $this->collectionData_100 = [ |
| 37 | + 'list' => array_fill(0, 100, $this->simpleData) |
84 | 38 | ]; |
85 | | - $this->modifyAdvancedDataByInstance = $this->modifyBasicData + [ |
86 | | - 'basic' => new Basic($this->modifyBasicData), |
87 | | - 'arrayOfBasics' => [ |
88 | | - new Basic($this->modifyBasicData), |
89 | | - new Basic($this->modifyBasicData) |
90 | | - ], |
91 | | - 'union' => 123, |
92 | | - 'unionNullable' => null |
| 39 | + $this->collectionData_1000 = [ |
| 40 | + 'list' => array_fill(0, 1000, $this->simpleData) |
93 | 41 | ]; |
94 | | - } |
95 | | - |
96 | | - /** |
97 | | - * 建立給定深度的深層巢狀 Advanced 陣列結構(用於測試深層建構與遞迴處理)。 |
98 | | - */ |
99 | | - private function buildDeepArray(int $depth = 5): array |
100 | | - { |
101 | | - $base = $this->basicData; |
102 | | - $base['basic'] = $this->basicData; |
103 | | - $base['arrayOfBasics'] = [$this->basicData]; |
104 | | - $base['union'] = 'string'; |
105 | | - $base['unionNullable'] = 'string'; |
106 | | - |
107 | | - $current = $base; |
108 | | - for ($i = 1; $i < $depth; $i++) { |
109 | | - $current = $this->basicData; |
110 | | - $current['basic'] = $current; |
111 | | - $current['arrayOfBasics'] = [$current]; |
112 | | - $current['union'] = 'string'; |
113 | | - $current['unionNullable'] = 'string'; |
| 42 | + $this->recursiveData_10 = $this->buildRecursiveData(10); |
| 43 | + $this->recursiveData_50 = $this->buildRecursiveData(50); |
| 44 | + $this->jsonString = json_encode($this->simpleData); |
| 45 | + } |
| 46 | + private function buildRecursiveData(int $depth): array |
| 47 | + { |
| 48 | + $current = null; |
| 49 | + for ($i = $depth; $i > 0; $i--) { |
| 50 | + $current = [ |
| 51 | + 'id' => $i, |
| 52 | + 'child' => $current |
| 53 | + ]; |
114 | 54 | } |
115 | | - |
116 | 55 | return $current; |
117 | 56 | } |
118 | | - |
119 | | - /** |
120 | | - * 建立給定深度的深層巢狀 Advanced 實例結構(由底層陣列遞迴轉換為 Advanced 實例)。 |
121 | | - */ |
122 | | - private function buildDeepInstance(int $depth = 5): Advanced |
| 57 | + public function benchGentleSimpleFromArray(): void |
123 | 58 | { |
124 | | - $base = $this->basicData; |
125 | | - $base['basic'] = $this->basicData; |
126 | | - $base['arrayOfBasics'] = [$this->basicData]; |
127 | | - $base['union'] = 'string'; |
128 | | - $base['unionNullable'] = 'string'; |
129 | | - |
130 | | - $current = $base; |
131 | | - for ($i = 1; $i < $depth; $i++) { |
132 | | - $current = $this->basicData; |
133 | | - $current['arrayOfBasics'] = [$current]; |
134 | | - $current['basic'] = $current instanceof Basic ? $current : $current; |
135 | | - $current['union'] = 'string'; |
136 | | - $current['unionNullable'] = 'string'; |
137 | | - } |
138 | | - |
139 | | - $convert = function ($node) use (&$convert) { |
140 | | - if (is_array($node) && isset($node['basic'])) { |
141 | | - $node['basic'] = $convert($node['basic']); |
142 | | - if (is_array($node['arrayOfBasics'])) { |
143 | | - $node['arrayOfBasics'] = array_map($convert, $node['arrayOfBasics']); |
144 | | - } |
145 | | - return new Advanced($node); |
146 | | - } |
147 | | - return $node; |
148 | | - }; |
149 | | - |
150 | | - return $convert($current); |
| 59 | + SimpleDTO::fromArray($this->simpleData); |
151 | 60 | } |
152 | | - |
153 | | - /** |
154 | | - * 從深層陣列(深度 5)建立 Advanced,測量深層建構的成本與行為。 |
155 | | - */ |
156 | | - public function benchConstructDeepAdvancedFromArray(): void |
| 61 | + public function benchGentleSimpleFromJson(): void |
157 | 62 | { |
158 | | - $deep = $this->buildDeepArray(5); |
159 | | - new Advanced($deep); |
| 63 | + SimpleDTO::fromJson($this->jsonString); |
160 | 64 | } |
161 | | - |
162 | | - /** |
163 | | - * 從深層實例建立 Advanced(先生成深層實例再由其陣列重建),用以測量實例->陣列->重建 的成本。 |
164 | | - */ |
165 | | - public function benchConstructDeepAdvancedFromInstance(): void |
| 65 | + public function benchModerateNested(): void |
166 | 66 | { |
167 | | - $deep = $this->buildDeepInstance(); |
168 | | - new Advanced($deep->toArray()); |
| 67 | + NestedDTO::fromArray($this->nestedData); |
169 | 68 | } |
170 | | - |
171 | | - /** |
172 | | - * 深層 Advanced 執行 toArray(),測量遞迴序列化深層巢狀結構的效能與輸出正確性。 |
173 | | - */ |
174 | | - public function benchToArrayDeepAdvanced(): array |
| 69 | + public function benchModerateToArray(): void |
175 | 70 | { |
176 | | - $deep = $this->buildDeepInstance(); |
177 | | - return $deep->toArray(); |
| 71 | + $dto = NestedDTO::fromArray($this->nestedData); |
| 72 | + $dto->toArray(); |
178 | 73 | } |
179 | | - |
180 | | - /** |
181 | | - * 在深層 Advanced 上執行 with(),測量複製與巢狀欄位覆寫在深層結構上的成本。 |
182 | | - */ |
183 | | - public function benchWithDeepAdvanced(): void |
| 74 | + public function benchModerateWith(): void |
184 | 75 | { |
185 | | - $deep = $this->buildDeepInstance(); |
186 | | - $deep->with($deep->toArray()); |
| 76 | + $dto = NestedDTO::fromArray($this->nestedData); |
| 77 | + $dto->with([ |
| 78 | + 'simple' => [ |
| 79 | + 'name' => 'New Name' |
| 80 | + ] |
| 81 | + ]); |
187 | 82 | } |
188 | | - |
189 | | - /** |
190 | | - * 從陣列建立 Basic 的建構效能測試(測量單層 DTO 建構成本)。 |
191 | | - */ |
192 | | - public function benchConstructBasicFromArray(): void |
| 83 | + public function benchViolentCollection_100(): void |
193 | 84 | { |
194 | | - new Basic($this->basicData); |
| 85 | + CollectionDTO::fromArray($this->collectionData_100); |
195 | 86 | } |
196 | | - |
197 | | - /** |
198 | | - * 從巢狀陣列建立 Advanced 的建構效能測試(測量解析巢狀陣列為 DTO 的成本)。 |
199 | | - */ |
200 | | - public function benchConstructAdvancedFromArray(): void |
| 87 | + public function benchViolentCollection_1000(): void |
201 | 88 | { |
202 | | - new Advanced($this->advancedDataByArray); |
| 89 | + CollectionDTO::fromArray($this->collectionData_1000); |
203 | 90 | } |
204 | | - |
205 | | - /** |
206 | | - * 從巢狀實例建立 Advanced 的建構效能測試(測量接受已初始化 instance 的情況)。 |
207 | | - */ |
208 | | - public function benchConstructAdvancedFromInstance(): void |
| 91 | + public function benchHellRecursion_10(): void |
209 | 92 | { |
210 | | - new Advanced($this->advancedDataByInstance); |
| 93 | + RecursiveDTO::fromArray($this->recursiveData_10); |
211 | 94 | } |
212 | | - |
213 | | - /** |
214 | | - * 在 Basic 上呼叫 toArray(),測量單層 DTO 序列化為陣列的成本。 |
215 | | - */ |
216 | | - public function benchToArrayBasic(): array |
| 95 | + public function benchHellRecursion_50(): void |
217 | 96 | { |
218 | | - $basic = new Basic($this->basicData); |
219 | | - return $basic->toArray(); |
| 97 | + RecursiveDTO::fromArray($this->recursiveData_50); |
220 | 98 | } |
221 | | - |
222 | | - /** |
223 | | - * 在由陣列建立的 Advanced 上呼叫 toArray(),測量巢狀 DTO 轉陣列的效能。 |
224 | | - */ |
225 | | - public function benchToArrayAdvancedByArray(): array |
| 99 | + public function benchHellRecursionToArray_50(): void |
226 | 100 | { |
227 | | - $advanced = new Advanced($this->advancedDataByArray); |
228 | | - return $advanced->toArray(); |
| 101 | + $dto = RecursiveDTO::fromArray($this->recursiveData_50); |
| 102 | + $dto->toArray(); |
229 | 103 | } |
| 104 | +} |
| 105 | +enum BenchEnum: string |
| 106 | +{ |
| 107 | + case A = 'A'; |
| 108 | + case B = 'B'; |
| 109 | + case C = 'C'; |
| 110 | +} |
230 | 111 |
|
231 | | - /** |
232 | | - * 在由實例建立的 Advanced 上呼叫 toArray(),測量巢狀實例序列化的效能。 |
233 | | - */ |
234 | | - public function benchToArrayAdvancedByInstance(): array |
235 | | - { |
236 | | - $advanced = new Advanced($this->advancedDataByInstance); |
237 | | - return $advanced->toArray(); |
238 | | - } |
| 112 | +class SimpleDTO extends DataTransferObject |
| 113 | +{ |
| 114 | + public readonly string $name; |
| 115 | + public readonly int $age; |
| 116 | + public readonly bool $active; |
| 117 | + public readonly ?float $score; |
| 118 | +} |
239 | 119 |
|
240 | | - /** |
241 | | - * 在 Basic 上執行 with(),測量建立新 immutable 實例並覆寫單層欄位的成本。 |
242 | | - */ |
243 | | - public function benchWithBasic(): void |
244 | | - { |
245 | | - $basic = new Basic($this->basicData); |
246 | | - $basic->with($this->modifyBasicData); |
247 | | - } |
| 120 | +class NestedDTO extends DataTransferObject |
| 121 | +{ |
| 122 | + public readonly SimpleDTO $simple; |
| 123 | + public readonly BenchEnum $type; |
| 124 | +} |
248 | 125 |
|
249 | | - /** |
250 | | - * 在由陣列建立的 Advanced 上執行 with(),測量巢狀欄位覆寫與新實例建立的成本。 |
251 | | - */ |
252 | | - public function benchWithAdvancedByArray(): void |
253 | | - { |
254 | | - $advanced = new Advanced($this->advancedDataByArray); |
255 | | - $advanced->with($this->modifyAdvancedDataByArray); |
256 | | - } |
| 126 | +class CollectionDTO extends DataTransferObject |
| 127 | +{ |
| 128 | + #[ArrayOf(SimpleDTO::class)] |
| 129 | + public readonly array $list; |
| 130 | +} |
257 | 131 |
|
258 | | - /** |
259 | | - * 在由實例建立的 Advanced 上執行 with(),測量接受巢狀 instance 作為修改來源時的成本。 |
260 | | - */ |
261 | | - public function benchWithAdvancedByInstance(): void |
262 | | - { |
263 | | - $advanced = new Advanced($this->advancedDataByInstance); |
264 | | - $advanced->with($this->modifyAdvancedDataByInstance); |
265 | | - } |
| 132 | +class RecursiveDTO extends DataTransferObject |
| 133 | +{ |
| 134 | + public readonly int $id; |
| 135 | + public readonly ?RecursiveDTO $child; |
266 | 136 | } |
0 commit comments