Bitap: My favorite string matching algorithm

(jo3-l.dev)

25 points | by haeseong 4 days ago ago

10 comments

  • Rendello a day ago ago

    I also have a favourite string matching algorithm, the "Generic SIMD" from this post [1] by Wojciech Muła (I haven't really read the other two SIMD algorithms since I wasn't planning on working with intrinsics).

    There were some good comments that post's thread [2], including from burntsushi of ripgrep.

    1. http://0x80.pl/notesen/2016-11-28-simd-strfind.html

    2. https://news.ycombinator.com/item?id=44274001

    • skrellm 16 hours ago ago

      I've also implemented a SIMD accelerated, but case in-sensitive (*) search algorithm as an stb-style single header library, also based on Wojciech Muła's work.

      https://gitlab.com/bztsrc/fast_memcasemem

      See the performance comparison in the README, it's about 6 times faster than libc.

      (*) - full UTF-8 support, but only works for UNICODE codepoints where the UTF-8 encoding lengths are the same for lowercase and uppercase. There are only 27 out of 40576 pairs which aren't handled (listed in the README).

      • Rendello 12 hours ago ago

        > UNICODE codepoints where the UTF-8 encoding lengths are the same for lowercase and uppercase.

        This very same property got me to post this [1], which sent me down the rabbithole of learning about Unicode in earnest and building my Unicode tool. Which may have an initial release some time this millennia... maybe.

        1. https://news.ycombinator.com/item?id=42014045

    • MattPalmer1086 21 hours ago ago

      Always been interested in using SIMD to speed up searching. So far though i have not found a really nice one.

      Need to figure out what area they excel in - there is no one search that is the best for all types of data and pattern/search length.

  • MattPalmer1086 a day ago ago

    Ah, last weekend I was just updating my own string search algorithm to use Bitap (Shift-OR variant) instead of KMP, when the pattern length is < 64. It is faster. It is a very lovely algorithm indeed.

    My search algorithm, HashChain [1] is a very fast sublinear algorithm, but is uses KMP (and now Bitap) to verify matches so it has a linear worst case (instead of quadratic, like Boyer Moore Horspool).

    [1] https://github.com/nishihatapalmer/HashChain

  • MattPalmer1086 a day ago ago

    It is a really nice derivation of Bitap from first principles. I had not seen that before. Good job!

    One small nit: he says the naive algorithm is linear - maybe it is for the average case, but it has a quadratic worst case complexity. Bitap is linear even for worst case.

  • jqpabc123 11 hours ago ago

    Interesting algorithm.

    I can see how this could be advantageous for moderate length patterns up to 64 bytes.

    But for short registered sized patterns (4 or 8 bytes), I am somewhat skeptical of any significant advantage over a very tight, brute force register based loop comparing multi-byte chunks.

    • jo3_l 10 hours ago ago

      (OP here.) You're correct that for short patterns there's little advantage over the brute-force algorithm, and in fact the brute-force algorithm should actually be faster in many cases. Indeed the per-iteration comparison against the pattern in the brute-force algorithm is essentially a memcmp, which is vectorized and runs very fast on modern hardware. Consequently all mainstream programming languages that I know of just use the brute-force algorithm as a fallback when the pattern is short, as opposed to something more complicated like bitap.

      I tried to be fairly careful to not overstate the performance benefits in the original post for this reason.

      • jqpabc123 9 hours ago ago

        Ok, so why not use a fast memcmp on the first 4-8 chars of the pattern to identify any potential match and once found, work from there to verify if a full match exists?

        This is essentially what I have have been doing for years and it is very simple. I'm sure it is not always the fastest but it's not too shabby either in the real world.