[LTP] [PATCH v2 2/2] ebizzy: prevent integer overflow in 64-bit systems
Vishal Chourasia
vishalc@linux.ibm.com
Tue Aug 29 12:03:01 CEST 2023
On 8/21/23 18:54, Cyril Hrubis wrote:
> Hi!
>> Signed-off-by: Vishal Chourasia <vishalc@linux.ibm.com>
>> Reviewed-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
>> Reviewed-by: Shrikanth Hegde <sshegde@linux.vnet.ibm.com>
>> ---
>> utils/benchmark/ebizzy-0.3/ebizzy.c | 7 +++----
>> 1 file changed, 3 insertions(+), 4 deletions(-)
>>
>> diff --git a/utils/benchmark/ebizzy-0.3/ebizzy.c b/utils/benchmark/ebizzy-0.3/ebizzy.c
>> index ae0981fbd..c3eac1133 100644
>> --- a/utils/benchmark/ebizzy-0.3/ebizzy.c
>> +++ b/utils/benchmark/ebizzy-0.3/ebizzy.c
>> @@ -456,7 +456,7 @@ static void start_threads(void)
>> unsigned int i;
>> struct rusage start_ru, end_ru;
>> struct timeval usr_time, sys_time;
>> - uintptr_t records_read = 0;
>> + uintptr_t records_per_sec = 0;
>> int err;
>>
>> if (verbose)
>> @@ -493,14 +493,13 @@ static void start_threads(void)
>> fprintf(stderr, "Error joining thread %d\n", i);
>> exit(1);
>> }
>> - records_read += record_thread;
>> + records_per_sec += (record_thread / elapsed);
>
> This actually introduces quite a bit rounding errors. Note that even
> with 10 second runtime we effectively throw away the last digit for each
> thread records and it's even worse for larger runtime. This kind of
> naive summing can easily add up to quite large differencies.
>
> E.g. for a machine with 256 CPUs and 10 seconds the value would be on
> average smaller by:
>
> 512 (number of threads) * 5 (average last digit) / 10 (runtime)
>
> So on average the result printed would be smaller by 256 units.
>
> Either we have to switch the records_per_sec to double and compute the
> number in floating point, which should add up fine as long as the work
> done by a threads is more or less the same.
>
> Or use uint64_t as a fixed point and use one or two bits for a fraction,
> which may be a bit safer than double and should work fine as long as
> we round properly.
>
> This should be easy to debug as well, just print the number computed by
> the method that sum first and then divide and compare it with the number
> that sums the already divided values. These two shouldn't differ much,
> ideally the should be the same.
>
To address this, We can modify the code to keep the records per second
as a `double` type until the point of printing. This ensures that we
maintain precision throughout the calculation.
diff --git a/utils/benchmark/ebizzy-0.3/ebizzy.c
b/utils/benchmark/ebizzy-0.3/ebizzy.c
index ffc439a24..f9bc41ba9 100644
--- a/utils/benchmark/ebizzy-0.3/ebizzy.c
+++ b/utils/benchmark/ebizzy-0.3/ebizzy.c
@@ -456,6 +456,7 @@ static void start_threads(void)
unsigned int i;
struct rusage start_ru, end_ru;
struct timeval usr_time, sys_time;
+ uintptr_t records = 0;
double records_per_sec = 0.0;
int err;
@@ -493,13 +494,15 @@ static void start_threads(void)
fprintf(stderr, "Error joining thread %d\n", i);
exit(1);
}
+ records += record_thread;
records_per_sec += ((double)record_thread / elapsed);
}
if (verbose)
printf("Threads finished\n");
- printf("%tu records/s\n", (uintptr_t) records_per_sec);
+ printf("Method 1: %tu records/s\n", (uintptr_t)((double)records
/ elapsed));
+ printf("Method 2: %tu records/s\n", (uintptr_t) records_per_sec);
usr_time = difftimeval(&end_ru.ru_utime, &start_ru.ru_utime);
sys_time = difftimeval(&end_ru.ru_stime, &start_ru.ru_stime);
Both methods yield the same result, confirming the accuracy of the
calculation. Here are some sample outputs:
$ ./ebizzy -S 10 -t 512
Method 1: 3049076 records/s
Method 2: 3049076 records/s
$ ./ebizzy -S 10 -t 1000
Method 1: 2273819 records/s
Method 2: 2273819 records/s
I will be sending a proper patch as reply to this thread.
vishal.c
More information about the ltp
mailing list