• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <gtest/gtest.h>
17 #include "libpandabase/utils/utils.h"
18 #include "runtime/mem/gc/g1/g1_analytics.h"
19 #include "runtime/include/runtime_options.h"
20 #include "runtime/include/runtime.h"
21 
22 namespace ark::mem {
23 class G1AnalyticsTest : public testing::Test {
24 public:
G1AnalyticsTest()25     G1AnalyticsTest()
26     {
27         RuntimeOptions options;
28         options.SetHeapSizeLimit(HEAP_SIZE);
29         options.SetShouldLoadBootPandaFiles(false);
30         options.SetShouldInitializeIntrinsics(false);
31         options.SetGcType("epsilon");
32         Runtime::Create(options);
33         for (size_t i = 0; i < ALL_REGIONS_NUM; i++) {
34             regions_.emplace_back(nullptr, 0, 0);
35         }
36     }
37 
~G1AnalyticsTest()38     ~G1AnalyticsTest() override
39     {
40         Runtime::Destroy();
41     }
42 
43     NO_COPY_SEMANTIC(G1AnalyticsTest);
44     NO_MOVE_SEMANTIC(G1AnalyticsTest);
45 
CreateCollectionSet(size_t edenLength,size_t oldLength=0)46     CollectionSet CreateCollectionSet(size_t edenLength, size_t oldLength = 0)
47     {
48         ASSERT(edenLength + oldLength < ALL_REGIONS_NUM);
49         PandaVector<Region *> vector;
50         auto it = regions_.begin();
51         for (size_t i = 0; i < edenLength; ++it, ++i) {
52             vector.push_back(&*it);
53         }
54         auto cs = CollectionSet(vector);
55         for (size_t i = 0; i < oldLength; ++it, ++i) {
56             auto &region = *it;
57             region.AddFlag(RegionFlag::IS_OLD);
58             cs.AddRegion(&region);
59         }
60         return cs;
61     }
62 
63     static constexpr uint64_t START_TIME = 1686312829587000000U;
64 
65 private:
66     static constexpr size_t ALL_REGIONS_NUM = 32;
67     static constexpr size_t HEAP_SIZE = 64_MB;
68     std::list<Region> regions_;
69 };
70 
FillAnalyticsUndefinedBehaviorTest(G1Analytics & analytics,const CollectionSet & collectionSet,uint64_t now)71 static void FillAnalyticsUndefinedBehaviorTest(G1Analytics &analytics, const CollectionSet &collectionSet, uint64_t now)
72 {
73     analytics.ReportCollectionStart(now);
74     {
75         const size_t remsetSize = 100;
76         const size_t remsetRefsCount = 1000;
77         analytics.ReportRemsetSize(remsetSize, remsetRefsCount);
78     }
79     {
80         const uint64_t delta = 200'000;
81         analytics.ReportScanDirtyCardsStart(now + delta);
82     }
83     {
84         const uint64_t delta = 250'000;
85         const size_t dirtyCardsCount = 2;
86         analytics.ReportScanDirtyCardsEnd(now + delta, dirtyCardsCount);
87     }
88     {
89         const uint64_t delta = 1'000'000;
90         analytics.ReportMarkingStart(now + delta);
91     }
92     {
93         const uint64_t delta = 2'000'000;
94         const size_t remsetRefsCount = 10000;
95         analytics.ReportMarkingEnd(now + delta, remsetRefsCount);
96     }
97     {
98         const uint64_t delta = 3'000'000;
99         analytics.ReportEvacuationStart(now + delta);
100     }
101     {
102         const uint64_t delta = 6'000'000;
103         analytics.ReportEvacuationEnd(now + delta);
104         analytics.ReportUpdateRefsStart(now + delta);
105     }
106     {
107         const uint64_t delta = 7'000'000;
108         analytics.ReportUpdateRefsEnd(now + delta);
109     }
110     {
111         const uint64_t delta = 10'000'000;
112         analytics.ReportCollectionEnd(GCTaskCause::YOUNG_GC_CAUSE, now + delta, collectionSet);
113     }
114 }
115 
TEST_F(G1AnalyticsTest,UndefinedBehaviorTest)116 TEST_F(G1AnalyticsTest, UndefinedBehaviorTest)
117 {
118     const size_t edenLength = 16;
119     uint64_t now = START_TIME;
120     const auto startTimeDelta = -20'000'000;
121     auto startTime = now + startTimeDelta;
122     G1Analytics analytics(startTime);
123     ASSERT_EQ(0, analytics.PredictYoungCollectionTimeInMicros(edenLength));
124 
125     auto collectionSet = CreateCollectionSet(edenLength);
126     FillAnalyticsUndefinedBehaviorTest(analytics, collectionSet, now);
127 
128     const uint64_t expectedTime = 7'000;
129     ASSERT_EQ(expectedTime, analytics.PredictYoungCollectionTimeInMicros(edenLength));
130 }
131 
FillAnalyticsPause0AllPromotedUndefinedBehaviorTest(G1Analytics & analytics,const CollectionSet & collectionSet,uint64_t now)132 static void FillAnalyticsPause0AllPromotedUndefinedBehaviorTest(G1Analytics &analytics,
133                                                                 const CollectionSet &collectionSet, uint64_t now)
134 {
135     analytics.ReportCollectionStart(now);
136     {
137         const size_t remsetSize = 100;
138         const size_t remsetRefsCount = 1000;
139         analytics.ReportRemsetSize(remsetSize, remsetRefsCount);
140     }
141     {
142         const uint64_t delta = 200'000;
143         analytics.ReportScanDirtyCardsStart(now + delta);
144     }
145     {
146         const uint64_t delta = 250'000;
147         const size_t dirtyCardsCount = 2;
148         analytics.ReportScanDirtyCardsEnd(now + delta, dirtyCardsCount);
149     }
150     {
151         const uint64_t delta = 1'000'000;
152         analytics.ReportMarkingStart(now + delta);
153     }
154     {
155         const uint64_t delta = 2'000'000;
156         const size_t remsetRefsCount = 12000;
157         analytics.ReportMarkingEnd(now + delta, remsetRefsCount);
158     }
159     {
160         const uint64_t delta = 3'000'000;
161         analytics.ReportEvacuationStart(now + delta);
162     }
163     {
164         const uint64_t delta = 6'000'000;
165         analytics.ReportEvacuationEnd(now + delta);
166         analytics.ReportUpdateRefsStart(now + delta);
167     }
168     {
169         const uint64_t delta = 7'000'000;
170         analytics.ReportUpdateRefsEnd(now + delta);
171     }
172     for (size_t i = 0; i < collectionSet.Young().size(); i++) {
173         analytics.ReportPromotedRegion();
174     }
175     {
176         const uint64_t delta = 10'000'000;
177         analytics.ReportCollectionEnd(GCTaskCause::YOUNG_GC_CAUSE, now + delta, collectionSet);
178     }
179 }
180 
FillAnalyticsPause1AllPromotedUndefinedBehaviorTest(G1Analytics & analytics,const CollectionSet & collectionSet,uint64_t now)181 static void FillAnalyticsPause1AllPromotedUndefinedBehaviorTest(G1Analytics &analytics,
182                                                                 const CollectionSet &collectionSet, uint64_t now)
183 {
184     analytics.ReportCollectionStart(now);
185     {
186         const size_t liveObjects = 32000;
187         analytics.ReportLiveObjects(liveObjects);
188     }
189     {
190         const size_t remsetSize = 100;
191         const size_t remsetRefsCount = 1000;
192         analytics.ReportRemsetSize(remsetSize, remsetRefsCount);
193     }
194     {
195         const uint64_t delta = 200'000;
196         analytics.ReportScanDirtyCardsStart(now + delta);
197     }
198     {
199         const uint64_t delta = 250'000;
200         const size_t dirtyCardsCount = 2;
201         analytics.ReportScanDirtyCardsEnd(now + delta, dirtyCardsCount);
202     }
203     {
204         const uint64_t delta = 1'000'000;
205         analytics.ReportMarkingStart(now + delta);
206     }
207     {
208         const uint64_t delta = 2'000'000;
209         const size_t remsetRefsCount = 11000;
210         analytics.ReportMarkingEnd(now + delta, remsetRefsCount);
211     }
212     {
213         const uint64_t delta = 3'000'000;
214         analytics.ReportEvacuationStart(now + delta);
215     }
216     {
217         const uint64_t delta = 6'000'000;
218         analytics.ReportEvacuationEnd(now + delta);
219         analytics.ReportUpdateRefsStart(now + delta);
220     }
221     {
222         const uint64_t delta = 7'000'000;
223         analytics.ReportUpdateRefsEnd(now + delta);
224     }
225     {
226         const uint64_t delta = 10'000'000;
227         analytics.ReportCollectionEnd(GCTaskCause::YOUNG_GC_CAUSE, now + delta, collectionSet);
228     }
229 }
230 
TEST_F(G1AnalyticsTest,AllPromotedUndefinedBehaviorTest)231 TEST_F(G1AnalyticsTest, AllPromotedUndefinedBehaviorTest)
232 {
233     uint64_t now = START_TIME;
234     const auto startTimeDelta = -20'000'000;
235     auto startTime = now + startTimeDelta;
236     const size_t edenLength = 16;
237     G1Analytics analytics(startTime);
238     ASSERT_EQ(0, analytics.PredictYoungCollectionTimeInMicros(edenLength));
239 
240     auto collectionSet = CreateCollectionSet(edenLength);
241     FillAnalyticsPause0AllPromotedUndefinedBehaviorTest(analytics, collectionSet, now);
242     {
243         const uint64_t expectedTime = 7'800;
244         ASSERT_EQ(expectedTime, analytics.PredictYoungCollectionTimeInMicros(edenLength));
245     }
246 
247     const uint64_t nextPauseDelta = 20'000'000;
248     now += nextPauseDelta;
249 
250     FillAnalyticsPause1AllPromotedUndefinedBehaviorTest(analytics, collectionSet, now);
251 
252     {
253         const uint64_t expectedTime = 7'732;
254         ASSERT_EQ(expectedTime, analytics.PredictYoungCollectionTimeInMicros(edenLength));
255     }
256 }
257 
FillAnalyticsPause0PredictionTest(G1Analytics & analytics,const CollectionSet & collectionSet,uint64_t now)258 static void FillAnalyticsPause0PredictionTest(G1Analytics &analytics, const CollectionSet &collectionSet, uint64_t now)
259 {
260     analytics.ReportCollectionStart(now);
261     {
262         const size_t remsetSize = 100;
263         const size_t remsetRefsCount = 1000;
264         analytics.ReportRemsetSize(remsetSize, remsetRefsCount);
265     }
266     {
267         const uint64_t delta = 200'000;
268         analytics.ReportScanDirtyCardsStart(now + delta);
269     }
270     {
271         const uint64_t delta = 250'000;
272         const size_t dirtyCardsCount = 2;
273         analytics.ReportScanDirtyCardsEnd(now + delta, dirtyCardsCount);
274     }
275     {
276         const uint64_t delta = 1'000'000;
277         analytics.ReportMarkingStart(now + delta);
278     }
279     {
280         const uint64_t delta = 2'000'000;
281         const size_t remsetRefsCount = 12000;
282         analytics.ReportMarkingEnd(now + delta, remsetRefsCount);
283     }
284     {
285         const uint64_t delta = 3'000'000;
286         analytics.ReportEvacuationStart(now + delta);
287     }
288     {
289         const uint64_t delta = 6'000'000;
290         analytics.ReportEvacuationEnd(now + delta);
291         const size_t evacuatedBytes = 2 * 1024 * 1024;
292         analytics.ReportEvacuatedBytes(evacuatedBytes);
293         const size_t liveObjects = 32000;
294         analytics.ReportLiveObjects(liveObjects);
295     }
296     {
297         const uint64_t delta = 6'000'000;
298         analytics.ReportUpdateRefsStart(now + delta);
299     }
300     {
301         const uint64_t delta = 7'000'000;
302         analytics.ReportUpdateRefsEnd(now + delta);
303     }
304     {
305         const uint64_t delta = 10'000'000;
306         analytics.ReportCollectionEnd(GCTaskCause::YOUNG_GC_CAUSE, now + delta, collectionSet);
307     }
308 }
309 
FillAnalyticsPause1PredictionTest(G1Analytics & analytics,const CollectionSet & collectionSet,uint64_t now)310 static void FillAnalyticsPause1PredictionTest(G1Analytics &analytics, const CollectionSet &collectionSet, uint64_t now)
311 {
312     analytics.ReportCollectionStart(now);
313 
314     {
315         const size_t remsetSize = 110;
316         const size_t remsetRefsCount = 1500;
317         analytics.ReportRemsetSize(remsetSize, remsetRefsCount);
318     }
319     {
320         const uint64_t delta = 900'000;
321         analytics.ReportScanDirtyCardsStart(now + delta);
322     }
323     {
324         const uint64_t delta = 950'000;
325         const size_t dirtyCardsCount = 2;
326         analytics.ReportScanDirtyCardsEnd(now + delta, dirtyCardsCount);
327     }
328     {
329         const uint64_t delta = 1'000'000;
330         analytics.ReportMarkingStart(now + delta);
331     }
332     {
333         const uint64_t delta = 2'500'000;
334         const size_t remsetRefsCount = 12000;
335         analytics.ReportMarkingEnd(now + delta, remsetRefsCount);
336     }
337     {
338         const uint64_t delta = 3'000'000;
339         analytics.ReportEvacuationStart(now + delta);
340     }
341     {
342         const uint64_t delta = 6'500'000;
343         analytics.ReportEvacuationEnd(now + delta);
344         const size_t evacuatedBytes = 2 * 1024 * 1024;
345         analytics.ReportEvacuatedBytes(evacuatedBytes);
346         analytics.ReportPromotedRegion();
347         analytics.ReportPromotedRegion();
348         const size_t liveObjects = 30000;
349         analytics.ReportLiveObjects(liveObjects);
350     }
351     {
352         const uint64_t delta = 6'000'000;
353         analytics.ReportUpdateRefsStart(now + delta);
354     }
355     {
356         const uint64_t delta = 7'500'000;
357         analytics.ReportUpdateRefsEnd(now + delta);
358     }
359     const uint64_t delta = 10'000'000;
360     analytics.ReportCollectionEnd(GCTaskCause::YOUNG_GC_CAUSE, now + delta, collectionSet);
361 }
362 
FillAnalyticsPause2PredictionTest(G1Analytics & analytics,const CollectionSet & collectionSet,uint64_t now)363 static void FillAnalyticsPause2PredictionTest(G1Analytics &analytics, const CollectionSet &collectionSet, uint64_t now)
364 {
365     analytics.ReportCollectionStart(now);
366     {
367         const size_t remsetSize = 120;
368         const size_t remsetRefsCount = 1600;
369         analytics.ReportRemsetSize(remsetSize, remsetRefsCount);
370     }
371     {
372         const uint64_t delta = 900'000;
373         analytics.ReportScanDirtyCardsStart(now + delta);
374     }
375     {
376         const uint64_t delta = 950'000;
377         const size_t dirtyCardsCount = 2;
378         analytics.ReportScanDirtyCardsEnd(now + delta, dirtyCardsCount);
379     }
380     {
381         const uint64_t delta = 1'000'000;
382         analytics.ReportMarkingStart(now + delta);
383     }
384     {
385         const uint64_t delta = 3'000'000;
386         const size_t remsetRefsCount = 13000;
387         analytics.ReportMarkingEnd(now + delta, remsetRefsCount);
388     }
389     {
390         const uint64_t delta = 3'000'000;
391         analytics.ReportEvacuationStart(now + delta);
392     }
393     {
394         const uint64_t delta = 7'000'000;
395         analytics.ReportEvacuationEnd(now + delta);
396         const size_t evacuatedBytes = 2 * 1024 * 1024;
397         analytics.ReportEvacuatedBytes(evacuatedBytes);
398         analytics.ReportPromotedRegion();
399         const size_t liveObjects = 33000;
400         analytics.ReportLiveObjects(liveObjects);
401     }
402     {
403         const uint64_t delta = 7'000'000;
404         analytics.ReportUpdateRefsStart(now + delta);
405     }
406     {
407         const uint64_t delta = 8'500'000;
408         analytics.ReportUpdateRefsEnd(now + delta);
409     }
410     const uint64_t delta = 11'000'000;
411     analytics.ReportCollectionEnd(GCTaskCause::YOUNG_GC_CAUSE, now + delta, collectionSet);
412 }
413 
TEST_F(G1AnalyticsTest,PredictionTest)414 TEST_F(G1AnalyticsTest, PredictionTest)
415 {
416     uint64_t now = START_TIME;
417     const auto startTimeDelta = -20'000'000;
418     auto startTime = now + startTimeDelta;
419     G1Analytics analytics(startTime);
420 
421     {
422         const size_t edenLength = 16;
423         auto collectionSet = CreateCollectionSet(edenLength);
424         FillAnalyticsPause0PredictionTest(analytics, collectionSet, now);
425 
426         const size_t expectedTime = 10'000;
427         ASSERT_EQ(expectedTime, analytics.PredictYoungCollectionTimeInMicros(edenLength));
428         const double expectedAllocationRate = 0.0008;
429         const double maxError = 1e-6;
430         ASSERT_NEAR(expectedAllocationRate, analytics.PredictAllocationRate(), maxError);
431     }
432 
433     const uint64_t nextPauseDelta = 20'000'000;
434     now += nextPauseDelta;
435 
436     {
437         const size_t edenLength = 10;
438         auto collectionSet = CreateCollectionSet(edenLength);
439         FillAnalyticsPause1PredictionTest(analytics, collectionSet, now);
440 
441         const uint64_t expectedTime = 9'266;
442         ASSERT_EQ(expectedTime, analytics.PredictYoungCollectionTimeInMicros(edenLength));
443         const double expectedAllocationRate = 0.000905;
444         const double maxError = 1e-6;
445         ASSERT_NEAR(expectedAllocationRate, analytics.PredictAllocationRate(), maxError);
446     }
447 
448     now += nextPauseDelta;
449 
450     const size_t edenLength = 14;
451     const size_t oldLength = 10;
452     auto collectionSet = CreateCollectionSet(edenLength, oldLength);
453     FillAnalyticsPause2PredictionTest(analytics, collectionSet, now);
454 
455     const uint64_t expectedTime = 10'772;
456     ASSERT_EQ(expectedTime, analytics.PredictYoungCollectionTimeInMicros(edenLength));
457     const uint64_t expectedOldTime = 110;
458     const size_t remsetSize = 50;
459     const size_t liveBytes = 64 * 1024;
460     const size_t liveObjects = 100;
461     ASSERT_EQ(expectedOldTime, analytics.PredictOldCollectionTimeInMicros(remsetSize, liveBytes, liveObjects));
462     const double expectedAllocationRate = 0.001151;
463     const double maxError = 1e-6;
464     ASSERT_NEAR(expectedAllocationRate, analytics.PredictAllocationRate(), maxError);
465 }
466 }  // namespace ark::mem
467