/bin/sh and 32-bit arithmetics [CORRECTED]

Alex Semenyaka alexs at snark.ratmir.ru
Sat Apr 19 18:10:51 PDT 2003

I'm EXTREMELY sorry about the previous wrong posting, just mixed the header
fields. Sorry again! Here is the correct one.
Especially sorry to those guys whose addresses get into the Subject line. Just
a mistake, nothing personal :(


I've heard a lot of recommendation about where I shoud show my patch and the
results of performance changes because of it. So I gathered all advices into
To: and CC: fields. Sorry, if there are unnecessary addresses (which then?).
Also as I was told the final patch I've send as the PR.

Brief description what was done: I've chanched the arithmitics in the /bin/sh
from 32 bits to 64 bits. There are some doubts that it conforms to the
standards: it does, I have send a quotations to -standards, there were no
objections. Couple of people advuces me to use intmax_t and %jd - I've rewritten
the patch, now there is those species instead of long long and %qd. The last
question was performance, I will show the results of measurements below.
The patch can be found in the attach to this message or in the PR bin/51171.
Also I've added the overflow control to the addition, substraction and
multiplication. There is pretty small overhead (see data below) so I decided
it harmless.

First, here is the processor description in the box I've run the tests.

CPU: Intel Pentium III (1002.28-MHz 686-class CPU)
  Origin = "GenuineIntel"  Id = 0x68a  Stepping = 10
real memory  = 268435456 (262144K bytes)
avail memory = 256475136 (250464K bytes)

The tests was a set of 12 scripts with the following structure:

for x in `jot 300000`
<some single operation>

and operations were "" (just no operation, empty loop), i=$(($i+1)),
i=$(($i+$m)) (here is _two_ variables), i=$(($i*1)), i=$(($i*$m)), i=$(($i/1)),
i=$(($i/$m)), i=$(($i<<1)), i=$(($i<<$m)), i=$(($i||1)), i=$(($i||$m)),
i=$((~$i)). In the tests with two variables second one ($m) was always equal
to 1. Starting value of $i was also 1.`

I've run those twelve scripts first with the 64-bit shell without overflow
control and compared with 32-bit shell:

Test      Time           Difference        Arith.
No    Old      New      Abs       %%       operation
 0    1.35     1.36     0.04     0.99%     no op
 1    5.12     5.36     0.72     4.69%     i=$(($i+1))
 2    5.17     5.43     0.78     5.03%     i=$(($i+$a))
 3    4.39     4.57     0.55     4.18%     i=$(($i*1))
 4    4.43     4.64     0.64     4.82%     i=$(($i*$m))
 5    4.40     4.62     0.67     5.08%     i=$(($i/1))
 6    4.45     4.68     0.68     5.09%     i=$(($i/$m))
 7    5.20     6.37     3.51    22.50%     i=$(($i<<1))
 8    5.25     6.42     3.51    22.27%     i=$(($i<<$m))
 9    4.52     4.67     0.45     3.32%     i=$(($i||1))
10    4.58     4.73     0.44     3.20%     i=$(($i||$m))
11    4.30     4.38     0.25     1.94%     i=$((~$i))

As you can see, even for arithmetic-only script the overhead is not too big
except with one case: shift operation. I decided to investigate is it usual
script operation. I've went through all scripts I could find in my FreeBSD
box. I've searched them with "locate .sh | grep '\.sh$'". There were a lot
of them:

$ locate .sh | grep '\.sh$' | wc -l

But there was no any script that uses the shift operation. Good, but not
enough. I've take the script that uses arithmetics and do some other job,
ttfadmin.sh from the Abiword package. I've run in 10000 times in the loop
with both (64-bit and 32-bit) shells. As an argument it received empty
directory so no work has been done, just run, check pars, found no files,
exit. It takes 65.35 seconds in the first case and 65.30 second in the second
one. So the the time that arithmetics takes during the real script execution
is too small in comparison to total running time (obviously: arithmetics
is in-core calculations while any script usually run some external programs
etc, and at least I/O is involved).

Then I've run tests with the addition and multiplication to compare 64-bit
shells compiled without the overview control and with it. In the last case
I've turned that control on by setting corresponding command line option
(-O in my patch). Here are results:

 1    5.24     5.26     0.08     0.51%
 2    5.31     5.34     0.08     0.50%
 3    4.53     4.57     0.14     1.03%
 4    4.60     4.65     0.14     1.01%

You can see, the difference is just negligible. 

So I hope I've answered all questions were asked about that 64-bit modification.
All apprehensions are, I hope, dismissed. Probably, after the last look of
the responsible person it can be committed, am I right?


								SY, Alex

More information about the freebsd-performance mailing list