@ -50,10 +50,6 @@ typedef struct slice_shard {
size_t capacity ;
size_t capacity ;
} slice_shard ;
} slice_shard ;
/* hash seed: decided at initialization time */
uint32_t g_hash_seed ;
static int g_forced_hash_seed = 0 ;
static slice_shard g_shards [ SHARD_COUNT ] ;
static slice_shard g_shards [ SHARD_COUNT ] ;
typedef struct {
typedef struct {
@ -68,6 +64,10 @@ uint32_t grpc_static_metadata_hash_values[GRPC_STATIC_MDSTR_COUNT];
namespace grpc_core {
namespace grpc_core {
/* hash seed: decided at initialization time */
uint32_t g_hash_seed ;
static bool g_forced_hash_seed = false ;
InternedSliceRefcount : : ~ InternedSliceRefcount ( ) {
InternedSliceRefcount : : ~ InternedSliceRefcount ( ) {
slice_shard * shard = & g_shards [ SHARD_IDX ( this - > hash ) ] ;
slice_shard * shard = & g_shards [ SHARD_IDX ( this - > hash ) ] ;
MutexLock lock ( & shard - > mu ) ;
MutexLock lock ( & shard - > mu ) ;
@ -115,7 +115,7 @@ grpc_core::InternedSlice::InternedSlice(InternedSliceRefcount* s) {
uint32_t grpc_slice_default_hash_impl ( grpc_slice s ) {
uint32_t grpc_slice_default_hash_impl ( grpc_slice s ) {
return gpr_murmur_hash3 ( GRPC_SLICE_START_PTR ( s ) , GRPC_SLICE_LENGTH ( s ) ,
return gpr_murmur_hash3 ( GRPC_SLICE_START_PTR ( s ) , GRPC_SLICE_LENGTH ( s ) ,
g_hash_seed ) ;
grpc_core : : g _hash_seed ) ;
}
}
uint32_t grpc_static_slice_hash ( grpc_slice s ) {
uint32_t grpc_static_slice_hash ( grpc_slice s ) {
@ -159,20 +159,20 @@ grpc_slice grpc_slice_intern(grpc_slice slice) {
}
}
// Attempt to see if the provided slice or string matches a static slice.
// Attempt to see if the provided slice or string matches a static slice.
// SliceArgs... is either a const grpc_slice& or a string and length. In either
// SliceArgs is either a const grpc_slice& or const pair<const char*, size_t>&.
// case, hash is the pre-computed hash value.
// In either case, hash is the pre-computed hash value.
//
//
// Returns: a matching static slice, or null.
// Returns: a matching static slice, or null.
template < class . . . SliceArgs >
template < typename SliceArgs >
static const grpc_core : : StaticMetadataSlice * MatchStaticSlice (
static const grpc_core : : StaticMetadataSlice * MatchStaticSlice (
uint32_t hash , SliceArgs & & . . . args ) {
uint32_t hash , const SliceArgs & args ) {
for ( uint32_t i = 0 ; i < = max_static_metadata_hash_probe ; i + + ) {
for ( uint32_t i = 0 ; i < = max_static_metadata_hash_probe ; i + + ) {
static_metadata_hash_ent ent =
static_metadata_hash_ent ent =
static_metadata_hash [ ( hash + i ) % GPR_ARRAY_SIZE ( static_metadata_hash ) ] ;
static_metadata_hash [ ( hash + i ) % GPR_ARRAY_SIZE ( static_metadata_hash ) ] ;
const grpc_core : : StaticMetadataSlice * static_slice_table =
const grpc_core : : StaticMetadataSlice * static_slice_table =
grpc_static_slice_table ( ) ;
grpc_static_slice_table ( ) ;
if ( ent . hash = = hash & & ent . idx < GRPC_STATIC_MDSTR_COUNT & &
if ( ent . hash = = hash & & ent . idx < GRPC_STATIC_MDSTR_COUNT & &
static_slice_table [ ent . idx ] . Equals ( std : : forward < SliceArgs > ( args ) . . . ) ) {
static_slice_table [ ent . idx ] = = args ) {
return & static_slice_table [ ent . idx ] ;
return & static_slice_table [ ent . idx ] ;
}
}
}
}
@ -182,8 +182,12 @@ static const grpc_core::StaticMetadataSlice* MatchStaticSlice(
// Helper methods to enable us to select appropriately overloaded slice methods
// Helper methods to enable us to select appropriately overloaded slice methods
// whether we're dealing with a slice, or a buffer with length, when interning
// whether we're dealing with a slice, or a buffer with length, when interning
// strings. Helpers for FindOrCreateInternedSlice().
// strings. Helpers for FindOrCreateInternedSlice().
static const void * GetBuffer ( const void * buf , size_t len ) { return buf ; }
static const char * GetBuffer ( const std : : pair < const char * , size_t > & buflen ) {
static size_t GetLength ( const void * buf , size_t len ) { return len ; }
return buflen . first ;
}
static size_t GetLength ( const std : : pair < const char * , size_t > & buflen ) {
return buflen . second ;
}
static const void * GetBuffer ( const grpc_slice & slice ) {
static const void * GetBuffer ( const grpc_slice & slice ) {
return GRPC_SLICE_START_PTR ( slice ) ;
return GRPC_SLICE_START_PTR ( slice ) ;
}
}
@ -192,19 +196,19 @@ static size_t GetLength(const grpc_slice& slice) {
}
}
// Creates an interned slice for a string that does not currently exist in the
// Creates an interned slice for a string that does not currently exist in the
// intern table. SliceArgs... is either a const grpc_slice& or a string and
// intern table. SliceArgs is either a const grpc_slice& or a con st
// length. In either case, hash is the pre-computed hash value. We must already
// pair<const char*, size_t>&. Hash is the pre-computed hash value. We must
// hold the shard lock. Helper for FindOrCreateInternedSlice().
// already hold the shard lock. Helper for FindOrCreateInternedSlice().
//
//
// Returns: a newly interned slice.
// Returns: a newly interned slice.
template < class . . . SliceArgs >
template < typename SliceArgs >
static InternedSliceRefcount * InternNewStringLocked ( slice_shard * shard ,
static InternedSliceRefcount * InternNewStringLocked ( slice_shard * shard ,
size_t shard_idx ,
size_t shard_idx ,
uint32_t hash ,
uint32_t hash ,
SliceArgs & & . . . args ) {
const SliceArgs & args ) {
/* string data goes after the internal_string header */
/* string data goes after the internal_string header */
size_t len = GetLength ( std : : forward < SliceArgs > ( args ) . . . ) ;
size_t len = GetLength ( args ) ;
const void * buffer = GetBuffer ( std : : forward < SliceArgs > ( args ) . . . ) ;
const void * buffer = GetBuffer ( args ) ;
InternedSliceRefcount * s =
InternedSliceRefcount * s =
static_cast < InternedSliceRefcount * > ( gpr_malloc ( sizeof ( * s ) + len ) ) ;
static_cast < InternedSliceRefcount * > ( gpr_malloc ( sizeof ( * s ) + len ) ) ;
new ( s ) grpc_core : : InternedSliceRefcount ( len , hash , shard - > strs [ shard_idx ] ) ;
new ( s ) grpc_core : : InternedSliceRefcount ( len , hash , shard - > strs [ shard_idx ] ) ;
@ -227,16 +231,15 @@ static InternedSliceRefcount* InternNewStringLocked(slice_shard* shard,
// shard lock. Helper for FindOrCreateInternedSlice().
// shard lock. Helper for FindOrCreateInternedSlice().
//
//
// Returns: a pre-existing matching static slice, or null.
// Returns: a pre-existing matching static slice, or null.
template < class . . . SliceArgs >
template < typename SliceArgs >
static InternedSliceRefcount * MatchInternedSliceLocked ( uint32_t hash ,
static InternedSliceRefcount * MatchInternedSliceLocked ( uint32_t hash ,
size_t idx ,
size_t idx ,
SliceArgs & & . . . args ) {
const SliceArgs & args ) {
InternedSliceRefcount * s ;
InternedSliceRefcount * s ;
slice_shard * shard = & g_shards [ SHARD_IDX ( hash ) ] ;
slice_shard * shard = & g_shards [ SHARD_IDX ( hash ) ] ;
/* search for an existing string */
/* search for an existing string */
for ( s = shard - > strs [ idx ] ; s ; s = s - > bucket_next ) {
for ( s = shard - > strs [ idx ] ; s ; s = s - > bucket_next ) {
if ( s - > hash = = hash & &
if ( s - > hash = = hash & & grpc_core : : InternedSlice ( s ) = = args ) {
grpc_core : : InternedSlice ( s ) . Equals ( std : : forward < SliceArgs > ( args ) . . . ) ) {
if ( s - > refcnt . RefIfNonZero ( ) ) {
if ( s - > refcnt . RefIfNonZero ( ) ) {
return s ;
return s ;
}
}
@ -248,22 +251,20 @@ static InternedSliceRefcount* MatchInternedSliceLocked(uint32_t hash,
// Attempt to see if the provided slice or string matches an existing interned
// Attempt to see if the provided slice or string matches an existing interned
// slice, and failing that, create an interned slice with its contents. Returns
// slice, and failing that, create an interned slice with its contents. Returns
// either the existing matching interned slice or the newly created one.
// either the existing matching interned slice or the newly created one.
// SliceArgs... is either a const grpc_slice& or a string and length. In either
// SliceArgs is either a const grpc_slice& or const pair<const char*, size_t>&.
// case, hash is the pre-computed hash value. We do not hold the shard lock
// In either case, hash is the pre-computed hash value. We do not hold the
// here, but do take it.
// shard lock here, but do take it.
//
//
// Returns: an interned slice, either pre-existing/matched or newly created.
// Returns: an interned slice, either pre-existing/matched or newly created.
template < class . . . SliceArgs >
template < typename SliceArgs >
static InternedSliceRefcount * FindOrCreateInternedSlice ( uint32_t hash ,
static InternedSliceRefcount * FindOrCreateInternedSlice ( uint32_t hash ,
SliceArgs & & . . . args ) {
const SliceArgs & args ) {
slice_shard * shard = & g_shards [ SHARD_IDX ( hash ) ] ;
slice_shard * shard = & g_shards [ SHARD_IDX ( hash ) ] ;
gpr_mu_lock ( & shard - > mu ) ;
gpr_mu_lock ( & shard - > mu ) ;
const size_t idx = TABLE_IDX ( hash , shard - > capacity ) ;
const size_t idx = TABLE_IDX ( hash , shard - > capacity ) ;
InternedSliceRefcount * s =
InternedSliceRefcount * s = MatchInternedSliceLocked ( hash , idx , args ) ;
MatchInternedSliceLocked ( hash , idx , std : : forward < SliceArgs > ( args ) . . . ) ;
if ( s = = nullptr ) {
if ( s = = nullptr ) {
s = InternNewStringLocked ( shard , idx , hash ,
s = InternNewStringLocked ( shard , idx , hash , args ) ;
std : : forward < SliceArgs > ( args ) . . . ) ;
}
}
gpr_mu_unlock ( & shard - > mu ) ;
gpr_mu_unlock ( & shard - > mu ) ;
return s ;
return s ;
@ -277,12 +278,13 @@ grpc_core::ManagedMemorySlice::ManagedMemorySlice(const char* string,
size_t len ) {
size_t len ) {
GPR_TIMER_SCOPE ( " grpc_slice_intern " , 0 ) ;
GPR_TIMER_SCOPE ( " grpc_slice_intern " , 0 ) ;
const uint32_t hash = gpr_murmur_hash3 ( string , len , g_hash_seed ) ;
const uint32_t hash = gpr_murmur_hash3 ( string , len , g_hash_seed ) ;
const StaticMetadataSlice * static_slice = MatchStaticSlice ( hash , string , len ) ;
const StaticMetadataSlice * static_slice =
MatchStaticSlice ( hash , std : : pair < const char * , size_t > ( string , len ) ) ;
if ( static_slice ) {
if ( static_slice ) {
* this = * static_slice ;
* this = * static_slice ;
} else {
} else {
* this =
* this = grpc_core : : InternedSlice ( FindOrCreateInternedSlice (
grpc_core : : InternedSlice ( FindOrCreateInternedSlice ( hash , string , len ) ) ;
hash , std : : pair < const char * , size_t > ( string , len ) ) ) ;
}
}
}
}
@ -303,13 +305,14 @@ grpc_core::ManagedMemorySlice::ManagedMemorySlice(const grpc_slice* slice_ptr) {
}
}
void grpc_test_only_set_slice_hash_seed ( uint32_t seed ) {
void grpc_test_only_set_slice_hash_seed ( uint32_t seed ) {
g_hash_seed = seed ;
grpc_core : : g _hash_seed = seed ;
g_forced_hash_seed = 1 ;
grpc_core : : g _forced_hash_seed = true ;
}
}
void grpc_slice_intern_init ( void ) {
void grpc_slice_intern_init ( void ) {
if ( ! g_forced_hash_seed ) {
if ( ! grpc_core : : g_forced_hash_seed ) {
g_hash_seed = static_cast < uint32_t > ( gpr_now ( GPR_CLOCK_REALTIME ) . tv_nsec ) ;
grpc_core : : g_hash_seed =
static_cast < uint32_t > ( gpr_now ( GPR_CLOCK_REALTIME ) . tv_nsec ) ;
}
}
for ( size_t i = 0 ; i < SHARD_COUNT ; i + + ) {
for ( size_t i = 0 ; i < SHARD_COUNT ; i + + ) {
slice_shard * shard = & g_shards [ i ] ;
slice_shard * shard = & g_shards [ i ] ;