Performance improvement to strnlen().
Lee Thomas
lee_thomas at aslantools.com
Sat May 25 20:27:16 UTC 2013
Hello FreeBSD devs,
I have found a performance improvement to libc's strnlen().
lib/libc/string/strnlen.c is a trivial byte-by-byte implementation,
where strlen.c has a smarter word-by-word implementation. I have
implemented strnlen similarly to strlen. It runs about 4x as fast, at
the cost of a binary codesize increase from 30 bytes to 221.
In writing this I needed a test, and there isn't one in
tools/regression/lib/libc/string, so I wrote a unit test for strnlen.
This really only makes sense for a word-by-word implementation, as it
tests each combination of string and limit length, overread characters,
and starting alignment.
Could someone please review these patches? I am not very experienced in
C, and am even less experienced with FreeBSD's style guidelines, so they
likely have a bunch of style and idiom issues. Even if one or both of
them prove not worth committing, it would still be useful for my
learning.
If/When these patches prove worthy of submitting, what is the next step
after that? Should I submit a PR, or is there some other process? This
code is quite similar to the existing strlen.c, and doesn't do anything
fancy with e.g. endianness, but I haven't tested it for correctness or
performance on anything other than x86...
And finally, there is some other low-hanging fruit in the other strn*
functions. Would it be worth it for me to give those the same treatment?
Thanks,
Lee Thomas
Test platform:
$uname -a
FreeBSD LeeDesktop 9.1-STABLE FreeBSD 9.1-STABLE #15 r250831: Mon May
20 17:31:28 EDT 2013
lthomas at LeeDesktop:/usr/obj/usr/src/sys/NOSOUND amd64
$dmesg | grep CPU:
CPU: Intel(R) Xeon(R) CPU X5650 @ 2.67GHz (2666.81-MHz
K8-class CPU)
$clang --version
FreeBSD clang version 3.2 (tags/RELEASE_32/final 170710) 20121221
Target: x86_64-unknown-freebsd9.1
Thread model: posix
My timing test was a file of 10000 strings, of uniformly random length,
50% between 0 and 20 bytes long, and 50% between 21 and 1000 bytes long.
Each was filled with random generated bytes in the range [1, 255]. The
test executables run their strlen on each string in the file 1000 times,
and a shell script ran the test programs alternately 100 times. Here are
the clang results; gcc results are roughly the same. I will share the
actual timing code if someone wants it, but it is pretty ugly C++ and
shell and I don't guarantee it working :-).
Results:
x ./times_bsd_strnlen.txt
+ ./times_my_strnlen.txt
+--------------------------------------------------------------------------+
|+
x|
|+
x|
|+
x|
|+
x|
|+
x|
|+
x|
|+
x|
|+
x|
|+
x|
|+
x|
|+
x|
|+
x|
|+
x|
|+
x|
|+
x|
|+
x|
|+
x|
|A
A|
+--------------------------------------------------------------------------+
N Min Max Median Avg
Stddev
x 101 1.8685486 1.8693889 1.8687506 1.8687894
0.0001484903
+ 101 0.42704683 0.42779486 0.42712813 0.42715597
0.00010681494
Difference at 95.0% confidence
-1.44163 +/- 3.56739e-05
-77.1426% +/- 0.00190893%
(Student's t, pooled s = 0.000129342)
Note: I manually shortened the histogram, as it was 100 lines long of
exactly the same.
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: strnlen.diff
URL: <http://lists.freebsd.org/pipermail/freebsd-hackers/attachments/20130525/a8e3fc6d/attachment.ksh>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: test-strnlen.diff
URL: <http://lists.freebsd.org/pipermail/freebsd-hackers/attachments/20130525/a8e3fc6d/attachment-0001.ksh>
More information about the freebsd-hackers
mailing list