{n} times faster than C
I made a variant that is (on my Apple m1 machine) 20x faster than the naive C version in the blog by branchlessly processing the string word-by-word:<p><pre><code>    int run_switches(const char* input) {
        int res = 0;

        &#x2F;&#x2F; Align to word boundary.
        while ((uintptr_t) input % sizeof(size_t)) {
            char c = *input++;
            res += c == &#x27;s&#x27;;
            res -= c == &#x27;p&#x27;;
            if (c == 0) return res;
        }

        &#x2F;&#x2F; Process word-by-word.
        const size_t ONES = ((size_t) -1) &#x2F; 255;  &#x2F;&#x2F; 0x...01010101
        const size_t HIGH_BITS = ONES &lt;&lt; 7;       &#x2F;&#x2F; 0x...80808080
        const size_t SMASK = ONES * (size_t) &#x27;s&#x27;; &#x2F;&#x2F; 0x...73737373
        const size_t PMASK = ONES * (size_t) &#x27;p&#x27;; &#x2F;&#x2F; 0x...70707070
        size_t s_accum = 0;
        size_t p_accum = 0;
        int iters = 0;
        while (1) {
            &#x2F;&#x2F; Load word and check for zero byte.
            &#x2F;&#x2F; (w - ONES) &amp; ~w has the top bit set in each byte where that byte is zero.
            size_t w;
            memcpy(&amp;w, input, sizeof(size_t));
            if ((w - ONES) &amp; ~w &amp; HIGH_BITS) break;
            input += sizeof(size_t);

            &#x2F;&#x2F; We reuse the same trick as before, but XORing with SMASK&#x2F;PMASK first to get
            &#x2F;&#x2F; exactly the high bits set where a byte is &#x27;s&#x27; or &#x27;p&#x27;.
            size_t s_high_bits = ((w ^ SMASK) - ONES) &amp; ~(w ^ SMASK) &amp; HIGH_BITS;
            size_t p_high_bits = ((w ^ PMASK) - ONES) &amp; ~(w ^ PMASK) &amp; HIGH_BITS;

            &#x2F;&#x2F; Shift down and accumulate.
            s_accum += s_high_bits &gt;&gt; 7;
            p_accum += p_high_bits &gt;&gt; 7;
            if (++iters &gt;= 255 &#x2F; sizeof(size_t)) {
                &#x2F;&#x2F; To prevent overflow in our byte-wise accumulators we must flush
                &#x2F;&#x2F; them every so often. We use a trick by noting that 2^8 = 1 (mod 255)
                &#x2F;&#x2F; and thus a + 2^8 b + 2^16 c + ... = a + b + c  (mod 255).
                res += s_accum % 255;
                res -= p_accum % 255;
                iters = s_accum = p_accum = 0;
            }
        }
        res += s_accum % 255;
        res -= p_accum % 255;

        &#x2F;&#x2F; Process tail.
        while (1) {
            char c = *input++;
            res += c == &#x27;s&#x27;;
            res -= c == &#x27;p&#x27;;
            if (c == 0) break;
        }

        return res;
    }
</code></pre>
Fun fact: the above is still 1.6x slower (on my machine) than the naive two-pass algorithm that gets autovectorized by clang:<p><pre><code>    int run_switches(const char* input) {
        size_t len = strlen(input);
        int res = 0;
        for (size_t i = 0; i &lt; len; ++i) {
            char c = input[i];
            res += c == &#x27;s&#x27;;
            res -= c == &#x27;p&#x27;;
        }
        return res;
    }</code></pre>