1 //===-- compute_size_class_config.cpp -------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
21 size_t measureWastage(const std::vector
<Alloc
> &allocs
,
22 const std::vector
<size_t> &classes
, size_t pageSize
,
24 size_t totalWastage
= 0;
25 for (auto &a
: allocs
) {
26 size_t sizePlusHeader
= a
.size
+ headerSize
;
27 size_t wastage
= -1ull;
28 for (auto c
: classes
)
29 if (c
>= sizePlusHeader
&& c
- sizePlusHeader
< wastage
)
30 wastage
= c
- sizePlusHeader
;
33 if (wastage
> 2 * pageSize
)
34 wastage
= 2 * pageSize
;
35 totalWastage
+= wastage
* a
.count
;
40 void readAllocs(std::vector
<Alloc
> &allocs
, const char *path
) {
41 FILE *f
= fopen(path
, "r");
43 fprintf(stderr
, "compute_size_class_config: could not open %s: %s\n", path
,
48 const char header
[] = "<malloc version=\"scudo-1\">\n";
49 char buf
[sizeof(header
) - 1];
50 if (fread(buf
, 1, sizeof(header
) - 1, f
) != sizeof(header
) - 1 ||
51 memcmp(buf
, header
, sizeof(header
) - 1) != 0) {
52 fprintf(stderr
, "compute_size_class_config: invalid input format\n");
57 while (fscanf(f
, "<alloc size=\"%zu\" count=\"%zu\"/>\n", &a
.size
,
63 size_t log2Floor(size_t x
) { return sizeof(long) * 8 - 1 - __builtin_clzl(x
); }
67 "usage: compute_size_class_config [-p pageSize] [-c largestClass] "
68 "[-h headerSize] [-n numClasses] [-b numBits] profile...\n");
72 int main(int argc
, char **argv
) {
73 size_t pageSize
= 4096;
74 size_t largestClass
= 65552;
75 size_t headerSize
= 16;
76 size_t numClasses
= 32;
79 std::vector
<Alloc
> allocs
;
80 for (size_t i
= 1; i
!= argc
;) {
81 auto matchArg
= [&](size_t &arg
, const char *name
) {
82 if (strcmp(argv
[i
], name
) == 0) {
84 arg
= atoi(argv
[i
+ 1]);
93 if (matchArg(pageSize
, "-p") || matchArg(largestClass
, "-c") ||
94 matchArg(headerSize
, "-h") || matchArg(numClasses
, "-n") ||
95 matchArg(numBits
, "-b"))
97 readAllocs(allocs
, argv
[i
]);
104 std::vector
<size_t> classes
;
105 classes
.push_back(largestClass
);
106 for (size_t i
= 1; i
!= numClasses
; ++i
) {
107 size_t minWastage
= -1ull;
108 size_t minWastageClass
;
109 for (size_t newClass
= 16; newClass
!= largestClass
; newClass
+= 16) {
110 // Skip classes with more than numBits bits, ignoring leading or trailing
112 if (__builtin_ctzl(newClass
- headerSize
) +
113 __builtin_clzl(newClass
- headerSize
) <
114 sizeof(long) * 8 - numBits
)
117 classes
.push_back(newClass
);
118 size_t newWastage
= measureWastage(allocs
, classes
, pageSize
, headerSize
);
120 if (newWastage
< minWastage
) {
121 minWastage
= newWastage
;
122 minWastageClass
= newClass
;
125 classes
.push_back(minWastageClass
);
128 std::sort(classes
.begin(), classes
.end());
129 size_t minSizeLog
= log2Floor(headerSize
);
130 size_t midSizeIndex
= 0;
131 while (classes
[midSizeIndex
+ 1] - classes
[midSizeIndex
] == (1 << minSizeLog
))
133 size_t midSizeLog
= log2Floor(classes
[midSizeIndex
] - headerSize
);
134 size_t maxSizeLog
= log2Floor(classes
.back() - headerSize
- 1) + 1;
136 printf(R
"(// wastage = %zu
138 struct MySizeClassConfig {
139 static const uptr NumBits = %zu;
140 static const uptr MinSizeLog = %zu;
141 static const uptr MidSizeLog = %zu;
142 static const uptr MaxSizeLog = %zu;
143 static const u16 MaxNumCachedHint = 14;
144 static const uptr MaxBytesCachedLog = 14;
146 static constexpr u32 Classes[] = {)",
147 measureWastage(allocs
, classes
, pageSize
, headerSize
), numBits
,
148 minSizeLog
, midSizeLog
, maxSizeLog
);
149 for (size_t i
= 0; i
!= classes
.size(); ++i
) {
154 printf("0x%05zx,", classes
[i
]);
158 static const uptr SizeDelta = %zu;