If we have a lot of huge pages in system, the memory init will
cost long time in legacy-mem mode. For example, we have 120G memory
in unit of 2MB hugepage, the env init will cost 43s. Almost half
of time spent on find_numasocket, since the address in
/proc/self/numa_maps is orderd, we can sort hugepg_tbl by orig_va
first and then just read numa_maps line by line is enough to find
socket. In my test, spent time reduced to 19s.

Signed-off-by: Fengnan Chang <changfeng...@bytedance.com>
---
 lib/eal/linux/eal_memory.c | 115 +++++++++++++++++++++++--------------
 1 file changed, 72 insertions(+), 43 deletions(-)

diff --git a/lib/eal/linux/eal_memory.c b/lib/eal/linux/eal_memory.c
index 45879ca743..28cc136ac0 100644
--- a/lib/eal/linux/eal_memory.c
+++ b/lib/eal/linux/eal_memory.c
@@ -414,7 +414,7 @@ map_all_hugepages(struct hugepage_file *hugepg_tbl, struct 
hugepage_info *hpi,
 static int
 find_numasocket(struct hugepage_file *hugepg_tbl, struct hugepage_info *hpi)
 {
-       int socket_id;
+       int socket_id = -1;
        char *end, *nodestr;
        unsigned i, hp_count = 0;
        uint64_t virt_addr;
@@ -432,54 +432,61 @@ find_numasocket(struct hugepage_file *hugepg_tbl, struct 
hugepage_info *hpi)
        snprintf(hugedir_str, sizeof(hugedir_str),
                        "%s/%s", hpi->hugedir, eal_get_hugefile_prefix());
 
-       /* parse numa map */
-       while (fgets(buf, sizeof(buf), f) != NULL) {
-
-               /* ignore non huge page */
-               if (strstr(buf, " huge ") == NULL &&
+       /* if we find this page in our mappings, set socket_id */
+       for (i = 0; i < hpi->num_pages[0]; i++) {
+               void *va = NULL;
+               /* parse numa map */
+               while (fgets(buf, sizeof(buf), f) != NULL) {
+                       if (strstr(buf, " huge ") == NULL &&
                                strstr(buf, hugedir_str) == NULL)
-                       continue;
-
-               /* get zone addr */
-               virt_addr = strtoull(buf, &end, 16);
-               if (virt_addr == 0 || end == buf) {
-                       EAL_LOG(ERR, "%s(): error in numa_maps parsing", 
__func__);
-                       goto error;
-               }
+                               continue;
+                       /* get zone addr */
+                       virt_addr = strtoull(buf, &end, 16);
+                       if (virt_addr == 0 || end == buf) {
+                               EAL_LOG(ERR, "error in numa_maps parsing");
+                               goto error;
+                       }
 
-               /* get node id (socket id) */
-               nodestr = strstr(buf, " N");
-               if (nodestr == NULL) {
-                       EAL_LOG(ERR, "%s(): error in numa_maps parsing", 
__func__);
-                       goto error;
-               }
-               nodestr += 2;
-               end = strstr(nodestr, "=");
-               if (end == NULL) {
-                       EAL_LOG(ERR, "%s(): error in numa_maps parsing", 
__func__);
-                       goto error;
-               }
-               end[0] = '\0';
-               end = NULL;
+                       /* get node id (socket id) */
+                       nodestr = strstr(buf, " N");
+                       if (nodestr == NULL) {
+                               EAL_LOG(ERR, "error in numa_maps parsing");
+                               goto error;
+                       }
+                       nodestr += 2;
+                       end = strstr(nodestr, "=");
+                       if (end == NULL) {
+                               EAL_LOG(ERR, "error in numa_maps parsing");
+                               goto error;
+                       }
+                       end[0] = '\0';
+                       end = NULL;
 
-               socket_id = strtoul(nodestr, &end, 0);
-               if ((nodestr[0] == '\0') || (end == NULL) || (*end != '\0')) {
-                       EAL_LOG(ERR, "%s(): error in numa_maps parsing", 
__func__);
-                       goto error;
+                       socket_id = strtoul(nodestr, &end, 0);
+                       if ((nodestr[0] == '\0') || (end == NULL) || (*end != 
'\0')) {
+                               EAL_LOG(ERR, "error in numa_maps parsing");
+                               goto error;
+                       }
+                       va = (void *)(unsigned long)virt_addr;
+                       if (hugepg_tbl[i].orig_va != va) {
+                               EAL_LOG(DEBUG, "search %p not seq, let's start 
from begin",
+                                       hugepg_tbl[i].orig_va);
+                               fseek(f, 0, SEEK_SET);
+                       } else {
+                               break;
+                       }
                }
-
-               /* if we find this page in our mappings, set socket_id */
-               for (i = 0; i < hpi->num_pages[0]; i++) {
-                       void *va = (void *)(unsigned long)virt_addr;
-                       if (hugepg_tbl[i].orig_va == va) {
-                               hugepg_tbl[i].socket_id = socket_id;
-                               hp_count++;
+               if (hugepg_tbl[i].orig_va == va) {
+                       hugepg_tbl[i].socket_id = socket_id;
+                       hp_count++;
 #ifdef RTE_EAL_NUMA_AWARE_HUGEPAGES
-                               EAL_LOG(DEBUG,
-                                       "Hugepage %s is on socket %d",
-                                       hugepg_tbl[i].filepath, socket_id);
+                       EAL_LOG(DEBUG,
+                               "Hugepage %s is on socket %d",
+                               hugepg_tbl[i].filepath, socket_id);
 #endif
-                       }
+               } else {
+                       EAL_LOG(ERR,
+                               "shoudn't happen %p", hugepg_tbl[i].orig_va);
                }
        }
 
@@ -494,6 +501,25 @@ find_numasocket(struct hugepage_file *hugepg_tbl, struct 
hugepage_info *hpi)
        return -1;
 }
 
+static int
+cmp_orig_va(const void *a, const void *b)
+{
+#ifndef RTE_ARCH_PPC_64
+       const struct hugepage_file *p1 = a;
+       const struct hugepage_file *p2 = b;
+#else
+       /* PowerPC needs memory sorted in reverse order from x86 */
+       const struct hugepage_file *p1 = b;
+       const struct hugepage_file *p2 = a;
+#endif
+       if (p1->orig_va < p2->orig_va)
+               return -1;
+       else if (p1->orig_va > p2->orig_va)
+               return 1;
+       else
+               return 0;
+}
+
 static int
 cmp_physaddr(const void *a, const void *b)
 {
@@ -1324,6 +1350,9 @@ eal_legacy_hugepage_init(void)
                        }
                }
 
+               qsort(&tmp_hp[hp_offset], hpi->num_pages[0],
+                     sizeof(struct hugepage_file), cmp_orig_va);
+
                if (find_numasocket(&tmp_hp[hp_offset], hpi) < 0){
                        EAL_LOG(DEBUG, "Failed to find NUMA socket for %u MB 
pages",
                                        (unsigned)(hpi->hugepage_sz / 
0x100000));
-- 
2.37.1 (Apple Git-137.1)

Reply via email to