Fine-grained add / delete locking

Add a bucket-level lock bit. Use a spinlock only when actually
allocating, freeing, or splitting a bucket. Should improve
multi-thread add/del performance.

Change-Id: I3e40e2a8371685457f340d6584dea14e3207f2b0
Signed-off-by: Dave Barach <dave@barachs.net>
This commit is contained in:
Dave Barach
2018-07-19 12:11:16 -04:00
committed by Damjan Marion
parent 13637632b8
commit 508498f74d
9 changed files with 234 additions and 354 deletions

View File

@ -13,12 +13,10 @@
* limitations under the License.
*/
#undef BIHASH_TYPE
#undef BIHASH_KVP_CACHE_SIZE
#undef BIHASH_KVP_PER_PAGE
#define BIHASH_TYPE _16_8
#define BIHASH_KVP_PER_PAGE 4
#define BIHASH_KVP_CACHE_SIZE 0
#ifndef __included_bihash_16_8_h__
#define __included_bihash_16_8_h__

View File

@ -13,12 +13,10 @@
* limitations under the License.
*/
#undef BIHASH_TYPE
#undef BIHASH_KVP_CACHE_SIZE
#undef BIHASH_KVP_PER_PAGE
#define BIHASH_TYPE _24_8
#define BIHASH_KVP_PER_PAGE 4
#define BIHASH_KVP_CACHE_SIZE 0
#ifndef __included_bihash_24_8_h__
#define __included_bihash_24_8_h__

View File

@ -14,12 +14,10 @@
*/
#undef BIHASH_TYPE
#undef BIHASH_KVP_CACHE_SIZE
#undef BIHASH_KVP_PER_PAGE
#define BIHASH_TYPE _40_8
#define BIHASH_KVP_PER_PAGE 4
#define BIHASH_KVP_CACHE_SIZE 0
#ifndef __included_bihash_40_8_h__
#define __included_bihash_40_8_h__

View File

@ -14,12 +14,10 @@
*/
#undef BIHASH_TYPE
#undef BIHASH_KVP_CACHE_SIZE
#undef BIHASH_KVP_PER_PAGE
#define BIHASH_TYPE _48_8
#define BIHASH_KVP_PER_PAGE 4
#define BIHASH_KVP_CACHE_SIZE 0
#ifndef __included_bihash_48_8_h__
#define __included_bihash_48_8_h__

View File

@ -13,12 +13,10 @@
* limitations under the License.
*/
#undef BIHASH_TYPE
#undef BIHASH_KVP_CACHE_SIZE
#undef BIHASH_KVP_PER_PAGE
#define BIHASH_TYPE _8_8
#define BIHASH_KVP_PER_PAGE 4
#define BIHASH_KVP_CACHE_SIZE 0
#ifndef __included_bihash_8_8_h__
#define __included_bihash_8_8_h__

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -13,12 +13,10 @@
* limitations under the License.
*/
#undef BIHASH_TYPE
#undef BIHASH_KVP_CACHE_SIZE
#undef BIHASH_KVP_PER_PAGE
#define BIHASH_TYPE _vec8_8
#define BIHASH_KVP_PER_PAGE 4
#define BIHASH_KVP_CACHE_SIZE 0
#ifndef __included_bihash_vec8_8_h__
#define __included_bihash_vec8_8_h__

View File

