@@ -395,6 +395,18 @@ template <typename Config> class SizeClassAllocator64 {
395395 }
396396 }
397397
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+
398410 bool setOption (Option O, sptr Value) {
399411 if (O == Option::ReleaseInterval) {
400412 const s32 Interval = Max (
@@ -1193,6 +1205,50 @@ template <typename Config> class SizeClassAllocator64 {
11931205 AllocatedPagesCount, InUseBytes >> 10 , Integral, Fractional);
11941206 }
11951207
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+
11961252 NOINLINE uptr releaseToOSMaybe (RegionInfo *Region, uptr ClassId,
11971253 ReleaseToOS ReleaseType = ReleaseToOS::Normal)
11981254 REQUIRES(Region->MMLock) EXCLUDES(Region->FLLock) {
0 commit comments