in src/throughputmanagement.c [84:255]
void run_ntttcp_throughput_management(struct ntttcp_test_endpoint *tep)
{
uint n = 0;
uint i = 0;
double elapsed_sec = 0.0;
struct timeval now;
double actual_test_time = 0;
struct report_segment last_checkpoint;
uint64_t total_bytes_warmup = 0;
uint64_t total_bytes_duration = 0;
uint64_t nbytes;
uint total_test_threads = tep->total_threads;
/* light is already turned on before entering this function */
/* Now the ntttcp test traffic is running now */
tep->state = TEST_RUNNING;
/* run the timer. it will trigger turn_off_light() after timer timeout */
run_test_timer(tep->negotiated_test_cycle_time);
/* 1) run test warm-up, if it is specified */
if (tep->test->warmup > 0) {
gettimeofday(&last_checkpoint.time, NULL);
last_checkpoint.bytes = 0;
elapsed_sec = 0;
while (elapsed_sec < (double)tep->test->warmup) {
/*
* wait 0.5 second, or 1000 test status poll cycles.
* we don't roll up the warmup bytes into final throughput report,
* so we don't care the time accuracy
*/
usleep(THROUGHPUT_INTERVAL_U_SEC); /* 500000 micro-seconds */
last_checkpoint = report_real_time_throughput(tep, last_checkpoint, total_test_threads);
elapsed_sec += last_checkpoint.interval_sec;
/* if test was interrupted by CTRL + C */
if (!is_light_turned_on()) {
PRINT_INFO("Test was interrupted.");
goto END;
}
}
PRINT_INFO("Test warmup completed.");
/*
* 1) reset each stream's total_bytes_transferred counter to 0 (discard warmup bytes)
* 2) do a simple stats for how many bytes transferred in this warmup stage
*/
for (n = 0; n < total_test_threads; n++) {
if (tep->test->client_role == true) {
total_bytes_warmup += (uint64_t)__sync_lock_test_and_set(&(tep->client_streams[n]->total_bytes_transferred), 0);
} else {
/* exclude the sync thread (only receiver has a thread for sync) */
if (tep->server_streams[n]->is_sync_thread == true)
continue;
total_bytes_warmup += (uint64_t)__sync_lock_test_and_set(&(tep->server_streams[n]->total_bytes_transferred), 0);
}
}
}
/* 2) now, let's run the real test duration */
elapsed_sec = 0; /* reset the counter */
last_checkpoint.bytes = 0; /* the counters in streams have been reset to 0 above */
gettimeofday(&now, NULL); /* reset the timestamp to now */
last_checkpoint.time = now;
tep->start_time = now;
/* calculate the initial resource usage */
get_cpu_usage(tep->results->init_cpu_usage);
get_cpu_usage_from_proc_stat(tep->results->init_cpu_ps);
get_tcp_retrans(tep->results->init_tcp_retrans);
tep->results->init_tx_packets = get_single_value_from_os_file(tep->test->show_interface_packets, "tx");
tep->results->init_rx_packets = get_single_value_from_os_file(tep->test->show_interface_packets, "rx");
tep->results->init_interrupts = get_interrupts_from_proc_by_dev(tep->test->show_dev_interrupts);
while (is_light_turned_on()) {
/*
* Wait 500 micro-seconds. We don't want to pull the status too often.
* But, we also don't want to wait too long time;
* otherwise, in the case of CTRL+C, the test streams have been stopped by CTRL+C (then light is turned off), but we are still waiting here
* which will make the "actual_test_time" longer than actual stream run time,
* and eventually make the final throughput reported inaccurate (will be lower than actual throughput)
*/
usleep(TEST_STATUS_POLL_INTERVAL_U_SEC);
check_bandwidth_limit(tep);
/* if we have already waited 1000 poll times (0.5 second), then let's report the throughput */
i++;
if (i == THROUGHPUT_INTERVAL_POLLS) {
last_checkpoint = report_real_time_throughput(tep, last_checkpoint, total_test_threads);
i = 0; /* reset the counter */
elapsed_sec += last_checkpoint.interval_sec;
}
/* if test duration time is reached, then exit this stage */
if (elapsed_sec > tep->test->duration)
break;
}
/* calculate the end resource usage */
get_cpu_usage(tep->results->final_cpu_usage);
get_cpu_usage_from_proc_stat(tep->results->final_cpu_ps);
get_tcp_retrans(tep->results->final_tcp_retrans);
tep->results->final_tx_packets = get_single_value_from_os_file(tep->test->show_interface_packets, "tx");
tep->results->final_rx_packets = get_single_value_from_os_file(tep->test->show_interface_packets, "rx");
tep->results->final_interrupts = get_interrupts_from_proc_by_dev(tep->test->show_dev_interrupts);
gettimeofday(&now, NULL);
tep->end_time = now;
/* calculate the actual test run time */
actual_test_time = get_time_diff(&tep->end_time, &tep->start_time);
for (n = 0; n < total_test_threads; n++) {
if (tep->test->client_role == true) {
nbytes = (uint64_t)__sync_lock_test_and_set(&(tep->client_streams[n]->total_bytes_transferred), 0);
} else {
/* exclude the sync thread (only receiver has a thread for sync) */
if (tep->server_streams[n]->is_sync_thread == true)
continue;
nbytes = (uint64_t)__sync_lock_test_and_set(&(tep->server_streams[n]->total_bytes_transferred), 0);
}
tep->results->threads[n]->total_bytes = nbytes;
tep->results->threads[n]->actual_test_time = actual_test_time;
total_bytes_duration += nbytes;
}
PRINT_INFO("Test run completed.");
tep->results->total_bytes = total_bytes_duration;
tep->results->actual_test_time = actual_test_time;
/*
* 3) wait, if cool-down specified. there are some possibilities:
* a) "-C" is specified by user, then Cooldown here.
* b) "-C" is not specified (Cooldown time is 0), but the total test cycle time negotiated with remote peer,
* is longer than the local one, then the excess time will be treated as Cooldown.
* Example:
* This endpoint is running with: warmup: 5, duration: 60, cooldown: 0
* Remote endpoint is running with: warmup: 10, duration: 90, cooldown: 10
* Then, this endpoint will have 110 secs of test cycle time (total time), which is negotiated with remote endpoint (use the max one);
* Then, this endpoint will have 45 seconds of cooldown time (= 110 - 5 - 60)
*/
if (tep->negotiated_test_cycle_time - tep->test->warmup - tep->test->duration > 0)
PRINT_INFO("Test cooldown is in progress...");
wait_light_off();
PRINT_INFO("Test cycle finished.");
END:
if (tep->test->client_role == true && tep->test->no_synch == false) {
/*
* if actual_test_time < tep->negotiated_test_cycle_time;
* then this indicates that in the sender side, test is being interrupted.
* hence, tell receiver about this.
*/
if (actual_test_time < tep->negotiated_test_cycle_time) {
tell_receiver_test_exit(tep->synch_socket);
}
close(tep->synch_socket);
}
tep->state = TEST_FINISHED;
return;
}