Skip to content

Commit 1c1a9ba

Browse files
committed
add min rtt and jitter stats
1 parent 208f5be commit 1c1a9ba

File tree

3 files changed

+89
-15
lines changed

3 files changed

+89
-15
lines changed

reliable.c

+80-13
Original file line numberDiff line numberDiff line change
@@ -508,13 +508,16 @@ struct reliable_endpoint_t
508508
struct reliable_config_t config;
509509
double time;
510510
float rtt;
511+
float rtt_min;
512+
float jitter;
511513
float packet_loss;
512514
float sent_bandwidth_kbps;
513515
float received_bandwidth_kbps;
514516
float acked_bandwidth_kbps;
515517
int num_acks;
516518
uint16_t * acks;
517519
uint16_t sequence;
520+
float * rtt_history_buffer;
518521
struct reliable_sequence_buffer_t * sent_packets;
519522
struct reliable_sequence_buffer_t * received_packets;
520523
struct reliable_sequence_buffer_t * fragment_reassembly;
@@ -556,9 +559,10 @@ void reliable_default_config( struct reliable_config_t * config )
556559
config->received_packets_buffer_size = 256;
557560
config->fragment_reassembly_buffer_size = 64;
558561
config->rtt_smoothing_factor = 0.0025f;
562+
config->rtt_history_size = 512;
559563
config->packet_loss_smoothing_factor = 0.1f;
560564
config->bandwidth_smoothing_factor = 0.1f;
561-
config->packet_header_size = 28; // note: UDP over IPv4 = 20 + 8 bytes, UDP over IPv6 = 40 + 8 bytes
565+
config->packet_header_size = 28; // note: UDP over IPv4 = 20 + 8 bytes, UDP over IPv6 = 40 + 8 bytes
562566
}
563567

