Skip to content

Commit 2078eb4

Browse files
authored
gh-120397: Optimize str.count() for single characters (#120398)
1 parent 6ae254a commit 2078eb4

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Improve the througput by up to two times for the :meth:`str.count`, :meth:`bytes.count` and :meth:`bytearray.count`
2+
methods for counting single characters.

Objects/stringlib/fastsearch.h

+19
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,22 @@ STRINGLIB(count_char)(const STRINGLIB_CHAR *s, Py_ssize_t n,
753753
}
754754

755755

756+
static inline Py_ssize_t
757+
STRINGLIB(count_char_no_maxcount)(const STRINGLIB_CHAR *s, Py_ssize_t n,
758+
const STRINGLIB_CHAR p0)
759+
/* A specialized function of count_char that does not cut off at a maximum.
760+
As a result, the compiler is able to vectorize the loop. */
761+
{
762+
Py_ssize_t count = 0;
763+
for (Py_ssize_t i = 0; i < n; i++) {
764+
if (s[i] == p0) {
765+
count++;
766+
}
767+
}
768+
return count;
769+
}
770+
771+
756772
Py_LOCAL_INLINE(Py_ssize_t)
757773
FASTSEARCH(const STRINGLIB_CHAR* s, Py_ssize_t n,
758774
const STRINGLIB_CHAR* p, Py_ssize_t m,
@@ -773,6 +789,9 @@ FASTSEARCH(const STRINGLIB_CHAR* s, Py_ssize_t n,
773789
else if (mode == FAST_RSEARCH)
774790
return STRINGLIB(rfind_char)(s, n, p[0]);
775791
else {
792+
if (maxcount == PY_SSIZE_T_MAX) {
793+
return STRINGLIB(count_char_no_maxcount)(s, n, p[0]);
794+
}
776795
return STRINGLIB(count_char)(s, n, p[0], maxcount);
777796
}
778797
}

0 commit comments

Comments
 (0)