diff --git a/include/yojimbo_network_info.h b/include/yojimbo_network_info.h index 756dcb53..0dc40af2 100644 --- a/include/yojimbo_network_info.h +++ b/include/yojimbo_network_info.h @@ -40,7 +40,9 @@ namespace yojimbo float minRTT; ///< Minimum RTT seen over the last n samples (see rtt_history_size in reliable config). This is a more stable and accurate RTT value under typical Wi-Fi jitter. float maxRTT; ///< Maximum RTT seen over the last n samples. float averageRTT; ///< Average RTT seen over the last n samples. - float jitter; ///< Jitter relative to min RTT over the last n samples. + float averageJitter; ///< Average jitter relative to min RTT over the last n samples. + float maxJitter; ///< Max jitter relative to min RTT seen over the last n samples. + float stddevJitter; ///< One standard deviation of jitter relative to average RTT over the last n samples. float packetLoss; ///< Packet loss percent. float sentBandwidth; ///< Sent bandwidth (kbps). float receivedBandwidth; ///< Received bandwidth (kbps). diff --git a/reliable/reliable.c b/reliable/reliable.c index 14d4c53d..a0bcb976 100644 --- a/reliable/reliable.c +++ b/reliable/reliable.c @@ -511,7 +511,9 @@ struct reliable_endpoint_t float rtt_min; float rtt_max; float rtt_avg; - float jitter; + float jitter_avg_vs_min_rtt; + float jitter_max_vs_min_rtt; + float jitter_stddev_vs_avg_rtt; float packet_loss; float sent_bandwidth_kbps; float received_bandwidth_kbps; @@ -1384,7 +1386,7 @@ void reliable_endpoint_update( struct reliable_endpoint_t * endpoint, double tim } } - // calculate jitter + // calculate average jitter vs. min rtt { float sum = 0.0f; int count = 0; @@ -1398,11 +1400,51 @@ void reliable_endpoint_update( struct reliable_endpoint_t * endpoint, double tim } if ( count > 0 ) { - endpoint->jitter = sum / (float)count; + endpoint->jitter_avg_vs_min_rtt = sum / (float)count; } else { - endpoint->jitter = 0.0f; + endpoint->jitter_avg_vs_min_rtt = 0.0f; + } + } + + // calculate max jitter vs. min rtt + { + float max = 0.0f; + for ( int i = 0; i < endpoint->config.rtt_history_size; i++ ) + { + if ( endpoint->rtt_history_buffer[i] >= 0.0f ) + { + float difference = ( endpoint->rtt_history_buffer[i] - endpoint->rtt_min ); + if ( difference > max ) + { + max = difference; + } + } + } + endpoint->jitter_max_vs_min_rtt = max; + } + + // calculate stddev jitter vs. avg rtt + { + float sum = 0.0f; + int count = 0; + for ( int i = 0; i < endpoint->config.rtt_history_size; i++ ) + { + if ( endpoint->rtt_history_buffer[i] >= 0.0f ) + { + float deviation = ( endpoint->rtt_history_buffer[i] - endpoint->rtt_min ); + sum += deviation * deviation; + count++; + } + } + if ( count > 0 ) + { + endpoint->jitter_stddev_vs_avg_rtt = pow( sum / (float)count, 0.5f ); + } + else + { + endpoint->jitter_stddev_vs_avg_rtt = 0.0f; } } @@ -1592,10 +1634,23 @@ float reliable_endpoint_rtt_avg( struct reliable_endpoint_t * endpoint ) return endpoint->rtt_avg; } -float reliable_endpoint_jitter( struct reliable_endpoint_t * endpoint ) +float reliable_endpoint_jitter_avg_vs_min_rtt( struct reliable_endpoint_t * endpoint ) +{ + reliable_assert( endpoint ); + return endpoint->jitter_avg_vs_min_rtt; +} + +float reliable_endpoint_jitter_max_vs_min_rtt( struct reliable_endpoint_t * endpoint ) +{ + reliable_assert( endpoint ); + return endpoint->jitter_max_vs_min_rtt; +} + + +float reliable_endpoint_jitter_stddev_vs_avg_rtt( struct reliable_endpoint_t * endpoint ) { reliable_assert( endpoint ); - return endpoint->jitter; + return endpoint->jitter_stddev_vs_avg_rtt; } float reliable_endpoint_packet_loss( struct reliable_endpoint_t * endpoint ) diff --git a/reliable/reliable.h b/reliable/reliable.h index 2aafb07f..e3c8e954 100644 --- a/reliable/reliable.h +++ b/reliable/reliable.h @@ -138,7 +138,7 @@ void reliable_endpoint_reset( struct reliable_endpoint_t * endpoint ); void reliable_endpoint_update( struct reliable_endpoint_t * endpoint, double time ); -float reliable_endpoint_rtt( struct reliable_endpoint_t * endpoint ); +float reliable_endpoint_rtt( struct reliable_endpoint_t * endpoint ); // exponentially smoothed moving average float reliable_endpoint_rtt_min( struct reliable_endpoint_t * endpoint ); @@ -146,7 +146,11 @@ float reliable_endpoint_rtt_max( struct reliable_endpoint_t * endpoint ); float reliable_endpoint_rtt_avg( struct reliable_endpoint_t * endpoint ); -float reliable_endpoint_jitter( struct reliable_endpoint_t * endpoint ); +float reliable_endpoint_jitter_avg_vs_min_rtt( struct reliable_endpoint_t * endpoint ); + +float reliable_endpoint_jitter_max_vs_min_rtt( struct reliable_endpoint_t * endpoint ); + +float reliable_endpoint_jitter_stddev_vs_avg_rtt( struct reliable_endpoint_t * endpoint ); float reliable_endpoint_packet_loss( struct reliable_endpoint_t * endpoint ); diff --git a/source/yojimbo_base_client.cpp b/source/yojimbo_base_client.cpp index adb611d6..eab88c26 100644 --- a/source/yojimbo_base_client.cpp +++ b/source/yojimbo_base_client.cpp @@ -284,7 +284,9 @@ namespace yojimbo info.minRTT = reliable_endpoint_rtt_min( m_endpoint ); info.maxRTT = reliable_endpoint_rtt_min( m_endpoint ); info.averageRTT = reliable_endpoint_rtt_avg( m_endpoint ); - info.jitter = reliable_endpoint_jitter( m_endpoint ); + info.averageJitter = reliable_endpoint_jitter_avg_vs_min_rtt( m_endpoint ); + info.maxJitter = reliable_endpoint_jitter_max_vs_min_rtt( m_endpoint ); + info.stddevJitter = reliable_endpoint_jitter_stddev_vs_avg_rtt( m_endpoint ); info.packetLoss = reliable_endpoint_packet_loss( m_endpoint ); reliable_endpoint_bandwidth( m_endpoint, &info.sentBandwidth, &info.receivedBandwidth, &info.ackedBandwidth ); }