@ -20,8 +20,9 @@
# include "src/core/ext/transport/chttp2/transport/hpack_parser_table.h"
# include "src/core/ext/transport/chttp2/transport/hpack_parser_table.h"
# include <assert.h>
# include <cassert>
# include <string.h>
# include <cstddef>
# include <cstring>
# include "absl/strings/str_format.h"
# include "absl/strings/str_format.h"
@ -38,29 +39,55 @@ extern grpc_core::TraceFlag grpc_http_trace;
namespace grpc_core {
namespace grpc_core {
HPackTable : : HPackTable ( ) : static_metadata_ ( GetStaticMementos ( ) ) { }
void HPackTable : : MementoRingBuffer : : Put ( Memento m ) {
GPR_ASSERT ( num_entries_ < max_entries_ ) ;
if ( entries_ . size ( ) < max_entries_ ) {
+ + num_entries_ ;
return entries_ . push_back ( std : : move ( m ) ) ;
}
size_t index = ( first_entry_ + num_entries_ ) % max_entries_ ;
entries_ [ index ] = std : : move ( m ) ;
+ + num_entries_ ;
}
HPackTable : : ~ HPackTable ( ) = default ;
auto HPackTable : : MementoRingBuffer : : PopOne ( ) - > Memento {
GPR_ASSERT ( num_entries_ > 0 ) ;
size_t index = first_entry_ % max_entries_ ;
+ + first_entry_ ;
- - num_entries_ ;
return std : : move ( entries_ [ index ] ) ;
}
/* Evict one element from the table */
auto HPackTable : : MementoRingBuffer : : Lookup ( uint32_t index ) const
void HPackTable : : EvictOne ( ) {
- > const Memento * {
auto first_entry = std : : move ( entries_ [ first_entry_ ] ) ;
if ( index > = num_entries_ ) return nullptr ;
GPR_ASSERT ( first_entry . transport_size ( ) < = mem_used_ ) ;
uint32_t offset = ( num_entries_ - 1u - index + first_entry_ ) % max_entries_ ;
mem_used_ - = first_entry . transport_size ( ) ;
return & entries_ [ offset ] ;
first_entry_ = ( ( first_entry_ + 1 ) % entries_ . size ( ) ) ;
num_entries_ - - ;
}
}
void HPackTable : : Rebuild ( uint32_t new_cap ) {
void HPackTable : : MementoRingBuffer : : Rebuild ( uint32_t max_entries ) {
EntriesVec entries ;
if ( max_entries = = max_entries_ ) return ;
entries . resize ( new_cap ) ;
std : : vector < Memento > entries ;
entries . reserve ( num_entries_ ) ;
for ( size_t i = 0 ; i < num_entries_ ; i + + ) {
for ( size_t i = 0 ; i < num_entries_ ; i + + ) {
entries [ i ] = std : : move ( entries_ [ ( first_entry_ + i ) % entries_ . size ( ) ] ) ;
entries . push_back (
std : : move ( entries_ [ ( first_entry_ + i ) % entries_ . size ( ) ] ) ) ;
}
}
first_entry_ = 0 ;
first_entry_ = 0 ;
entries_ . swap ( entries ) ;
entries_ . swap ( entries ) ;
}
}
HPackTable : : HPackTable ( ) : static_metadata_ ( GetStaticMementos ( ) ) { }
HPackTable : : ~ HPackTable ( ) = default ;
/* Evict one element from the table */
void HPackTable : : EvictOne ( ) {
auto first_entry = entries_ . PopOne ( ) ;
GPR_ASSERT ( first_entry . transport_size ( ) < = mem_used_ ) ;
mem_used_ - = first_entry . transport_size ( ) ;
}
void HPackTable : : SetMaxBytes ( uint32_t max_bytes ) {
void HPackTable : : SetMaxBytes ( uint32_t max_bytes ) {
if ( max_bytes_ = = max_bytes ) {
if ( max_bytes_ = = max_bytes ) {
return ;
return ;
@ -90,18 +117,9 @@ grpc_error_handle HPackTable::SetCurrentTableSize(uint32_t bytes) {
EvictOne ( ) ;
EvictOne ( ) ;
}
}
current_table_bytes_ = bytes ;
current_table_bytes_ = bytes ;
max_entries_ = hpack_constants : : EntriesForBytes ( bytes ) ;
uint32_t new_cap = std : : max ( hpack_constants : : EntriesForBytes ( bytes ) ,
if ( max_entries_ > entries_ . size ( ) ) {
hpack_constants : : kInitialTableEntries ) ;
Rebuild ( max_entries_ ) ;
entries_ . Rebuild ( new_cap ) ;
} else if ( max_entries_ < entries_ . size ( ) / 3 ) {
// TODO(ctiller): move to resource quota system, only shrink under memory
// pressure
uint32_t new_cap =
std : : max ( max_entries_ , static_cast < uint32_t > ( kInlineEntries ) ) ;
if ( new_cap ! = entries_ . size ( ) ) {
Rebuild ( new_cap ) ;
}
}
return GRPC_ERROR_NONE ;
return GRPC_ERROR_NONE ;
}
}
@ -122,7 +140,7 @@ grpc_error_handle HPackTable::Add(Memento md) {
// attempt to add an entry larger than the entire table causes
// attempt to add an entry larger than the entire table causes
// the table to be emptied of all existing entries, and results in an
// the table to be emptied of all existing entries, and results in an
// empty table.
// empty table.
while ( num_entries_ ) {
while ( entries_ . num_entries ( ) ) {
EvictOne ( ) ;
EvictOne ( ) ;
}
}
return GRPC_ERROR_NONE ;
return GRPC_ERROR_NONE ;
@ -136,10 +154,7 @@ grpc_error_handle HPackTable::Add(Memento md) {
// copy the finalized entry in
// copy the finalized entry in
mem_used_ + = md . transport_size ( ) ;
mem_used_ + = md . transport_size ( ) ;
entries_ [ ( first_entry_ + num_entries_ ) % entries_ . size ( ) ] = std : : move ( md ) ;
entries_ . Put ( std : : move ( md ) ) ;
// update accounting values
num_entries_ + + ;
return GRPC_ERROR_NONE ;
return GRPC_ERROR_NONE ;
}
}
@ -225,7 +240,7 @@ GPR_ATTRIBUTE_NOINLINE HPackTable::Memento MakeMemento(size_t i) {
} // namespace
} // namespace
const HPackTable : : StaticMementos & HPackTable : : GetStaticMementos ( ) {
auto HPackTable : : GetStaticMementos ( ) - > const StaticMementos & {
static const StaticMementos * const static_mementos = new StaticMementos ( ) ;
static const StaticMementos * const static_mementos = new StaticMementos ( ) ;
return * static_mementos ;
return * static_mementos ;
}
}