diff options
| author | David Lamparter <equinox@opensourcerouting.org> | 2015-04-13 10:21:37 +0200 | 
|---|---|---|
| committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2015-11-03 05:54:27 -0800 | 
| commit | 20b8a998aa1be595b737c25d3fc0991628bfa3c2 (patch) | |
| tree | b7a6998d487d77d3dfc542cd892fdfa62a82a5e4 /lib | |
| parent | 7e111b6b0de44a9d351cdfeda4c674224a65ec3b (diff) | |
lib: optimise prefix list setup
- duplicate prefix check can use the trie structure
- appending with a seq# beyond the end of the list can shortcut
Configuration load is now bottlenecked by cmd_element_match() and
strcmp().  For a real-world routeserver prefix list configuration
(38668 lines of config for multiple prefix lists):
  before: 4.73s
  after:  1.92s    x 2.46
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/plist.c | 46 | 
1 files changed, 36 insertions, 10 deletions
diff --git a/lib/plist.c b/lib/plist.c index 2fdb0b33e8..63fd94c422 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -641,15 +641,20 @@ prefix_list_entry_add (struct prefix_list *plist,    if (pentry->seq == -1)      pentry->seq = prefix_new_seq_get (plist); -  /* Is there any same seq prefix list entry? */ -  replace = prefix_seq_check (plist, pentry->seq); -  if (replace) -    prefix_list_entry_delete (plist, replace, 0); - -  /* Check insert point. */ -  for (point = plist->head; point; point = point->next) -    if (point->seq >= pentry->seq) -      break; +  if (plist->tail && pentry->seq > plist->tail->seq) +    point = NULL; +  else +    { +      /* Is there any same seq prefix list entry? */ +      replace = prefix_seq_check (plist, pentry->seq); +      if (replace) +        prefix_list_entry_delete (plist, replace, 0); + +      /* Check insert point. */ +      for (point = plist->head; point; point = point->next) +        if (point->seq >= pentry->seq) +          break; +    }    /* In case of this is the first element of the list. */    pentry->next = point; @@ -829,6 +834,10 @@ static struct prefix_list_entry *  prefix_entry_dup_check (struct prefix_list *plist,  			struct prefix_list_entry *new)  { +  size_t depth, maxdepth = plist->master->trie_depth; +  uint8_t byte, *bytes = &new->prefix.u.prefix; +  size_t validbits = new->prefix.prefixlen; +  struct pltrie_table *table;    struct prefix_list_entry *pentry;    int seq = 0; @@ -837,7 +846,24 @@ prefix_entry_dup_check (struct prefix_list *plist,    else      seq = new->seq; -  for (pentry = plist->head; pentry; pentry = pentry->next) +  table = plist->trie; +  for (depth = 0; validbits > PLC_BITS && depth < maxdepth - 1; depth++) +    { +      byte = bytes[depth]; +      if (!table->entries[byte].next_table) +        return NULL; + +      table = table->entries[byte].next_table; +      validbits -= PLC_BITS; +    } + +  byte = bytes[depth]; +  if (validbits > PLC_BITS) +    pentry = table->entries[byte].final_chain; +  else +    pentry = table->entries[byte].up_chain; + +  for (; pentry; pentry = pentry->next_best)      {        if (prefix_same (&pentry->prefix, &new->prefix)  	  && pentry->type == new->type  | 
