Skip to content

optimize StringPiece::find(char) for RISC-V with RVV memchr#3396

Open
Felix-Gong wants to merge 4 commits into
apache:masterfrom
Felix-Gong:riscv-stringpiece-memchr
Open

optimize StringPiece::find(char) for RISC-V with RVV memchr#3396
Felix-Gong wants to merge 4 commits into
apache:masterfrom
Felix-Gong:riscv-stringpiece-memchr

Conversation

@Felix-Gong

@Felix-Gong Felix-Gong commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Adds RVV-accelerated rvv_memchr() for byte search in StringPiece::find(char) on RISC-V.

Implementation

  • rvv_memchr() in string_compare_rvv.cc: uses RVV vector compare (vmseq) + vfirst to scan for target byte across buffer
  • Declaration in string_piece.h with BUTIL_EXPORT for shared library builds
  • RVV dispatch in string_piece.cc::find(const StringPiece, char, size_t) — routes to rvv_memchr() when RVV available, falls back to generic findT() otherwise

Performance (RISC-V SG2044, 50000 iterations)

Size glibc memchr RVV memchr Speedup
64B 229 ns 39 ns 5.8x
256B 963 ns 175 ns 5.5x
1KB 3,317 ns 753 ns 4.4x
4KB 13,764 ns 3,522 ns 3.9x
16KB 52,970 ns 13,155 ns 4.0x
64KB 207,870 ns 52,168 ns 4.0x
256KB 723,560 ns 251,868 ns 2.9x
1MB 2,877,680 ns 986,480 ns 2.9x

Dependency

Depends on #3390 (RVV memcmp for StringPiece) being merged first, as this branch is based on top of it.

Tests

  • test_butil: 724/725 passed (1 pre-existing StackTraceTest.find_symbol failure)
  • test_bvar: 64/64 passed
  • Custom memchr correctness tests: 42/42 passed
  • Custom memchr performance benchmarks: all sizes tested

This patch adds RVV-accelerated memcmp for StringPiece operations
on RISC-V 64-bit platforms.

The implementation follows glibc's official RVV pattern:
- e8m8 LMUL for maximum throughput
- Hardware-adaptive vector length via vsetvl
- vfirst.m for early-out on first difference

Performance on SOPHGO SG2044 (RVV 1.0, VLEN >= 128, GCC 15.1):
glibc 2.38 scalar memcmp (no RVV acceleration) as baseline.

  memcmp (worst-case full scan, 50000 iterations):
    64 B:   20 ns ->   6 ns  (3.4x)
   256 B:   54 ns ->  15 ns  (3.6x)
     1 KB: 120 ns ->  55 ns  (2.2x)
     4 KB: 435 ns -> 225 ns  (1.9x)
    16 KB: 1968 ns -> 1258 ns (1.6x)
    64 KB: 10962 ns -> 9044 ns (1.2x)
   256 KB: 46893 ns -> 43108 ns (1.1x)
     1 MB: 446161 ns -> 454717 ns (1.01x)

Correctness:
  - 59/59 expanded correctness tests passed (64B - 1MB)
  - string_piece_unittest: 24/24 passed
  - test_butil: 724/725 passed (1 pre-existing StackTrace failure)
  - test_bvar: 64/64 passed

Files changed:
  - src/butil/string_compare_rvv.cc (new): RVV memcmp implementation
  - src/butil/strings/string_piece.h: RVV dispatch in wordmemcmp (N >= 16)
  - BUILD.bazel: added string_compare_rvv.cc to BUTIL_SRCS
  - CMakeLists.txt: added string_compare_rvv.cc

Signed-off-by: Xiaofei Gong <gongxiaofei24@iscas.ac.cn>
Signed-off-by: YuanSheng <yuansheng@isrc.iscas.ac.cn>
This patch adds RVV-accelerated memcmp for StringPiece operations
on RISC-V 64-bit platforms.

The implementation follows glibc's official RVV pattern:
- e8m8 LMUL for maximum throughput
- Hardware-adaptive vector length via vsetvl
- vfirst.m for early-out on first difference

Performance on SOPHGO SG2044 (RVV 1.0, VLEN >= 128, GCC 15.1):
glibc 2.38 scalar memcmp (no RVV acceleration) as baseline.

  memcmp (worst-case full scan, 50000 iterations):
    64 B:   20 ns ->   6 ns  (3.4x)
   256 B:   54 ns ->  15 ns  (3.6x)
     1 KB: 120 ns ->  55 ns  (2.2x)
     4 KB: 435 ns -> 225 ns  (1.9x)
    16 KB: 1968 ns -> 1258 ns (1.6x)
    64 KB: 10962 ns -> 9044 ns (1.2x)
   256 KB: 46893 ns -> 43108 ns (1.1x)
     1 MB: 446161 ns -> 454717 ns (1.01x)

