]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Multipage allocation
authorMaria Matejka <mq@ucw.cz>
Wed, 8 Sep 2021 09:29:49 +0000 (11:29 +0200)
committerMaria Matejka <mq@ucw.cz>
Wed, 13 Oct 2021 17:01:22 +0000 (19:01 +0200)
We can also quite simply allocate bigger blocks. Anyway, we need these
blocks to be aligned to their size which needs one mmap() two times
bigger and then two munmap()s returning the unaligned parts.

The user can specify -B <N> on startup when <N> is the exponent of 2,
setting the block size to 2^N. On most systems, N is 12, anyway if you
know that your configuration is going to eat gigabytes of RAM, you are
almost forced to raise your block size as you may easily get into memory
fragmentation issues or you have to raise your maximum mapping count,
e.g. "sysctl vm.max_map_count=(number)".

doc/bird.sgml
lib/resource.c
lib/slab.c
sysdep/unix/alloc.c
sysdep/unix/main.c

index 39dadaf20eee3157e2c7fec8ebc180e8346fb7fb..ddad4d98eb7eb34be48f90996a4781c1f73b8d29 100644 (file)
@@ -145,6 +145,13 @@ BIRD executable by configuring out routing protocols you don't use, and
 <p>You can pass several command-line options to bird:
 
 <descrip>
+       <tag><label id="argv-block">-B <m/exp/</tag>
+       allocate memory using 2^<cf/exp/ byte sized blocks;
+       if you're expecting high memory load, raise this to
+        reduce number of allocated memory pages. For a million routes
+       in one table, the recommended setting is 18.
+       Default is your system page size, typically 12 for 4096 bytes.
+
        <tag><label id="argv-config">-c <m/config name/</tag>
        use given configuration file instead of <it/prefix/<file>/etc/bird.conf</file>.
 
index 0ad886d9e068ebd114bea26d430b3b4477a7dc4a..e80b315b2c85e276d64eaa86ce13834a64c095d4 100644 (file)
@@ -61,7 +61,6 @@ pool root_pool;
 
 void *alloc_sys_page(void);
 void free_sys_page(void *);
-void resource_sys_init(void);
 
 static int indent;
 
@@ -283,7 +282,6 @@ rlookup(unsigned long a)
 void
 resource_init(void)
 {
-  resource_sys_init();
   root_pool.r.class = &pool_class;
   root_pool.name = "Root";
   init_list(&root_pool.inside);
index 2fc88ee08e5a05588ff9872ca65821b7d8b503fe..6348e29bf22ceb97da46697a408cb66cf6681830 100644 (file)
@@ -178,7 +178,7 @@ struct sl_alignment {                       /* Magic structure for testing of alignment */
   int x[0];
 };
 
-#define SL_GET_HEAD(x) ((struct sl_head *) (((uintptr_t) (x)) & ~(page_size-1)))
+#define SL_GET_HEAD(x) ((struct sl_head *) PAGE_HEAD(x))
 
 /**
  * sl_new - create a new Slab
index f6296afee7d7d8d94d097260deeb568b474ee3c5..4c9d5eb5d14512ac70da0089a66bc9973e4a5fad 100644 (file)
@@ -17,6 +17,7 @@
 #endif
 
 long page_size = 0;
+_Bool alloc_multipage = 0;
 
 #ifdef HAVE_MMAP
 static _Bool use_fake = 0;
@@ -45,9 +46,31 @@ alloc_sys_page(void)
 #ifdef HAVE_MMAP
   if (!use_fake)
   {
+    if (alloc_multipage)
+    {
+      void *big = mmap(NULL, page_size * 2, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+      if (big == MAP_FAILED)
+       bug("mmap(%lu) failed: %m", page_size);
+
+      uintptr_t offset = ((uintptr_t) big) % page_size;
+      if (offset)
+      {
+       void *ret = big + page_size - offset;
+       munmap(big, page_size - offset);
+       munmap(ret + page_size, offset);
+       return ret;
+      }
+      else
+      {
+       munmap(big + page_size, page_size);
+       return big;
+      }
+    }
+
     void *ret = mmap(NULL, page_size, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     if (ret == MAP_FAILED)
       bug("mmap(%lu) failed: %m", page_size);
+
     return ret;
   }
   else
index cdf0a3101bb3afb2488d322548b4ee9621a17923..7e8ea0dc550b2eba77100bc5eb5288b357757623 100644 (file)
@@ -682,7 +682,7 @@ signal_init(void)
  *     Parsing of command-line arguments
  */
 
-static char *opt_list = "bc:dD:ps:P:u:g:flRh";
+static char *opt_list = "B:c:dD:ps:P:u:g:flRh";
 int parse_and_exit;
 char *bird_name;
 static char *use_user;
@@ -703,6 +703,7 @@ display_help(void)
   fprintf(stderr,
     "\n"
     "Options: \n"
+    "  -B <block-size>     Use 2^this number as memory allocation block size (default: 12)\n"
     "  -c <config-file>     Use given configuration file instead of\n"
     "                       "  PATH_CONFIG_FILE "\n"
     "  -d                   Enable debug messages and run bird in foreground\n"
@@ -789,12 +790,15 @@ get_gid(const char *s)
   return gr->gr_gid;
 }
 
+extern _Bool alloc_multipage;
+
 static void
 parse_args(int argc, char **argv)
 {
   int config_changed = 0;
   int socket_changed = 0;
   int c;
+  int bp;
 
   bird_name = get_bird_name(argv[0], "bird");
   if (argc == 2)
@@ -807,6 +811,29 @@ parse_args(int argc, char **argv)
   while ((c = getopt(argc, argv, opt_list)) >= 0)
     switch (c)
       {
+      case 'B':
+       bp = atoi(optarg);
+       if (bp < 1)
+       {
+         fprintf(stderr, "Strange block size power %d\n\n", bp);
+         display_usage();
+         exit(1);
+       }
+
+       if ((1 << bp) < page_size)
+       {
+         fprintf(stderr, "Requested block size %ld is lesser than page size %ld\n\n", (1L<<bp), page_size);
+         display_usage();
+         exit(1);
+       }
+
+       if ((1L << bp) > page_size)
+       {
+         alloc_multipage = 1;
+         page_size = (1L << bp);
+       }
+
+       break;
       case 'c':
        config_name = optarg;
        config_changed = 1;
@@ -861,6 +888,8 @@ parse_args(int argc, char **argv)
    }
 }
 
+void resource_sys_init(void);
+
 /*
  *     Hic Est main()
  */
@@ -873,6 +902,7 @@ main(int argc, char **argv)
     dmalloc_debug(0x2f03d00);
 #endif
 
+  resource_sys_init();
   parse_args(argc, argv);
   log_switch(1, NULL, NULL);