Measure actual echo timeout instead of network timeout to first hop
This commit is contained in:
@@ -77,8 +77,6 @@ namespace Network {
|
|||||||
int fd( void ) { return connection.fd(); }
|
int fd( void ) { return connection.fd(); }
|
||||||
|
|
||||||
void set_verbose( void ) { sender.set_verbose(); verbose = true; }
|
void set_verbose( void ) { sender.set_verbose(); verbose = true; }
|
||||||
|
|
||||||
uint64_t timeout( void ) { return connection.timeout(); }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -164,8 +164,7 @@ bool STMClient::process_user_input( int fd )
|
|||||||
for ( int i = 0; i < bytes_read; i++ ) {
|
for ( int i = 0; i < bytes_read; i++ ) {
|
||||||
char the_byte = buf[ i ];
|
char the_byte = buf[ i ];
|
||||||
|
|
||||||
overlays.get_prediction_engine().new_user_byte( the_byte, *local_framebuffer,
|
overlays.get_prediction_engine().new_user_byte( the_byte, *local_framebuffer );
|
||||||
network->timeout() );
|
|
||||||
|
|
||||||
if ( quit_sequence_started ) {
|
if ( quit_sequence_started ) {
|
||||||
if ( the_byte == '.' ) { /* Quit sequence is Ctrl-^ . */
|
if ( the_byte == '.' ) { /* Quit sequence is Ctrl-^ . */
|
||||||
|
|||||||
+37
-5
@@ -92,10 +92,29 @@ void OverlayEngine::apply( Framebuffer &fb ) const
|
|||||||
[&fb]( OverlayElement *x ) { x->apply( fb ); } );
|
[&fb]( OverlayElement *x ) { x->apply( fb ); } );
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayEngine::cull( const Framebuffer &fb )
|
void PredictionEngine::cull( const Framebuffer &fb )
|
||||||
{
|
{
|
||||||
|
uint64_t now = timestamp();
|
||||||
|
|
||||||
auto i = elements.begin();
|
auto i = elements.begin();
|
||||||
while ( i != elements.end() ) {
|
while ( i != elements.end() ) {
|
||||||
|
/* update echo timeout state */
|
||||||
|
if ( (*i)->get_validity( fb ) == Correct ) {
|
||||||
|
double R = now - (*i)->prediction_time;
|
||||||
|
if ( !RTT_hit ) { /* first measurement */
|
||||||
|
SRTT = R;
|
||||||
|
RTTVAR = R / 2;
|
||||||
|
RTT_hit = true;
|
||||||
|
} else {
|
||||||
|
const double alpha = 1.0 / 8.0;
|
||||||
|
const double beta = 1.0 / 4.0;
|
||||||
|
|
||||||
|
RTTVAR = (1 - beta) * RTTVAR + ( beta * fabs( SRTT - R ) );
|
||||||
|
SRTT = (1 - alpha) * SRTT + ( alpha * R );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eliminate predictions proven correct or incorrect */
|
||||||
if ( (*i)->get_validity( fb ) != Pending ) {
|
if ( (*i)->get_validity( fb ) != Pending ) {
|
||||||
delete (*i);
|
delete (*i);
|
||||||
i = elements.erase( i );
|
i = elements.erase( i );
|
||||||
@@ -263,6 +282,8 @@ void NotificationEngine::apply( Framebuffer &fb ) const
|
|||||||
void OverlayManager::apply( Framebuffer &fb )
|
void OverlayManager::apply( Framebuffer &fb )
|
||||||
{
|
{
|
||||||
predictions.calculate_score( fb );
|
predictions.calculate_score( fb );
|
||||||
|
|
||||||
|
/* eliminate predictions proven correct or incorrect and update echo timers */
|
||||||
predictions.cull( fb );
|
predictions.cull( fb );
|
||||||
|
|
||||||
if ( predictions.get_score() > 3 ) {
|
if ( predictions.get_score() > 3 ) {
|
||||||
@@ -289,14 +310,14 @@ void PredictionEngine::calculate_score( const Framebuffer &fb )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb, int prediction_len )
|
void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb )
|
||||||
{
|
{
|
||||||
uint64_t now = timestamp();
|
uint64_t now = timestamp();
|
||||||
|
|
||||||
if ( elements.empty() ) {
|
if ( elements.empty() ) {
|
||||||
/* starting from scratch */
|
/* starting from scratch */
|
||||||
|
|
||||||
elements.push_front( new ConditionalCursorMove( now + prediction_len,
|
elements.push_front( new ConditionalCursorMove( now + prediction_len(),
|
||||||
fb.ds.get_cursor_row(),
|
fb.ds.get_cursor_row(),
|
||||||
fb.ds.get_cursor_col() ) );
|
fb.ds.get_cursor_col() ) );
|
||||||
}
|
}
|
||||||
@@ -313,7 +334,7 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb, int
|
|||||||
|
|
||||||
const Cell *existing_cell = fb.get_cell( ccm->new_row, ccm->new_col );
|
const Cell *existing_cell = fb.get_cell( ccm->new_row, ccm->new_col );
|
||||||
|
|
||||||
ConditionalOverlayCell *coc = new ConditionalOverlayCell( now + prediction_len,
|
ConditionalOverlayCell *coc = new ConditionalOverlayCell( now + prediction_len(),
|
||||||
ccm->new_row, ccm->new_col,
|
ccm->new_row, ccm->new_col,
|
||||||
existing_cell->renditions.background_color,
|
existing_cell->renditions.background_color,
|
||||||
*existing_cell );
|
*existing_cell );
|
||||||
@@ -323,7 +344,7 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb, int
|
|||||||
coc->replacement.contents.push_back( the_byte );
|
coc->replacement.contents.push_back( the_byte );
|
||||||
|
|
||||||
ccm->new_col++;
|
ccm->new_col++;
|
||||||
ccm->expiration_time = now + prediction_len;
|
ccm->expiration_time = now + prediction_len();
|
||||||
|
|
||||||
elements.push_back( coc );
|
elements.push_back( coc );
|
||||||
} else {
|
} else {
|
||||||
@@ -357,3 +378,14 @@ int OverlayManager::wait_time( void )
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PredictionEngine::prediction_len( void )
|
||||||
|
{
|
||||||
|
uint64_t RTO = lrint( ceil( SRTT + 4 * RTTVAR ) );
|
||||||
|
if ( RTO < 20 ) {
|
||||||
|
RTO = 20;
|
||||||
|
} else if ( RTO > 2000 ) {
|
||||||
|
RTO = 2000;
|
||||||
|
}
|
||||||
|
return RTO;
|
||||||
|
}
|
||||||
|
|||||||
+12
-5
@@ -20,12 +20,13 @@ namespace Overlay {
|
|||||||
/* The individual elements of an overlay -- cursor movements and replaced cells */
|
/* The individual elements of an overlay -- cursor movements and replaced cells */
|
||||||
class OverlayElement {
|
class OverlayElement {
|
||||||
public:
|
public:
|
||||||
uint64_t expiration_time;
|
uint64_t prediction_time, expiration_time;
|
||||||
|
|
||||||
virtual void apply( Framebuffer &fb ) const = 0;
|
virtual void apply( Framebuffer &fb ) const = 0;
|
||||||
virtual Validity get_validity( const Framebuffer & ) const;
|
virtual Validity get_validity( const Framebuffer & ) const;
|
||||||
|
|
||||||
OverlayElement( uint64_t s_expiration_time ) : expiration_time( s_expiration_time ) {}
|
OverlayElement( uint64_t s_expiration_time ) : prediction_time( timestamp() ),
|
||||||
|
expiration_time( s_expiration_time ) {}
|
||||||
virtual ~OverlayElement() {}
|
virtual ~OverlayElement() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -75,7 +76,6 @@ namespace Overlay {
|
|||||||
list<OverlayElement *> elements;
|
list<OverlayElement *> elements;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void cull( const Framebuffer &fb );
|
|
||||||
virtual void apply( Framebuffer &fb ) const;
|
virtual void apply( Framebuffer &fb ) const;
|
||||||
void clear( void );
|
void clear( void );
|
||||||
|
|
||||||
@@ -109,11 +109,18 @@ namespace Overlay {
|
|||||||
private:
|
private:
|
||||||
int score;
|
int score;
|
||||||
|
|
||||||
|
/* use the TCP timeout algorithm to measure appropriate echo prediction timeout */
|
||||||
|
bool RTT_hit;
|
||||||
|
double SRTT, RTTVAR;
|
||||||
|
int prediction_len( void );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void new_user_byte( char the_byte, const Framebuffer &fb, int prediction_len );
|
void cull( const Framebuffer &fb );
|
||||||
|
void new_user_byte( char the_byte, const Framebuffer &fb );
|
||||||
void calculate_score( const Framebuffer &fb );
|
void calculate_score( const Framebuffer &fb );
|
||||||
|
|
||||||
PredictionEngine() : score( 0 ) {}
|
PredictionEngine() : score( 0 ), RTT_hit( false ), SRTT( 1000 ), RTTVAR( 500 ) {}
|
||||||
|
|
||||||
int get_score( void ) { return score; }
|
int get_score( void ) { return score; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user