This is an automated email from the ASF dual-hosted git repository.

chenBright pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brpc.git


The following commit(s) were added to refs/heads/master by this push:
     new 5197621b Optimize StringPiece memcmp/memchr for RISC-V with RVV (#3396)
5197621b is described below

commit 5197621b915084ac9ca357763c6870d086cd7e12
Author: Felix-Gong <[email protected]>
AuthorDate: Wed Jul 22 17:00:33 2026 +0800

    Optimize StringPiece memcmp/memchr for RISC-V with RVV (#3396)
    
    This patch adds RVV-accelerated memcmp and memchr for StringPiece operations
    on RISC-V 64-bit platforms.
    
    The implementation follows glibc's official RVV memcmp/memchr patterns:
    - e8m8 LMUL for maximum throughput
    - Hardware-adaptive vector length via vsetvl
    - vfirst.m for early-out on first difference/match
    
    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)
    
      memchr (worst-case full scan, 50000 iterations):
        64 B:    5 ns ->  0.9 ns  (5.8x)
       256 B:   12 ns ->   3 ns  (4.0x)
         1 KB:   40 ns ->  12 ns  (3.3x)
         4 KB:  148 ns ->  44 ns  (3.4x)
        16 KB:  558 ns -> 158 ns  (3.5x)
        64 KB: 2150 ns ->  635 ns (3.4x)
       256 KB: 9200 ns -> 2900 ns (3.2x)
         1 MB: 39000 ns -> 13000 ns (3.0x)
    
    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 + memchr 
implementations
      - src/butil/strings/string_piece.h: RVV dispatch declarations
      - src/butil/strings/string_piece.cc: RVV dispatch in find(char) for memchr
      - BUILD.bazel: added string_compare_rvv.cc to BUTIL_SRCS
      - CMakeLists.txt: added string_compare_rvv.cc
      - Makefile: added string_compare_rvv.cc
    
    Signed-off-by: Xiaofei Gong <[email protected]>
    Signed-off-by: YuanSheng <[email protected]>
---
 BUILD.bazel                       |  1 +
 src/butil/string_compare_rvv.cc   | 28 ++++++++++++++++++++++++----
 src/butil/strings/string_piece.cc | 11 +++++++++++
 src/butil/strings/string_piece.h  |  3 ++-
 4 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/BUILD.bazel b/BUILD.bazel
index cf4560b7..5dc5fcf7 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -128,6 +128,7 @@ BUTIL_SRCS = [
     "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",
     "src/butil/third_party/snappy/snappy-sinksource.cc",
diff --git a/src/butil/string_compare_rvv.cc b/src/butil/string_compare_rvv.cc
index 3f7985e1..6373e83d 100644
--- a/src/butil/string_compare_rvv.cc
+++ b/src/butil/string_compare_rvv.cc
@@ -15,10 +15,9 @@
 // specific language governing permissions and limitations
 // under the License.
 
-// 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
+// RVV-accelerated memcmp and memchr for StringPiece operations.
+// memcmp: follows glibc's RVV memcmp pattern (e8m8 LMUL, vfirst.m early-out).
+// memchr: uses vmseq + vfirst.m to locate first matching byte.
 
 #include "butil/strings/string_piece.h"
 
@@ -50,6 +49,27 @@ int rvv_memcmp(const void* p1, const void* p2, size_t n) {
     return 0;
 }
 
+const void* rvv_memchr(const void* s, int c, size_t n) {
+    const uint8_t* src = static_cast<const uint8_t*>(s);
+    uint8_t ch = static_cast<uint8_t>(c);
+    size_t remaining = n;
+
+    while (remaining > 0) {
+        size_t vl = __riscv_vsetvl_e8m8(remaining);
+        vuint8m8_t v = __riscv_vle8_v_u8m8(src, vl);
+        vbool1_t eq = __riscv_vmseq_vx_u8m8_b1(v, ch, vl);
+        long first = __riscv_vfirst_m_b1(eq, vl);
+
+        if (first >= 0) {
+            return src + first;
+        }
+
+        src += vl;
+        remaining -= vl;
+    }
+    return nullptr;
+}
+
 }  // namespace butil
 
 #endif  // __riscv && __riscv_vector
diff --git a/src/butil/strings/string_piece.cc 
b/src/butil/strings/string_piece.cc
index 2d249243..a96d6ad0 100644
--- a/src/butil/strings/string_piece.cc
+++ b/src/butil/strings/string_piece.cc
@@ -134,7 +134,18 @@ size_t findT(const BasicStringPiece<STR>& self,
 }
 
 size_t find(const StringPiece& self, char c, size_t pos) {
+#if defined(__riscv) && defined(__riscv_vector)
+  if (pos < self.size()) {
+    const void* result = butil::rvv_memchr(self.data() + pos, c, self.size() - 
pos);
+    if (result != nullptr) {
+      return static_cast<size_t>(static_cast<const char*>(result) - 
self.data());
+    }
+    return BasicStringPiece<std::string>::npos;
+  }
+  return BasicStringPiece<std::string>::npos;
+#else
   return findT(self, c, pos);
+#endif
 }
 
 size_t find(const StringPiece16& self, char16 c, size_t pos) {
diff --git a/src/butil/strings/string_piece.h b/src/butil/strings/string_piece.h
index b1a4ed73..808ccbb1 100644
--- a/src/butil/strings/string_piece.h
+++ b/src/butil/strings/string_piece.h
@@ -43,9 +43,10 @@
 
 namespace butil {
 
-// RVV-accelerated byte comparison (implemented in string_compare_rvv.cc)
+// RVV-accelerated byte comparison and search (implemented in 
string_compare_rvv.cc)
 #if defined(__riscv) && defined(__riscv_vector)
 BUTIL_EXPORT int rvv_memcmp(const void* p1, const void* p2, size_t n);
+BUTIL_EXPORT const void* rvv_memchr(const void* s, int c, size_t n);
 #endif
 
 template <typename STRING_TYPE> class BasicStringPiece;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to