Fishwaldo opened a new pull request, #19856:
URL: https://github.com/apache/nuttx/pull/19856

   ## Summary
   
   Four functions in the RISC-V machine directory decide whether to work a
   register at a time by asking whether both pointers are already on a boundary.
   That is the wrong question, and in one case it produces a store that the ISA
   does not guarantee will work at all.
   
   `strlcpy` aligns only its source and then stores a whole register at a time 
to
   a destination that is aligned by luck. `memcmp`, `strncmp` and `strcmp` test
   `or` of the two pointers, so a pair that is equally misaligned falls back to
   the byte loop the word loop exists to replace.
   
   Two commits: the `strlcpy` store, then the three compares.
   
   ## Where this comes from
   
   I opened #19735 with C implementations of these routines, built around
   testing whether two pointers *agree* about where a boundary falls rather than
   whether either is already on one. While that was in review, #19781 and #19782
   landed assembly implementations covering a wider set of functions, so I have
   dropped my versions; the assembly is the better base and is faster than my C
   in most cases.
   
   This PR carries over the one idea from #19735 that did not make it across, 
and
   applies it to the code that is now in tree. It is not a re-run of that 
review.
   I will close #19735 once this lands; the part of it that belongs in the 
shared
   BSD implementation rather than an arch directory, which is what
   @xiaoxiang781216 asked for there, follows as its own PR.
   
   ## Why it matters more than a missed optimisation
   
   Misaligned access is not guaranteed on RISC-V. The base ISA permits it to be
   unsupported, and implementations differ:
   
   - where firmware emulates it, every access traps into machine mode
   - where nothing emulates it, the access faults
   
   So a routine in a machine directory cannot assume a misaligned store will
   work, whatever it might cost. `arch_strcpy.S` and `arch_memcpy.S` already 
take
   this view. `arch_strlcpy.S` does not.
   
   **This is also why QEMU is a poor place to measure or test it.** QEMU 
executes
   misaligned accesses natively at full speed, so the `strlcpy` defect is
   invisible there: correct results, no penalty, nothing to see. Every number
   below is from silicon.
   
   ## Measured
   
   EIC7700X, rv64 at 1.4 GHz, `CONFIG_RISCV_STRING_FUNCTION=y`, 32 KB operands,
   taken with the benchmark in apache/nuttx-apps#3706. `generic` is the same
   board with the machine directory disabled, included so the byte-loop rate is
   visible.
   
   Source and destination misaligned by different amounts, which is the case
   `strlcpy` gets wrong:
   
   ```
                   generic     before      after
     strlcpy         410.4        7.5      490.0 MB/s
   ```
   
   7.5 MB/s is about 178 cycles per byte, flat from 512 bytes to 32 KB, which is
   what a trapped and emulated store costs on this part. It is 55x slower than
   the generic C it replaced.
   
   Source and destination equally misaligned, which is the case the compares
   reject:
   
   ```
                   generic     before      after
     memcmp           30.7       34.4      456.0 MB/s
     strncmp          32.2       32.2      254.0 MB/s
     strcmp           41.2       40.9      280.0 MB/s
   ```
   
   Each `before` figure is the generic rate, so the word loops were not being
   entered at all.
   
   Both aligned, to show the guard costs nothing where it does not fire:
   
   ```
                    before      after
     strlcpy        2474.0     2452.0 MB/s
     memcmp          452.0      458.0 MB/s
     strncmp         266.0      256.0 MB/s
     strcmp          282.0      280.9 MB/s
   ```
   
   Pointers that genuinely disagree still take the byte loop. No unaligned 
access
   is introduced anywhere.
   
   ## Testing
   
   - Correctness: `testing/libc/arch_libc` under qemu rv64, all functions pass
     before and after. The `strlcpy` defect is a performance defect on the parts
     that emulate, so no correctness test can catch it, and none did.
   - Throughput: the benchmark in apache/nuttx-apps#3706, which sweeps sizes
     against every source and destination alignment pair. An aligned measurement
     at a single size cannot see any of this.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to