stats: avoid linear search for empty entry 02/35902/4
authorDamjan Marion <damarion@cisco.com>
Wed, 6 Apr 2022 10:06:41 +0000 (12:06 +0200)
committerOle Tr�an <otroan@employees.org>
Wed, 6 Apr 2022 11:25:03 +0000 (11:25 +0000)
Type: improvement
Change-Id: Ie4cdc6d8906da3d1cd18a8f1d7076283546d3003
Signed-off-by: Damjan Marion <damarion@cisco.com>
src/vlib/stats/init.c
src/vlib/stats/stats.c
src/vlib/stats/stats.h

index 3cfbd2d..2a7b6f5 100644 (file)
@@ -98,6 +98,7 @@ vlib_stats_init (vlib_main_t *vm)
 
   /* Set up the name to counter-vector hash table */
   sm->directory_vector = 0;
+  sm->dir_vector_first_free_elt = CLIB_U32_MAX;
 
   shared_header->epoch = 1;
 
index 9063fa3..cb29dda 100644 (file)
@@ -106,20 +106,21 @@ vlib_stats_create_counter (vlib_stats_entry_t *e)
 {
   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
   void *oldheap;
-  u32 index = ~0;
-  int i;
+  u32 index;
 
   oldheap = clib_mem_set_heap (sm->heap);
-  vec_foreach_index_backwards (i, sm->directory_vector)
-    if (sm->directory_vector[i].type == STAT_DIR_TYPE_EMPTY)
-      {
-       index = i;
-       break;
-      }
 
-  index = index == ~0 ? vec_len (sm->directory_vector) : index;
+  if (sm->dir_vector_first_free_elt != CLIB_U32_MAX)
+    {
+      index = sm->dir_vector_first_free_elt;
+      sm->dir_vector_first_free_elt = sm->directory_vector[index].index;
+    }
+  else
+    {
+      index = vec_len (sm->directory_vector);
+      vec_validate (sm->directory_vector, index);
+    }
 
-  vec_validate (sm->directory_vector, index);
   sm->directory_vector[index] = *e;
 
   clib_mem_set_heap (oldheap);
@@ -183,6 +184,9 @@ vlib_stats_remove_entry (u32 entry_index)
 
   memset (e, 0, sizeof (*e));
   e->type = STAT_DIR_TYPE_EMPTY;
+
+  e->value = sm->dir_vector_first_free_elt;
+  sm->dir_vector_first_free_elt = entry_index;
 }
 
 static void
index ef43510..09a9aef 100644 (file)
@@ -75,6 +75,7 @@ typedef struct
   /* statistics segment */
   uword *directory_vector_by_name;
   vlib_stats_entry_t *directory_vector;
+  u32 dir_vector_first_free_elt;
   u8 **nodes;
 
   /* Update interval */