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)
66 static uint16_t SystemNodeCountGetLinux(
void)
68 char dir_path[] =
"/sys/devices/system/node/";
69 DIR *dir = opendir(dir_path);
75 while ((entry = readdir(dir)) != NULL) {
76 char d_name[] =
"node";
89 static uint16_t SystemHugepageSizesCntPerNodeGetLinux(uint16_t node_index)
92 snprintf(dir_path,
sizeof(dir_path),
"/sys/devices/system/node/node%d/hugepages/", node_index);
93 DIR *dir = opendir(dir_path);
100 struct dirent *entry;
101 while ((entry = readdir(dir)) != NULL) {
102 char d_name[] =
"hugepages-";
117 static void SystemHugepagePerNodeGetHugepageSizesLinux(
118 uint16_t node_index, uint16_t hp_sizes_cnt, uint32_t *hp_sizes)
121 snprintf(dir_path,
sizeof(dir_path),
"/sys/devices/system/node/node%d/hugepages/", node_index);
122 DIR *dir = opendir(dir_path);
127 struct dirent *entry;
128 while ((entry = readdir(dir)) != NULL) {
130 sscanf(entry->d_name,
"hugepages-%ukB", &(hp_sizes[index]));
146 static int16_t SystemHugepagePerNodeGetHugepageInfoLinux(
147 HugepageInfo *hugepages, uint32_t *hp_sizes, uint16_t hp_sizes_cnt, uint16_t node_index)
149 for (int16_t i = 0; i < hp_sizes_cnt; i++) {
150 hugepages[i].
size_kb = hp_sizes[i];
152 snprintf(path,
sizeof(path),
153 "/sys/devices/system/node/node%hu/hugepages/hugepages-%ukB/nr_hugepages",
154 node_index, hp_sizes[i]);
155 FILE *f = fopen(path,
"r");
160 if (fscanf(f,
"%hu", &hugepages[i].allocated) != 1) {
161 SCLogInfo(
"failed to read the total number of allocated hugepages (%ukB) on node %hu",
162 hp_sizes[i], node_index);
168 snprintf(path,
sizeof(path),
169 "/sys/devices/system/node/node%hu/hugepages/hugepages-%ukB/free_hugepages",
170 node_index, hp_sizes[i]);
171 f = fopen(path,
"r");
176 if (fscanf(f,
"%hu", &hugepages[i].free) != 1) {
177 SCLogInfo(
"failed to read the total number of free hugepages (%ukB) on node %hu",
178 hp_sizes[i], node_index);
194 static int16_t SystemHugepagePerNodeGetHugepageInfo(uint16_t node_index,
NodeInfo *node)
196 uint16_t hp_sizes_cnt = SystemHugepageSizesCntPerNodeGet(node_index);
197 if (hp_sizes_cnt == 0) {
198 SCLogInfo(
"hugepages not found for node %d", node_index);
201 uint32_t *hp_sizes =
SCCalloc(hp_sizes_cnt,
sizeof(*hp_sizes));
202 if (hp_sizes == NULL) {
203 FatalError(
"failed to allocate memory for hugepage info");
205 SystemHugepagePerNodeGetHugepageSizes(node_index, hp_sizes_cnt, hp_sizes);
207 node->
hugepages = SystemHugepageHugepageInfoCreate(hp_sizes_cnt);
212 ret = SystemHugepagePerNodeGetHugepageInfoLinux(
223 static uint16_t SystemNodeCountGet(
void)
226 return SystemNodeCountGetLinux();
234 static uint16_t SystemHugepageSizesCntPerNodeGet(uint16_t node_index)
237 return SystemHugepageSizesCntPerNodeGetLinux(node_index);
248 static void SystemHugepagePerNodeGetHugepageSizes(
249 uint16_t node_index, uint16_t hp_sizes_cnt, uint32_t *hp_sizes)
252 SystemHugepagePerNodeGetHugepageSizesLinux(node_index, hp_sizes_cnt, hp_sizes);
255 static HugepageInfo *SystemHugepageHugepageInfoCreate(uint16_t hp_size_cnt)
259 FatalError(
"failed to allocate hugepage info array");
264 static void SystemHugepageHugepageInfoDestroy(
HugepageInfo *h)
270 static void SystemHugepageNodeInfoDestroy(
NodeInfo *n)
275 SystemHugepageHugepageInfoDestroy(n->
hugepages);
278 static void SystemHugepageNodeInfoDump(
NodeInfo *n)
298 for (uint16_t i = 0; i < s->
num_nodes; i++) {
300 SystemHugepageNodeInfoDump(&(s->
nodes[i]));
309 for (uint16_t i = 0; i < s->
num_nodes; i++) {
310 SystemHugepageNodeInfoDestroy(&(s->
nodes[i]));
325 if (!SystemHugepageSupported())
328 uint16_t node_cnt = SystemNodeCountGet();
330 SCLogInfo(
"hugepage snapshot failed - cannot obtain number of NUMA nodes in the system");
335 FatalError(
"failed to allocate memory for NUMA node info");
341 FatalError(
"failed to allocate memory for NUMA node snapshot");
346 for (uint16_t i = 0; i < s->
num_nodes; i++) {
347 int16_t ret = SystemHugepagePerNodeGetHugepageInfo(i, &s->
nodes[i]);
365 if (!SystemHugepageSupported() || pre_s == NULL || post_s == NULL)
368 SCLogDebug(
"Hugepages before initialization");
369 SystemHugepageSnapshotDump(pre_s);
372 SystemHugepageSnapshotDump(post_s);
375 FatalError(
"Number of NUMA nodes changed during hugepage evaluation");
377 for (int32_t i = 0; i < post_s->
num_nodes; i++) {
379 FatalError(
"Number of NUMA node hugepage sizes changed during hugepage evaluation");
385 if (prerun_hp->
free == 0) {
387 }
else if (prerun_hp->
free < postrun_hp->
free) {
389 "Hugepage usage decreased while it should only increase/stay the same");
390 }
else if (prerun_hp->
free > 0 && prerun_hp->
free == postrun_hp->
free) {
391 SCLogPerf(
"%ukB hugepages on NUMA node %u are unused and can be deallocated",
397 if (postrun_hp->
size_kb == 2048 && postrun_hp->
free == 0) {
398 SCLogPerf(
"all %ukB hugepages used on NUMA node %d - consider increasing to "
399 "prevent memory allocation from other NUMA nodes",
403 float free_hugepages_ratio = (float)postrun_hp->
free / (
float)prerun_hp->
free;
404 if (free_hugepages_ratio > 0.5) {
405 int32_t used_hps = prerun_hp->
free - postrun_hp->
free;
406 SCLogPerf(
"Hugepages on NUMA node %u can be set to %.0lf (only using %u/%u "
408 i, ceil((prerun_hp->
free - postrun_hp->
free) * 1.15), used_hps,