@ -17,6 +17,7 @@
#include <vppinfra/error.h>
#include <sys/resource.h>
#include <stdio.h>
#include <pthread.h>
#include <vppinfra/bihash_8_8.h>
#include <vppinfra/bihash_template.h>
@ -25,6 +26,9 @@
typedef struct
{
volatile u32 thread_barrier;
volatile u32 threads_running;
volatile u64 sequence_number;
u64 seed;
u32 nbuckets;
u32 nitems;
@ -34,11 +38,13 @@ typedef struct
int careful_delete_tests;
int verbose;
int non_random_keys;
u32 nthreads;
uword *key_hash;
u64 *keys;
uword hash_memory_size;
BVT (clib_bihash) hash;
clib_time_t clib_time;
void *global_heap;
unformat_input_t *input;
@ -89,6 +95,102 @@ test_bihash_vec64 (test_main_t * tm)
return 0;
}
void *
test_bihash_thread_fn (void *arg)
{
BVT (clib_bihash) * h;
BVT (clib_bihash_kv) kv;
test_main_t *tm = &test_main;
int i, j;
u32 my_thread_index = (u32) (u64) arg;
__os_thread_index = my_thread_index;
clib_mem_set_per_cpu_heap (tm->global_heap);
while (tm->thread_barrier)
;
h = &tm->hash;
for (i = 0; i < tm->ncycles; i++)
{
for (j = 0; j < tm->nitems; j++)
{
kv.key = ((u64) my_thread_index << 32) | (u64) j;
kv.value = ((u64) my_thread_index << 32) | (u64) j;
(void) __atomic_add_fetch (&tm->sequence_number, 1,
__ATOMIC_ACQUIRE);
BV (clib_bihash_add_del) (h, &kv, 1 /* is_add */ );
}
for (j = 0; j < tm->nitems; j++)
{
kv.key = ((u64) my_thread_index << 32) | (u64) j;
kv.value = ((u64) my_thread_index << 32) | (u64) j;
(void) __atomic_add_fetch (&tm->sequence_number, 1,
__ATOMIC_ACQUIRE);
BV (clib_bihash_add_del) (h, &kv, 0 /* is_add */ );
}
}
(void) __atomic_sub_fetch (&tm->threads_running, 1, __ATOMIC_ACQUIRE);
while (1)
{
struct timespec ts, tsrem;
ts.tv_sec = 1;
ts.tv_nsec = 0;
while (nanosleep (&ts, &tsrem) < 0)
ts = tsrem;
}
return (0); /* not so much */
}
static clib_error_t *
test_bihash_threads (test_main_t * tm)
{
int i;
pthread_t handle;
BVT (clib_bihash) * h;
int rv;
h = &tm->hash;
BV (clib_bihash_init) (h, "test", tm->nbuckets, tm->hash_memory_size);
tm->thread_barrier = 1;
/* Start the worker threads */
for (i = 0; i < tm->nthreads; i++)
{
rv = pthread_create (&handle, NULL, test_bihash_thread_fn,
(void *) (u64) i);
if (rv)
{
clib_unix_warning ("pthread_create returned %d", rv);
}
}
tm->threads_running = i;
tm->sequence_number = 0;
CLIB_MEMORY_BARRIER ();
/* start the workers */
tm->thread_barrier = 0;
while (tm->threads_running)
{
struct timespec ts, tsrem;
ts.tv_sec = 0;
ts.tv_nsec = 20 * 1000 * 1000; /* sleep for 20ms at a time */
while (nanosleep (&ts, &tsrem) < 0)
ts = tsrem;
}
return 0;
}
static clib_error_t *
test_bihash (test_main_t * tm)
{
@ -282,39 +384,6 @@ test_bihash (test_main_t * tm)
return 0;
}
clib_error_t *
test_bihash_cache (test_main_t * tm)
{
u32 lru;
BVT (clib_bihash_bucket) _b, *b = &_b;
BV (clib_bihash_reset_cache) (b);
fformat (stdout, "Initial LRU config: %U\n", BV (format_bihash_lru), b);
BV (clib_bihash_update_lru_not_inline) (b, 3);
fformat (stdout, "use slot 3, LRU config: %U\n", BV (format_bihash_lru), b);
BV (clib_bihash_update_lru) (b, 1);
fformat (stdout, "use slot 1 LRU config: %U\n", BV (format_bihash_lru), b);
lru = BV (clib_bihash_get_lru) (b);
fformat (stdout, "least-recently-used is %d\n", lru);
BV (clib_bihash_update_lru) (b, 4);
fformat (stdout, "use slot 4 LRU config: %U\n", BV (format_bihash_lru), b);
lru = BV (clib_bihash_get_lru) (b);
fformat (stdout, "least-recently-used is %d\n", lru);
return 0;
}
clib_error_t *
test_bihash_main (test_main_t * tm)
{
@ -351,9 +420,8 @@ test_bihash_main (test_main_t * tm)
;
else if (unformat (i, "vec64"))
which = 1;
else if (unformat (i, "cache"))
else if (unformat (i, "threads %u", &tm->nthreads))
which = 2;
else if (unformat (i, "verbose"))
tm->verbose = 1;
else
@ -378,7 +446,7 @@ test_bihash_main (test_main_t * tm)
break;
case 2:
error = test_bihash_cache (tm);
error = test_bihash_threads (tm);
break;
default:
@ -398,6 +466,8 @@ main (int argc, char *argv[])
clib_mem_init (0, 4095ULL << 20);
tm->global_heap = clib_mem_get_per_cpu_heap ();
tm->input = &i;
tm->seed = 0xdeaddabe;