Page MenuHomeFreeBSD

libc: scalar strnlen() in RISC-V assembly
Needs ReviewPublic

Authored by strajabot on Aug 5 2024, 2:29 PM.
Tags
None
Referenced Files
Unknown Object (File)
Fri, Oct 10, 8:54 AM
Unknown Object (File)
Fri, Oct 10, 8:54 AM
Unknown Object (File)
Fri, Oct 10, 8:54 AM
Unknown Object (File)
Fri, Oct 10, 2:42 AM
Unknown Object (File)
Sun, Sep 28, 4:47 PM
Unknown Object (File)
Thu, Sep 25, 12:36 PM
Unknown Object (File)
Wed, Sep 24, 11:18 AM
Unknown Object (File)
Wed, Sep 24, 6:57 AM

Details

Reviewers
fuz
emaste
mhorne
Group Reviewers
riscv
Summary

Optimized implementation of strnlen() in RISC-V assembly

Performance was measured using strperf on a HiFive Unmatched (SiFive HF105-001) board.

os: FreeBSD
arch: riscv
        │ strnlen_baseline │           strnlen_scalar            │
        │      sec/op      │   sec/op     vs base                │
Short          787.0µ ± 0%   430.9µ ± 1%  -45.24% (p=0.000 n=20)
Mid            621.6µ ± 0%   195.1µ ± 1%  -68.61% (p=0.000 n=20)
Long           569.4µ ± 1%   100.6µ ± 0%  -82.34% (p=0.000 n=20)
geomean        653.1µ        203.7µ       -68.81%

        │ strnlen_baseline │            strnlen_scalar            │
        │      MiB/s       │    MiB/s     vs base                 │
Short           158.8 ± 0%    290.1 ± 1%   +82.62% (p=0.000 n=20)
Mid             201.1 ± 0%    640.6 ± 1%  +218.59% (p=0.000 n=20)
Long            219.5 ± 1%   1242.9 ± 0%  +466.19% (p=0.000 n=20)
geomean         191.4         613.5       +220.57%
Test Plan

The test suite currently has no test for strnlen. I've tested the function with all different alignments and maxlen up to 128...

All tests that pass before, pass after adding the changes.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 67246
Build 64129: arc lint + arc unit

Event Timeline

Check if you can add a unit test for strnlen. You should be able to adapt the existing memchr unit test for this purpose.

Code looks reasonable.

mhorne requested changes to this revision.Aug 19 2025, 6:52 PM
mhorne added a subscriber: mhorne.
mhorne added inline comments.
lib/libc/riscv/string/strnlen.S
10–23

Which of these comment blocks is the real one?

This revision now requires changes to proceed.Aug 19 2025, 6:52 PM
lib/libc/riscv/string/strnlen.S
10–23

Okay I seem to have misunderstood; the latter is a detailed accounting of register usage. But please check both for their accuracy and formatting. The top comment does not properly describe the arguments to strnlen(3).

I went through this code. No bugs detected. The parameter list looks flawed to me as explained.

lib/libc/riscv/string/strnlen.S
14

This looks like a parameter list, but a2 is not a parameter (not used like a parameter in the code, not mentioned in man strnlen) and a1 should be called maxlen

87

This MV of the loop could probably be transferred to the beginning of find_zero if for instance register A7 was used here instead of A6 but maybe very long strings in very large quantities are not processed so often this would make sense.

  • fixup: comments in strnlen

@mhorne Are you happy with the updated code? I would like to land the changeset soon.