|
|
|
@ -72,6 +72,16 @@ static int g_forced_hash_seed = 0; |
|
|
|
|
|
|
|
|
|
static slice_shard g_shards[SHARD_COUNT]; |
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
uint32_t hash; |
|
|
|
|
uint32_t idx; |
|
|
|
|
} static_metadata_hash_ent; |
|
|
|
|
|
|
|
|
|
static static_metadata_hash_ent |
|
|
|
|
static_metadata_hash[2 * GRPC_STATIC_MDSTR_COUNT]; |
|
|
|
|
static uint32_t max_static_metadata_hash_probe; |
|
|
|
|
static uint32_t static_metadata_hash_values[GRPC_STATIC_MDSTR_COUNT]; |
|
|
|
|
|
|
|
|
|
static void interned_slice_ref(void *p) { |
|
|
|
|
interned_slice_refcount *s = p; |
|
|
|
|
GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&s->refcnt, 1) > 0); |
|
|
|
@ -152,15 +162,35 @@ uint32_t grpc_slice_default_hash_impl(void *unused_refcnt, grpc_slice s) { |
|
|
|
|
g_hash_seed); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint32_t grpc_static_slice_hash(void *unused_refcnt, grpc_slice s) { |
|
|
|
|
int id = grpc_static_metadata_index(s); |
|
|
|
|
if (id == -1) { |
|
|
|
|
return grpc_slice_default_hash_impl(unused_refcnt, s); |
|
|
|
|
} |
|
|
|
|
return static_metadata_hash_values[id]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint32_t grpc_slice_hash(grpc_slice s) { |
|
|
|
|
return s.refcount == NULL ? grpc_slice_default_hash_impl(NULL, s) |
|
|
|
|
: s.refcount->vtable->hash(s.refcount, s); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_slice grpc_slice_intern(grpc_slice slice) { |
|
|
|
|
if (grpc_is_static_metadata_string(slice)) { |
|
|
|
|
return slice; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint32_t hash = grpc_slice_hash(slice); |
|
|
|
|
for (uint32_t i = 0; i <= max_static_metadata_hash_probe; i++) { |
|
|
|
|
static_metadata_hash_ent ent = |
|
|
|
|
static_metadata_hash[(hash + i) % GPR_ARRAY_SIZE(static_metadata_hash)]; |
|
|
|
|
if (ent.hash == hash && ent.idx < GRPC_STATIC_MDSTR_COUNT && |
|
|
|
|
0 == grpc_slice_cmp(grpc_static_slice_table[ent.idx], slice)) { |
|
|
|
|
return grpc_static_slice_table[ent.idx]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
interned_slice_refcount *s; |
|
|
|
|
uint32_t hash = gpr_murmur_hash3(GRPC_SLICE_START_PTR(slice), |
|
|
|
|
GRPC_SLICE_LENGTH(slice), g_hash_seed); |
|
|
|
|
slice_shard *shard = &g_shards[SHARD_IDX(hash)]; |
|
|
|
|
|
|
|
|
|
gpr_mu_lock(&shard->mu); |
|
|
|
@ -212,6 +242,9 @@ void grpc_test_only_set_slice_hash_seed(uint32_t seed) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_slice_intern_init(void) { |
|
|
|
|
if (!g_forced_hash_seed) { |
|
|
|
|
g_hash_seed = (uint32_t)gpr_now(GPR_CLOCK_REALTIME).tv_nsec; |
|
|
|
|
} |
|
|
|
|
for (size_t i = 0; i < SHARD_COUNT; i++) { |
|
|
|
|
slice_shard *shard = &g_shards[i]; |
|
|
|
|
gpr_mu_init(&shard->mu); |
|
|
|
@ -220,6 +253,27 @@ void grpc_slice_intern_init(void) { |
|
|
|
|
shard->strs = gpr_malloc(sizeof(*shard->strs) * shard->capacity); |
|
|
|
|
memset(shard->strs, 0, sizeof(*shard->strs) * shard->capacity); |
|
|
|
|
} |
|
|
|
|
for (size_t i = 0; i < GPR_ARRAY_SIZE(static_metadata_hash); i++) { |
|
|
|
|
static_metadata_hash[i].hash = 0; |
|
|
|
|
static_metadata_hash[i].idx = GRPC_STATIC_MDSTR_COUNT; |
|
|
|
|
} |
|
|
|
|
max_static_metadata_hash_probe = 0; |
|
|
|
|
for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) { |
|
|
|
|
static_metadata_hash_values[i] = |
|
|
|
|
grpc_slice_default_hash_impl(NULL, grpc_static_slice_table[i]); |
|
|
|
|
for (size_t j = 0; j < GPR_ARRAY_SIZE(static_metadata_hash); j++) { |
|
|
|
|
size_t slot = (static_metadata_hash_values[i] + j) % |
|
|
|
|
GPR_ARRAY_SIZE(static_metadata_hash); |
|
|
|
|
if (static_metadata_hash[slot].idx == GRPC_STATIC_MDSTR_COUNT) { |
|
|
|
|
static_metadata_hash[slot].hash = static_metadata_hash_values[i]; |
|
|
|
|
static_metadata_hash[slot].idx = (uint32_t)i; |
|
|
|
|
if (j > max_static_metadata_hash_probe) { |
|
|
|
|
max_static_metadata_hash_probe = (uint32_t)j; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_slice_intern_shutdown(void) { |
|
|
|
|