29 static uint16_t SystemHugepageSizesCntPerNodeGet(uint16_t node_index);
30 static uint16_t SystemNodeCountGet(
void);
31 static void SystemHugepagePerNodeGetHugepageSizes(
32 uint16_t node_index, uint16_t hp_sizes_cnt, uint32_t *hp_sizes);
33 static HugepageInfo *SystemHugepageHugepageInfoCreate(uint16_t hp_size_cnt);
34 static int16_t SystemHugepagePerNodeGetHugepageInfo(uint16_t node_index,
NodeInfo *node);
35 static void SystemHugepageHugepageInfoDestroy(
HugepageInfo *h);
36 static void SystemHugepageNodeInfoDestroy(
NodeInfo *n);
37 static void SystemHugepageNodeInfoDump(
NodeInfo *n);
55 static bool SystemHugepageSupported(
void)
57 return SystemHugepageDetermineOS() !=
OS_UNKNOWN;
64 static uint16_t SystemNodeCountGetLinux(
void)
66 char dir_path[] =
"/sys/devices/system/node/";
67 DIR *dir = opendir(dir_path);
73 while ((entry = readdir(dir)) != NULL) {
74 char d_name[] =
"node";
87 static uint16_t SystemHugepageSizesCntPerNodeGetLinux(uint16_t node_index)
90 snprintf(dir_path,
sizeof(dir_path),
"/sys/devices/system/node/node%d/hugepages/", node_index);
91 DIR *dir = opendir(dir_path);
99 while ((entry = readdir(dir)) != NULL) {
100 char d_name[] =
"hugepages-";
115 static void SystemHugepagePerNodeGetHugepageSizesLinux(
116 uint16_t node_index, uint16_t hp_sizes_cnt, uint32_t *hp_sizes)
119 snprintf(dir_path,
sizeof(dir_path),
"/sys/devices/system/node/node%d/hugepages/", node_index);
120 DIR *dir = opendir(dir_path);
125 struct dirent *entry;
126 while ((entry = readdir(dir)) != NULL) {
128 sscanf(entry->d_name,
"hugepages-%ukB", &(hp_sizes[index]));
144 static int16_t SystemHugepagePerNodeGetHugepageInfoLinux(
145 HugepageInfo *hugepages, uint32_t *hp_sizes, uint16_t hp_sizes_cnt, uint16_t node_index)
147 for (int16_t i = 0; i < hp_sizes_cnt; i++) {
148 hugepages[i].
size_kb = hp_sizes[i];
150 snprintf(path,
sizeof(path),
151 "/sys/devices/system/node/node%hu/hugepages/hugepages-%ukB/nr_hugepages",
152 node_index, hp_sizes[i]);
153 FILE *f = fopen(path,
"r");
158 if (fscanf(f,
"%hu", &hugepages[i].allocated) != 1) {
159 SCLogInfo(
"failed to read the total number of allocated hugepages (%ukB) on node %hu",
160 hp_sizes[i], node_index);
166 snprintf(path,
sizeof(path),
167 "/sys/devices/system/node/node%hu/hugepages/hugepages-%ukB/free_hugepages",
168 node_index, hp_sizes[i]);
169 f = fopen(path,
"r");
174 if (fscanf(f,
"%hu", &hugepages[i].free) != 1) {
175 SCLogInfo(
"failed to read the total number of free hugepages (%ukB) on node %hu",
176 hp_sizes[i], node_index);
192 static int16_t SystemHugepagePerNodeGetHugepageInfo(uint16_t node_index,
NodeInfo *node)
194 uint16_t hp_sizes_cnt = SystemHugepageSizesCntPerNodeGet(node_index);
195 if (hp_sizes_cnt == 0) {
196 SCLogInfo(
"hugepages not found for node %d", node_index);
199 uint32_t *hp_sizes =
SCCalloc(hp_sizes_cnt,
sizeof(*hp_sizes));
200 if (hp_sizes == NULL) {
201 FatalError(
"failed to allocate memory for hugepage info");
203 SystemHugepagePerNodeGetHugepageSizes(node_index, hp_sizes_cnt, hp_sizes);
205 node->
hugepages = SystemHugepageHugepageInfoCreate(hp_sizes_cnt);
210 ret = SystemHugepagePerNodeGetHugepageInfoLinux(
221 static uint16_t SystemNodeCountGet(
void)
224 return SystemNodeCountGetLinux();
232 static uint16_t SystemHugepageSizesCntPerNodeGet(uint16_t node_index)
235 return SystemHugepageSizesCntPerNodeGetLinux(node_index);
246 static void SystemHugepagePerNodeGetHugepageSizes(
247 uint16_t node_index, uint16_t hp_sizes_cnt, uint32_t *hp_sizes)
250 SystemHugepagePerNodeGetHugepageSizesLinux(node_index, hp_sizes_cnt, hp_sizes);
253 static HugepageInfo *SystemHugepageHugepageInfoCreate(uint16_t hp_size_cnt)
257 FatalError(
"failed to allocate hugepage info array");
262 static void SystemHugepageHugepageInfoDestroy(
HugepageInfo *h)
268 static void SystemHugepageNodeInfoDestroy(
NodeInfo *n)
273 SystemHugepageHugepageInfoDestroy(n->
hugepages);
276 static void SystemHugepageNodeInfoDump(
NodeInfo *n)
296 for (uint16_t i = 0; i < s->
num_nodes; i++) {
298 SystemHugepageNodeInfoDump(&(s->
nodes[i]));
307 for (uint16_t i = 0; i < s->
num_nodes; i++) {
308 SystemHugepageNodeInfoDestroy(&(s->
nodes[i]));
323 if (!SystemHugepageSupported())
326 uint16_t node_cnt = SystemNodeCountGet();
328 SCLogInfo(
"hugepage snapshot failed - cannot obtain number of NUMA nodes in the system");
333 FatalError(
"failed to allocate memory for NUMA node info");
339 FatalError(
"failed to allocate memory for NUMA node snapshot");
344 for (uint16_t i = 0; i < s->
num_nodes; i++) {
345 int16_t ret = SystemHugepagePerNodeGetHugepageInfo(i, &s->
nodes[i]);
363 if (!SystemHugepageSupported() || pre_s == NULL || post_s == NULL)
366 SCLogDebug(
"Hugepages before initialization");
367 SystemHugepageSnapshotDump(pre_s);
370 SystemHugepageSnapshotDump(post_s);
373 FatalError(
"Number of NUMA nodes changed during hugepage evaluation");
375 for (int32_t i = 0; i < post_s->
num_nodes; i++) {
377 FatalError(
"Number of NUMA node hugepage sizes changed during hugepage evaluation");
383 if (prerun_hp->
free == 0) {
385 }
else if (prerun_hp->
free < postrun_hp->
free) {
387 "Hugepage usage decreased while it should only increase/stay the same");
388 }
else if (prerun_hp->
free > 0 && prerun_hp->
free == postrun_hp->
free) {
389 SCLogPerf(
"%ukB hugepages on NUMA node %u are unused and can be deallocated",
395 if (postrun_hp->
size_kb == 2048 && postrun_hp->
free == 0) {
396 SCLogPerf(
"all %ukB hugepages used on NUMA node %d - consider increasing to "
397 "prevent memory allocation from other NUMA nodes",
401 float free_hugepages_ratio = (float)postrun_hp->
free / (
float)prerun_hp->
free;
402 if (free_hugepages_ratio > 0.5) {
403 int32_t used_hps = prerun_hp->
free - postrun_hp->
free;
404 SCLogPerf(
"Hugepages on NUMA node %u can be set to %.0lf (only using %u/%u "
406 i, ceil((prerun_hp->
free - postrun_hp->
free) * 1.15), used_hps,