Correctness:
  - 59/59 expanded correctness tests passed (64B - 1MB)
  - string_piece_unittest: 24/24 passed
  - test_butil: 724/725 passed (1 pre-existing StackTrace failure)
  - test_bvar: 64/64 passed

Files changed:
  - src/butil/string_compare_rvv.cc (new): RVV memcmp implementation
  - src/butil/strings/string_piece.h: RVV dispatch in wordmemcmp (N >= 16)
  - BUILD.bazel: added string_compare_rvv.cc to BUTIL_SRCS
  - CMakeLists.txt: added string_compare_rvv.cc

Signed-off-by: Xiaofei Gong <gongxiaofei24@iscas.ac.cn>
Signed-off-by: YuanSheng <yuansheng@isrc.iscas.ac.cn>
Add RVV-accelerated rvv_memchr() for byte search in StringPiece::find(char).
Uses RVV vector compare + vfirst to scan for target byte, achieving 2.9x-5.8x
speedup over glibc memchr on RISC-V SG2044 across 64B-1MB buffer sizes.

Signed-off-by: Xiaofei Gong <gongxiaofei24@iscas.ac.cn>
Signed-off-by: YuanSheng <yuansheng@isrc.iscas.ac.cn>
Signed-off-by: Felix-Gong <gongxiaofei24@iscas.ac.cn>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a RISC-V RVV-accelerated byte-search implementation (rvv_memchr) and wires it into butil::StringPiece::find(char) to speed up single-byte searches on RVV-capable targets.

Changes:

  • Add rvv_memchr() implementation alongside rvv_memcmp() in src/butil/string_compare_rvv.cc.
  • Expose RVV helpers in string_piece.h and dispatch StringPiece::find(char) to rvv_memchr() when RVV is available.
  • Update build files to compile the RVV implementation (CMake + Bazel).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/butil/strings/string_piece.h Declares RVV helpers and uses rvv_memcmp in wordmemcmp for byte strings.
src/butil/strings/string_piece.cc Dispatches StringPiece::find(char) to RVV memchr on RVV-enabled RISC-V.
src/butil/string_compare_rvv.cc Implements RVV memcmp and new RVV memchr.
CMakeLists.txt Adds string_compare_rvv.cc to BUTIL sources for CMake builds.
BUILD.bazel Adds string_compare_rvv.cc to BUTIL sources for Bazel builds (but currently drops modp_b64_rvv.cc).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread BUILD.bazel
Comment on lines 128 to 132
"src/butil/third_party/icu/icu_utf.cc",
"src/butil/third_party/superfasthash/superfasthash.c",
"src/butil/third_party/modp_b64/modp_b64.cc",
"src/butil/third_party/modp_b64/modp_b64_rvv.cc",
"src/butil/third_party/symbolize/demangle.cc",
"src/butil/third_party/symbolize/symbolize.cc",
Comment thread src/butil/string_compare_rvv.cc Outdated
Comment on lines +18 to +22
// RVV-accelerated memcmp for StringPiece operations.
// Algorithm follows glibc's RVV memcmp pattern:
// - e8m8 LMUL with hardware-adaptive VL via vsetvl
// - vfirst.m for early-out on first mismatch

Comment on lines +139 to +143
const void* result = butil::rvv_memchr(self.data() + pos, c, self.size() - pos);
if (result != nullptr) {
return static_cast<const char*>(result) - self.data();
}
return BasicStringPiece<std::string>::npos;
@wwbmmm

wwbmmm commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

LGTM

… cast

- Restore modp_b64_rvv.cc in BUILD.bazel: modp_b64.cc calls
  rvv_modp_b64_encode/decode when RVV is enabled, so the RVV
  implementation file must be compiled.
- Update file header in string_compare_rvv.cc to mention memchr.
- Add explicit size_t cast for pointer difference in string_piece.cc.

Signed-off-by: Xiaofei Gong <gongxiaofei24@iscas.ac.cn>
Signed-off-by: YuanSheng <yuansheng@isrc.iscas.ac.cn>
Signed-off-by: Felix-Gong <gongxiaofei24@iscas.ac.cn>
@Felix-Gong
Felix-Gong force-pushed the riscv-stringpiece-memchr branch from 85d8403 to cb23e48 Compare July 21, 2026 03:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants