diff mbox

[1/2] performance: odp_pktio_perf: fix potential overflow for send_duration

Message ID 1438870038-25155-2-git-send-email-ivan.khoronzhuk@linaro.org
State New
Headers show

Commit Message

Ivan Khoronzhuk Aug. 6, 2015, 2:07 p.m. UTC
The direct comparing of "cur_cycles" and "end_cycles" is not valid,
as "end_cycles" can be overflowed and comparison will give wrong
result. So use odp_time_diff_cycles() for that, as it takes in
account cycles overflow.

Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
---
 test/performance/odp_pktio_perf.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

Comments

Stuart Haslam Aug. 6, 2015, 4:44 p.m. UTC | #1
On Thu, Aug 06, 2015 at 05:07:17PM +0300, Ivan Khoronzhuk wrote:
> The direct comparing of "cur_cycles" and "end_cycles" is not valid,
> as "end_cycles" can be overflowed and comparison will give wrong
> result. So use odp_time_diff_cycles() for that, as it takes in
> account cycles overflow.
> 
> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
> ---
>  test/performance/odp_pktio_perf.c | 9 ++++-----
>  1 file changed, 4 insertions(+), 5 deletions(-)
> 
> diff --git a/test/performance/odp_pktio_perf.c b/test/performance/odp_pktio_perf.c
> index fcbc4ec..8f1daeb 100644
> --- a/test/performance/odp_pktio_perf.c
> +++ b/test/performance/odp_pktio_perf.c
> @@ -303,7 +303,7 @@ static void *run_thread_tx(void *arg)
>  	int thr_id;
>  	odp_queue_t outq;
>  	pkt_tx_stats_t *stats;
> -	uint64_t next_tx_cycles, end_cycles, cur_cycles;
> +	uint64_t next_tx_cycles, end_cycles, cur_cycles, send_duration;
>  	uint64_t burst_gap_cycles;
>  	uint32_t batch_len;
>  	int unsent_pkts = 0;
> @@ -331,12 +331,11 @@ static void *run_thread_tx(void *arg)
>  
>  	odp_barrier_wait(&globals->tx_barrier);
>  
> +	send_duration = odp_time_ns_to_cycles(targs->duration * ODP_TIME_SEC);
>  	cur_cycles     = odp_time_cycles();
>  	next_tx_cycles = cur_cycles;
> -	end_cycles     = cur_cycles +
> -			 odp_time_ns_to_cycles(targs->duration * ODP_TIME_SEC);
> -
> -	while (cur_cycles < end_cycles) {
> +	end_cycles     = cur_cycles + send_duration;
> +	while (odp_time_diff_cycles(cur_cycles, end_cycles) < send_duration) {

This isn't right. The initial condition here is that the difference is
exactly equal to send_duration, so this loop won't be entered at all.

I would have thought the right way to fix this is to record the
start_cycles then do;

while (odp_time_diff_cycles(start_cycles, cur_cycles) < send_duration) {

It looks like odp_time_diff_cycles() as it assumes a wrap when t1==t2,
but I think that should be fixed to just return 0.

How often does your counter overflow? there's still going to be a problem
if it overflows in less than targs->duration seconds, if that's possible
though it's probably not a suitable counter for this purpose.
Ivan Khoronzhuk Aug. 6, 2015, 5:06 p.m. UTC | #2
Hi, Stuart

On 06.08.15 19:44, Stuart Haslam wrote:
> On Thu, Aug 06, 2015 at 05:07:17PM +0300, Ivan Khoronzhuk wrote:
>> The direct comparing of "cur_cycles" and "end_cycles" is not valid,
>> as "end_cycles" can be overflowed and comparison will give wrong
>> result. So use odp_time_diff_cycles() for that, as it takes in
>> account cycles overflow.
>>
>> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
>> ---
>>   test/performance/odp_pktio_perf.c | 9 ++++-----
>>   1 file changed, 4 insertions(+), 5 deletions(-)
>>
>> diff --git a/test/performance/odp_pktio_perf.c b/test/performance/odp_pktio_perf.c
>> index fcbc4ec..8f1daeb 100644
>> --- a/test/performance/odp_pktio_perf.c
>> +++ b/test/performance/odp_pktio_perf.c
>> @@ -303,7 +303,7 @@ static void *run_thread_tx(void *arg)
>>   	int thr_id;
>>   	odp_queue_t outq;
>>   	pkt_tx_stats_t *stats;
>> -	uint64_t next_tx_cycles, end_cycles, cur_cycles;
>> +	uint64_t next_tx_cycles, end_cycles, cur_cycles, send_duration;
>>   	uint64_t burst_gap_cycles;
>>   	uint32_t batch_len;
>>   	int unsent_pkts = 0;
>> @@ -331,12 +331,11 @@ static void *run_thread_tx(void *arg)
>>
>>   	odp_barrier_wait(&globals->tx_barrier);
>>
>> +	send_duration = odp_time_ns_to_cycles(targs->duration * ODP_TIME_SEC);
>>   	cur_cycles     = odp_time_cycles();
>>   	next_tx_cycles = cur_cycles;
>> -	end_cycles     = cur_cycles +
>> -			 odp_time_ns_to_cycles(targs->duration * ODP_TIME_SEC);
>> -
>> -	while (cur_cycles < end_cycles) {
>> +	end_cycles     = cur_cycles + send_duration;
>> +	while (odp_time_diff_cycles(cur_cycles, end_cycles) < send_duration) {
>
> This isn't right. The initial condition here is that the difference is
> exactly equal to send_duration, so this loop won't be entered at all.

That's why I had sent v2

>
> I would have thought the right way to fix this is to record the
> start_cycles then do;

It was my zero version. It requires more changes w/o reasons.

>
> while (odp_time_diff_cycles(start_cycles, cur_cycles) < send_duration) {
>
> It looks like odp_time_diff_cycles() as it assumes a wrap when t1==t2,
> but I think that should be fixed to just return 0.

Now it's not changed, so fix is correct.

>
> How often does your counter overflow? there's still going to be a problem

It's more then possible.

> if it overflows in less than targs->duration seconds, if that's possible

It has nothing to do with duration. You never know the current counter
state when start the test. Do you think you reset it at init? It can
be in any state at test time.

> though it's probably not a suitable counter for this purpose.

counter is always 64bit according to the API. It cannot be another,
as all ODP test based on it ). The freq can be ~ CPU freq.



>
Ivan Khoronzhuk Aug. 6, 2015, 5:29 p.m. UTC | #3
On 06.08.15 20:06, Ivan Khoronzhuk wrote:
> Hi, Stuart
>
> On 06.08.15 19:44, Stuart Haslam wrote:
>> On Thu, Aug 06, 2015 at 05:07:17PM +0300, Ivan Khoronzhuk wrote:
>>> The direct comparing of "cur_cycles" and "end_cycles" is not valid,
>>> as "end_cycles" can be overflowed and comparison will give wrong
>>> result. So use odp_time_diff_cycles() for that, as it takes in
>>> account cycles overflow.
>>>
>>> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
>>> ---
>>>   test/performance/odp_pktio_perf.c | 9 ++++-----
>>>   1 file changed, 4 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/test/performance/odp_pktio_perf.c
>>> b/test/performance/odp_pktio_perf.c
>>> index fcbc4ec..8f1daeb 100644
>>> --- a/test/performance/odp_pktio_perf.c
>>> +++ b/test/performance/odp_pktio_perf.c
>>> @@ -303,7 +303,7 @@ static void *run_thread_tx(void *arg)
>>>       int thr_id;
>>>       odp_queue_t outq;
>>>       pkt_tx_stats_t *stats;
>>> -    uint64_t next_tx_cycles, end_cycles, cur_cycles;
>>> +    uint64_t next_tx_cycles, end_cycles, cur_cycles, send_duration;
>>>       uint64_t burst_gap_cycles;
>>>       uint32_t batch_len;
>>>       int unsent_pkts = 0;
>>> @@ -331,12 +331,11 @@ static void *run_thread_tx(void *arg)
>>>
>>>       odp_barrier_wait(&globals->tx_barrier);
>>>
>>> +    send_duration = odp_time_ns_to_cycles(targs->duration *
>>> ODP_TIME_SEC);
>>>       cur_cycles     = odp_time_cycles();
>>>       next_tx_cycles = cur_cycles;
>>> -    end_cycles     = cur_cycles +
>>> -             odp_time_ns_to_cycles(targs->duration * ODP_TIME_SEC);
>>> -
>>> -    while (cur_cycles < end_cycles) {
>>> +    end_cycles     = cur_cycles + send_duration;
>>> +    while (odp_time_diff_cycles(cur_cycles, end_cycles) <
>>> send_duration) {
>>
>> This isn't right. The initial condition here is that the difference is
>> exactly equal to send_duration, so this loop won't be entered at all.
>
> That's why I had sent v2
>
>>
>> I would have thought the right way to fix this is to record the
>> start_cycles then do;
>
> It was my zero version. It requires more changes w/o reasons.
>

But I have no objection to back to it. It allows a little more gap to
avoid overlap.

>
>
>>
>
Stuart Haslam Aug. 7, 2015, 9:31 a.m. UTC | #4
On Thu, Aug 06, 2015 at 08:06:18PM +0300, Ivan Khoronzhuk wrote:
> Hi, Stuart
> 
> On 06.08.15 19:44, Stuart Haslam wrote:
> >On Thu, Aug 06, 2015 at 05:07:17PM +0300, Ivan Khoronzhuk wrote:
> >>The direct comparing of "cur_cycles" and "end_cycles" is not valid,
> >>as "end_cycles" can be overflowed and comparison will give wrong
> >>result. So use odp_time_diff_cycles() for that, as it takes in
> >>account cycles overflow.
> >>
> >>Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
> >>---
> >>  test/performance/odp_pktio_perf.c | 9 ++++-----
> >>  1 file changed, 4 insertions(+), 5 deletions(-)
> >>
> >>diff --git a/test/performance/odp_pktio_perf.c b/test/performance/odp_pktio_perf.c
> >>index fcbc4ec..8f1daeb 100644
> >>--- a/test/performance/odp_pktio_perf.c
> >>+++ b/test/performance/odp_pktio_perf.c
> >>@@ -303,7 +303,7 @@ static void *run_thread_tx(void *arg)
> >>  	int thr_id;
> >>  	odp_queue_t outq;
> >>  	pkt_tx_stats_t *stats;
> >>-	uint64_t next_tx_cycles, end_cycles, cur_cycles;
> >>+	uint64_t next_tx_cycles, end_cycles, cur_cycles, send_duration;
> >>  	uint64_t burst_gap_cycles;
> >>  	uint32_t batch_len;
> >>  	int unsent_pkts = 0;
> >>@@ -331,12 +331,11 @@ static void *run_thread_tx(void *arg)
> >>
> >>  	odp_barrier_wait(&globals->tx_barrier);
> >>
> >>+	send_duration = odp_time_ns_to_cycles(targs->duration * ODP_TIME_SEC);
> >>  	cur_cycles     = odp_time_cycles();
> >>  	next_tx_cycles = cur_cycles;
> >>-	end_cycles     = cur_cycles +
> >>-			 odp_time_ns_to_cycles(targs->duration * ODP_TIME_SEC);
> >>-
> >>-	while (cur_cycles < end_cycles) {
> >>+	end_cycles     = cur_cycles + send_duration;
> >>+	while (odp_time_diff_cycles(cur_cycles, end_cycles) < send_duration) {
> >
> >This isn't right. The initial condition here is that the difference is
> >exactly equal to send_duration, so this loop won't be entered at all.
> 
> That's why I had sent v2
> 
> >
> >I would have thought the right way to fix this is to record the
> >start_cycles then do;
> 
> It was my zero version. It requires more changes w/o reasons.
> 
> >
> >while (odp_time_diff_cycles(start_cycles, cur_cycles) < send_duration) {
> >
> >It looks like odp_time_diff_cycles() as it assumes a wrap when t1==t2,
> >but I think that should be fixed to just return 0.
> 
> Now it's not changed, so fix is correct.
> 
> >
> >How often does your counter overflow? there's still going to be a problem
> 
> It's more then possible.
> 
> >if it overflows in less than targs->duration seconds, if that's possible
> 
> It has nothing to do with duration. You never know the current counter
> state when start the test. Do you think you reset it at init? It can
> be in any state at test time.

Duration is important, you can't measure a 60 second interval in this
way using a counter that wraps every 20 seconds. I asked because I wasn't
sure if you were actually hitting an issue with this code or fixing a
theoretical one, given that a 64-bit counter will wrap every couple of
centuries or so, I thought you may be using a 32-bit counter.

> >though it's probably not a suitable counter for this purpose.
> 
> counter is always 64bit according to the API. It cannot be another,
> as all ODP test based on it ). The freq can be ~ CPU freq.
> 

It has to return a 64-bit value but it's not specified that it has to be
a 64-bit counter or what frequency it runs at.. we should probably add
some guidelines for acceptable ranges though.

--
Stuart.
diff mbox

Patch

diff --git a/test/performance/odp_pktio_perf.c b/test/performance/odp_pktio_perf.c
index fcbc4ec..8f1daeb 100644
--- a/test/performance/odp_pktio_perf.c
+++ b/test/performance/odp_pktio_perf.c
@@ -303,7 +303,7 @@  static void *run_thread_tx(void *arg)
 	int thr_id;
 	odp_queue_t outq;
 	pkt_tx_stats_t *stats;
-	uint64_t next_tx_cycles, end_cycles, cur_cycles;
+	uint64_t next_tx_cycles, end_cycles, cur_cycles, send_duration;
 	uint64_t burst_gap_cycles;
 	uint32_t batch_len;
 	int unsent_pkts = 0;
@@ -331,12 +331,11 @@  static void *run_thread_tx(void *arg)
 
 	odp_barrier_wait(&globals->tx_barrier);
 
+	send_duration = odp_time_ns_to_cycles(targs->duration * ODP_TIME_SEC);
 	cur_cycles     = odp_time_cycles();
 	next_tx_cycles = cur_cycles;
-	end_cycles     = cur_cycles +
-			 odp_time_ns_to_cycles(targs->duration * ODP_TIME_SEC);
-
-	while (cur_cycles < end_cycles) {
+	end_cycles     = cur_cycles + send_duration;
+	while (odp_time_diff_cycles(cur_cycles, end_cycles) < send_duration) {
 		unsigned alloc_cnt = 0, tx_cnt;
 
 		if (cur_cycles < next_tx_cycles) {