@@ -395,6 +395,18 @@ template <typename Config> class SizeClassAllocator64 {
395
395
}
396
396
}
397
397
398
+ void getMemoryGroupFragmentationInfo (ScopedString *Str) {
399
+ Str->append (
400
+ " Fragmentation Stats: SizeClassAllocator64: page size = %zu bytes\n " ,
401
+ getPageSizeCached ());
402
+
403
+ for (uptr I = 1 ; I < NumClasses; I++) {
404
+ RegionInfo *Region = getRegionInfo (I);
405
+ ScopedLock L (Region->MMLock );
406
+ getMemoryGroupFragmentationInfoInRegion (Region, I, Str);
407
+ }
408
+ }
409
+
398
410
bool setOption (Option O, sptr Value) {
399
411
if (O == Option::ReleaseInterval) {
400
412
const s32 Interval = Max (
@@ -1193,6 +1205,50 @@ template <typename Config> class SizeClassAllocator64 {
1193
1205
AllocatedPagesCount, InUseBytes >> 10 , Integral, Fractional);
1194
1206
}
1195
1207
1208
+ void getMemoryGroupFragmentationInfoInRegion (RegionInfo *Region, uptr ClassId,
1209
+ ScopedString *Str)
1210
+ REQUIRES(Region->MMLock) {
1211
+ const uptr BlockSize = getSizeByClassId (ClassId);
1212
+ const uptr AllocatedUserEnd =
1213
+ Region->MemMapInfo .AllocatedUser + Region->RegionBeg ;
1214
+
1215
+ SinglyLinkedList<BatchGroupT> GroupsToRelease;
1216
+ {
1217
+ ScopedLock L (Region->FLLock );
1218
+ GroupsToRelease = Region->FreeListInfo .BlockList ;
1219
+ Region->FreeListInfo .BlockList .clear ();
1220
+ }
1221
+
1222
+ constexpr uptr GroupSize = (1UL << GroupSizeLog);
1223
+ constexpr uptr MaxNumGroups = RegionSize / GroupSize;
1224
+
1225
+ MemoryGroupFragmentationRecorder<GroupSize, MaxNumGroups> Recorder;
1226
+ if (!GroupsToRelease.empty ()) {
1227
+ PageReleaseContext Context =
1228
+ markFreeBlocks (Region, BlockSize, AllocatedUserEnd,
1229
+ getCompactPtrBaseByClassId (ClassId), GroupsToRelease);
1230
+ auto SkipRegion = [](UNUSED uptr RegionIndex) { return false ; };
1231
+ releaseFreeMemoryToOS (Context, Recorder, SkipRegion);
1232
+
1233
+ mergeGroupsToReleaseBack (Region, GroupsToRelease);
1234
+ }
1235
+
1236
+ Str->append (" MemoryGroupFragmentationInfo in Region %zu (%zu)\n " , ClassId,
1237
+ BlockSize);
1238
+
1239
+ const uptr MaxNumGroupsInUse =
1240
+ roundUp (Region->MemMapInfo .AllocatedUser , GroupSize) / GroupSize;
1241
+ for (uptr I = 0 ; I < MaxNumGroupsInUse; ++I) {
1242
+ uptr Integral;
1243
+ uptr Fractional;
1244
+ computePercentage (Recorder.NumPagesInOneGroup -
1245
+ Recorder.getNumFreePages (I),
1246
+ Recorder.NumPagesInOneGroup , &Integral, &Fractional);
1247
+ Str->append (" MemoryGroup #%zu (0x%zx): util: %3zu.%02zu%%\n " , I,
1248
+ Region->RegionBeg + I * GroupSize, Integral, Fractional);
1249
+ }
1250
+ }
1251
+
1196
1252
NOINLINE uptr releaseToOSMaybe (RegionInfo *Region, uptr ClassId,
1197
1253
ReleaseToOS ReleaseType = ReleaseToOS::Normal)
1198
1254
REQUIRES(Region->MMLock) EXCLUDES(Region->FLLock) {
0 commit comments