564568
struct reliable_endpoint_t * reliable_endpoint_create( struct reliable_config_t * config, double time )
@@ -574,6 +578,7 @@ struct reliable_endpoint_t * reliable_endpoint_create( struct reliable_config_t
574578
reliable_assert( config->received_packets_buffer_size > 0 );
575579
reliable_assert( config->transmit_packet_function != NULL );
576580
reliable_assert( config->process_packet_function != NULL );
581+
reliable_assert( config->rtt_history_size > 0 );
577582

578583
void * allocator_context = config->allocator_context;
579584
void * (*allocate_function)(void*,size_t) = config->allocate_function;
@@ -601,7 +606,7 @@ struct reliable_endpoint_t * reliable_endpoint_create( struct reliable_config_t
601606
endpoint->config = *config;
602607
endpoint->time = time;
603608

604-
endpoint->acks = (uint16_t*) allocate_function( allocator_context, config->ack_buffer_size * sizeof( uint16_t ) );
609+
endpoint->acks = (uint16_t*) allocate_function( allocator_context, config->ack_buffer_size * sizeof(uint16_t) );
605610

606611
endpoint->sent_packets = reliable_sequence_buffer_create( config->sent_packets_buffer_size,
607612
sizeof( struct reliable_sent_packet_data_t ),
@@ -621,7 +626,14 @@ struct reliable_endpoint_t * reliable_endpoint_create( struct reliable_config_t
621626
allocate_function,
622627
free_function );
623628

624-
memset( endpoint->acks, 0, config->ack_buffer_size * sizeof( uint16_t ) );
629+
endpoint->rtt_history_buffer = (float*) allocate_function( allocator_context, config->rtt_history_size * sizeof(float) );
630+
631+
for ( int i = 0; i < config->rtt_history_size; i++ )
632+
{
633+
endpoint->rtt_history_buffer[i] = -1.0f;
634+
}
635+
636+
memset( endpoint->acks, 0, config->ack_buffer_size * sizeof(uint16_t) );
625637

626638
return endpoint;
627639
}
@@ -632,6 +644,8 @@ void reliable_endpoint_destroy( struct reliable_endpoint_t * endpoint )
632644
reliable_assert( endpoint->acks );
633645
reliable_assert( endpoint->sent_packets );
634646
reliable_assert( endpoint->received_packets );
647+
reliable_assert( endpoint->fragment_reassembly );
648+
reliable_assert( endpoint->rtt_history_buffer );
635649

636650
int i;
637651
for ( i = 0; i < endpoint->config.fragment_reassembly_buffer_size; ++i )
@@ -652,6 +666,8 @@ void reliable_endpoint_destroy( struct reliable_endpoint_t * endpoint )
652666
reliable_sequence_buffer_destroy( endpoint->received_packets );
653667
reliable_sequence_buffer_destroy( endpoint->fragment_reassembly );
654668

669+
endpoint->free_function( endpoint->allocator_context, endpoint->rtt_history_buffer );
670+
655671
endpoint->free_function( endpoint->allocator_context, endpoint );
656672
}
657673

@@ -1141,8 +1157,14 @@ void reliable_endpoint_receive_packet( struct reliable_endpoint_t * endpoint, ui
11411157
endpoint->counters[RELIABLE_ENDPOINT_COUNTER_NUM_PACKETS_ACKED]++;
11421158
sent_packet_data->acked = 1;
11431159

1144-
float rtt = (float) ( endpoint->time - sent_packet_data->time ) * 1000.0f;
1160+
const float rtt = (float) ( endpoint->time - sent_packet_data->time ) * 1000.0f;
1161+
11451162
reliable_assert( rtt >= 0.0 );
1163+
1164+
int index = ack_sequence % endpoint->config.rtt_history_size;
1165+
1166+
endpoint->rtt_history_buffer[index] = rtt;
1167+
11461168
if ( ( endpoint->rtt == 0.0f && rtt > 0.0f ) || fabs( endpoint->rtt - rtt ) < 0.00001 )
11471169
{
11481170
endpoint->rtt = rtt;
@@ -1291,13 +1313,6 @@ void reliable_endpoint_reset( struct reliable_endpoint_t * endpoint )
12911313
{
12921314
reliable_assert( endpoint );
12931315

1294-
endpoint->time = 0;
1295-
endpoint->rtt = 0;
1296-
endpoint->packet_loss = 0;
1297-
endpoint->sent_bandwidth_kbps = 0;
1298-
endpoint->received_bandwidth_kbps = 0;
1299-
endpoint->acked_bandwidth_kbps = 0;
1300-
13011316
endpoint->num_acks = 0;
13021317
endpoint->sequence = 0;
13031318

@@ -1327,7 +1342,45 @@ void reliable_endpoint_update( struct reliable_endpoint_t * endpoint, double tim
13271342
reliable_assert( endpoint );
13281343

13291344
endpoint->time = time;
1330-
1345+
1346+
// calculate min rtt
1347+
{
1348+
float min_rtt = 10000.0f;
1349+
for ( int i = 0; i < endpoint->config.rtt_history_size; i++ )
1350+
{
1351+
if ( endpoint->rtt_history_buffer[i] >= 0.0f && endpoint->rtt_history_buffer[i] < min_rtt )
1352+
{
1353+
min_rtt = endpoint->rtt_history_buffer[i];
1354+
}
1355+
}
1356+
if ( min_rtt == 10000.0f )
1357+
{
1358+
min_rtt = 0.0f;
1359+
}
1360+
endpoint->rtt_min = min_rtt;
1361+
}
1362+
1363+
// calculate jitter
1364+
{
1365+
float sum = 0.0f;
1366+
int count = 0;
1367+
for ( int i = 0; i < endpoint->config.rtt_history_size; i++ )
1368+
{
1369+
if ( endpoint->rtt_history_buffer[i] >= 0.0f )
1370+
{
1371+
sum += endpoint->rtt_history_buffer[i];
1372+
}
1373+
}
1374+
if ( count > 0 )
1375+
{
1376+
endpoint->jitter = sum / (float)count;
1377+
}
1378+
else
1379+
{
1380+
endpoint->jitter = 0.0f;
1381+
}
1382+
}
1383+
13311384
// calculate packet loss
13321385
{
13331386
uint32_t base_sequence = ( endpoint->sent_packets->sequence - endpoint->config.sent_packets_buffer_size + 1 ) + 0xFFFF;
@@ -1485,6 +1538,18 @@ float reliable_endpoint_rtt( struct reliable_endpoint_t * endpoint )
14851538
return endpoint->rtt;
14861539
}
14871540

1541+
float reliable_endpoint_rtt_min( struct reliable_endpoint_t * endpoint )
1542+
{
1543+
reliable_assert( endpoint );
1544+
return endpoint->rtt_min;
1545+
}
1546+
1547+
float reliable_endpoint_jitter( struct reliable_endpoint_t * endpoint )
1548+
{
1549+
reliable_assert( endpoint );
1550+
return endpoint->jitter;
1551+
}
1552+
14881553
float reliable_endpoint_packet_loss( struct reliable_endpoint_t * endpoint )
14891554
{
14901555
reliable_assert( endpoint );
@@ -2126,7 +2191,7 @@ void test_packets()
21262191
uint8_t packet_data[TEST_MAX_PACKET_BYTES];
21272192
uint16_t sequence = reliable_endpoint_next_packet_sequence( context.sender );
21282193
int packet_bytes = generate_packet_data( sequence, packet_data );
2129-
reliable_endpoint_send_packet( context.receiver, packet_data, packet_bytes );
2194+
reliable_endpoint_send_packet( context.sender, packet_data, packet_bytes );
21302195
}
21312196

21322197
reliable_endpoint_update( context.sender, time );
@@ -2234,13 +2299,15 @@ void test_sequence_buffer_rollover()
22342299
{
22352300
uint8_t packet_data[16];
22362301
int packet_bytes = sizeof( packet_data ) / sizeof( uint8_t );
2302+
reliable_endpoint_next_packet_sequence( context.sender );
22372303
reliable_endpoint_send_packet( context.sender, packet_data, packet_bytes );
22382304

22392305
++num_packets_sent;
22402306
}
22412307

22422308
uint8_t packet_data[TEST_MAX_PACKET_BYTES];
22432309
int packet_bytes = sizeof( packet_data ) / sizeof( uint8_t );
2310+
reliable_endpoint_next_packet_sequence( context.sender );
22442311
reliable_endpoint_send_packet( context.sender, packet_data, packet_bytes );
22452312
++num_packets_sent;
22462313

reliable.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
#define RELIABLE_ENDPOINT_NUM_COUNTERS 10
6969

7070
#define RELIABLE_MAX_PACKET_HEADER_BYTES 9
71-
#define RELIABLE_FRAGMENT_HEADER_BYTES 5
71+
#define RELIABLE_FRAGMENT_HEADER_BYTES 5
7272

7373
#define RELIABLE_LOG_LEVEL_NONE 0
7474
#define RELIABLE_LOG_LEVEL_ERROR 1
@@ -107,6 +107,7 @@ struct reliable_config_t
107107
int received_packets_buffer_size;
108108
int fragment_reassembly_buffer_size;
109109
float rtt_smoothing_factor;
110+
int rtt_history_size;
110111
float packet_loss_smoothing_factor;
111112
float bandwidth_smoothing_factor;
112113
int packet_header_size;
@@ -139,6 +140,10 @@ void reliable_endpoint_update( struct reliable_endpoint_t * endpoint, double tim
139140

140141
float reliable_endpoint_rtt( struct reliable_endpoint_t * endpoint );
141142

143+
float reliable_endpoint_rtt_min( struct reliable_endpoint_t * endpoint );
144+
145+
float reliable_endpoint_jitter( struct reliable_endpoint_t * endpoint );
146+
142147
float reliable_endpoint_packet_loss( struct reliable_endpoint_t * endpoint );
143148

144149
void reliable_endpoint_bandwidth( struct reliable_endpoint_t * endpoint, float * sent_bandwidth_kbps, float * received_bandwidth_kbps, float * acked_bandwidth_kpbs );

stats.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,13 @@ void stats_iteration( double time )
217217
float sent_bandwidth_kbps, received_bandwidth_kbps, acked_bandwidth_kbps;
218218
reliable_endpoint_bandwidth( global_context.client, &sent_bandwidth_kbps, &received_bandwidth_kbps, &acked_bandwidth_kbps );
219219

220-
printf( "%" PRIi64 " sent | %" PRIi64 " received | %" PRIi64 " acked | rtt = %dms | packet loss = %d%% | sent = %dkbps | recv = %dkbps | acked = %dkbps\n",
220+
printf( "%" PRIi64 " sent | %" PRIi64 " received | %" PRIi64 " acked | rtt avg = %dms | rtt min = %dms | jitter = %dms | packet loss = %d%% | sent = %dkbps | recv = %dkbps | acked = %dkbps\n",
221221
counters[RELIABLE_ENDPOINT_COUNTER_NUM_PACKETS_SENT],
222222
counters[RELIABLE_ENDPOINT_COUNTER_NUM_PACKETS_RECEIVED],
223223
counters[RELIABLE_ENDPOINT_COUNTER_NUM_PACKETS_ACKED],
224224
(int) reliable_endpoint_rtt( global_context.client ),
225+
(int) reliable_endpoint_rtt_min( global_context.client ),
226+
(int) reliable_endpoint_jitter( global_context.client ),
225227
(int) ( reliable_endpoint_packet_loss( global_context.client ) + 0.5f ),
226228
(int) sent_bandwidth_kbps,
227229
(int) received_bandwidth_kbps,

0 commit comments

Comments
 (0)