Skip to content
HomeVideosBooksBlogs
AllTop postsTopics
Podcasts
HistoryListsWatch laterLiked videosFollowing

The videos, books, blogs and podcasts Hacker News keeps recommending, all in one place.

VideosBooksBlogsPodcastsAboutPrivacySettings

Data from Hacker News, HackerTube, HackerBooks, HackerBlogs and Open Library. Credits · Not affiliated with Y Combinator.

HomeVideosBooksBlogsPodcasts
Ctrl K
    W

    Wojciech Muła

    0x80.pl · Personal blog · on HN since 2011

    Wojciech Muła writes technical articles on SIMD and low-level algorithms, covering substring search, popcount, integer parsing, and hashing.

    Visit blogRSSHN submissions
    Systems & PerformanceProgramming
    What HN says

    HN commenters praise his deep SIMD knowledge and recommend his substring-search and popcount articles, though one notes the code can be dense.

    Stats for nerds
    55HN people shared it
    45linked in comments
    1.3Kstory points
    Jul 2026last shared
    2015people per year2026

    Top posts on HN

    1. 1
      SIMD-friendly algorithms for substring searching (2016)
      4 people · 223 points · first shared 2025 · 35 comments on HN
    2. 2
      Is sorted using SIMD instructions
      1 person · 177 points · first shared 2018 · 67 comments on HN
    3. 3
      Dividing unsigned 8-bit numbers
      1 person · 162 points · first shared 2024 · 67 comments on HN
    4. 4
      Parsing Series of Integers with SIMD (2018)
      5 people · 158 points · first shared 2018 · 13 comments on HN
    5. 5
      AVX512 VBMI – remove spaces from text
      2 people · 152 points · first shared 2019 · 75 comments on HN
    6. 6
      AVX2 faster than native popcnt instruction on Haswell/Skylake
      7 people · 149 points · first shared 2016 · 38 comments on HN
    7. 7
      SIMD Binary Heap Operations
      1 person · 60 points · first shared 2025 · 19 comments on HN
    8. 8
      Base64 decoding with SIMD instructions
      1 person · 53 points · first shared 2016 · 26 comments on HN
    9. 9
      LoongArch64 Subjective Higlights
      1 person · 49 points · first shared 2025 · 13 comments on HN
    10. 10
      Bit Test and Reset vs. Compilers
      1 person · 36 points · first shared 2021 · 13 comments on HN

    What HN people wrote when they linked it

    • mananaysiempreJul 2025

      > Lookup tables are always faster than calculation - is that true?

      Maybe on the Z80. Contemporary RAM was quite fast compared to it, by our sad standards.

      A table lookup per byte will see you hit a pretty hard limit of about 1 cycle per byte on all x86 CPUs of the last decade. If you’re doing a state machine or a multistage table[1] where the next table index depends on both the next byte and the previous table value, you’ll be lucky to see half that. Outracing your SSD[2] you’re not, with this approach.

      If instead you can load a 64-bit chunk (or several!) at a time, you’ll have quite a bit of leeway to do some computation to it before you’re losing to the lookup table, especially considering you’ve got fast shifts and even multiplies (another difference from the Z80). And if you’re doing 128- or 256-bit vectors, you’ve got even more compute budget—but you’re also going to spend a good portion of it just shuffling the right bytes into the right positions. Ultimately, though, one of your best tools there is going to be ... an instruction that does 16 resp. 32 lookups in a 16-entry table at a time[3].

      So no, if you want to be fast on longer pieces of data, in-memory tables are not your friend. On smaller data, with just a couple of lookups, they could be[4]. In any case, you need to be thinking about your code’s performance in detail for these things to matter—I can’t think of a situation where “prefer a lookup table” is a useful heuristic. “Consider a lookup table” (then…

    • clauseckerFeb 2024

      > Ah, Highway is C++ so that won't work for you then. And indeed CMPISTR is quite nonportable. I'm curious whether you are getting good performance from CMPISTR relative to AVX2 or even AVX-512, for those who have it? Wider vectors might reduce the advantage of specialized instructions.

      The main advantage of pcmpistrm is that it doesn't need preprocessing. You can beat its raw speed just fine, e.g. using the Muła/Langdale algorithm (http://0x80.pl/articles/simd-byte-lookup.html), but that algorithm requires costly preprocessing of the set to be matched. For string functions, input strings are usually very short and algorithms have to be optimised for that case; the steady state of a tight main loop is rarely reached and not the primary goal of optimisation. So as a result, any preprocessing before we can get started walking down the string gets really expensive.

      In fact, the benchmarks I wrote and whose results the Phoronox page has shamelessly ripped off use strings of just 64 bytes on average, which I believe is more representative for real-world cases than the very long strings other implementations seemed to have been optimised for. This is also the reason why I ended up using just SSE: not only do the instructions provided by SSE2 largely suffice for the job, but also is the advantage of longer vectors severely reduced when your input is unlikely to be longer than one or two of them. Plus for AVX and later, we have to do a VZEROUPPER before return (to ensure…

    • deckard1Apr 2023

      x86 doesn't have thousands. That's overstating it by quite a bit. The assembler I wrote contains 1095 encodings. It's from ~2004 but 100% complete at the time, so sure new instructions have been added since. But those are encodings. SAL has like 8 encodings, SAR has 12, CMP has 14, etc. These encodings are just different ways to use the same opcode but with different source/target parameters (8/16/32-bit immediates or registers, etc.)

      Someone wrote a script that disassembled all the binaries on their Linux machine and counted the number of actual instructions used (mostly by gcc, of course). Only a tiny fraction of the total instructions were used:

      http://0x80.pl/notesen/2014-01-01-instruction-utilization.html

      Just take the top 30 of that chart and learn those. The x86 contains a lot of instructions that no one needs to worry about. Things related to the ancient segment mode or x87 floating point, OS-privileged instructions (context switching, HLT/LIDT/etc.), AMD-only 3DNow, etc.

      The ISA is not the hard part anyway. Dealing with the ABI (System V on Linux) to interface with C/C++ code, the kernel syscall interface, position independent code/executable (PIC/PIE) are somewhat bigger concerns and are going to apply to RISC as well.

    • serejaMar 2024

      When you add prefetching (that is, compare against the middle element and fetch both the middle of the left half and the middle of the right half ahead of time) you are essentially doing radix-4 search, just with fewer actual comparisons.

      (You can prefetch k layers ahead for radix-2^k search, but searching in small arrays will become more expensive this way.)

      I didn't benchmark it, but I guess on mid-to-large arrays it would actually work somewhat slower than prefetching because it is more instruction-heavy, and, more importantly, prefetches are "cancelable": if the memory bus is too busy with actual requests, they will be skipped, while in explicit radix-k search you would have to wait for all (k-1) elements even if the middle element happened to be already cached and you already know which elements you need next.

      That said, it could probably work with small arrays where caching is not a concern and especially if you optimize for latency and not throughput. You can also try to do the comparisons with SIMD (Wojciech Mula tried something similar and got a small boost: http://0x80.pl/articles/simd-search.html).

    • kevingaddMay 2024

      I would expect it depends on where the lookup table enters the picture. If the table lookup is at the end of a dependency chain, it's not going to stall anything and then you're putting less strain on the branch predictor/reordering machinery.

      The article is using pext, which is different from a regular table lookup. While it has horrible latency and overhead on older chips, on Zen3 it appears to decode to a single uop with a latency of 3, and on Haswell it also decodes to one uop with a latency of 3. So it's not as bad as a regular table lookup as long as you're on a new enough processor.

      It's also possible to do vectorized lookup table loads if your lookup table is small enough and you have a modern CPU, see http://0x80.pl/notesen/2016-03-13-simd-lookup-pshufb.html and http://0x80.pl/notesen/2019-02-03-simd-switch-implementation.html (there's a more generalized version of this I can't remember the URL of...)

    • _3u10Nov 2021

      use the popcnt instruction or the popcnt intrinsic function.

      It counts how many bits are set to 1, you’re looking for 0.

      You can also cast it into a uint64_t integer and do an equality test. There might be a way to use fused multiply add.

      Also are you mmaping the file so you can just read it directly as a single buffer? You should be able to madvise to free pages after they’ve been checked.

      PUSHFB can also be used. http://0x80.pl/articles/sse-popcount.html

      Essentially you want to vectorize this tho memcmp may already be vectorized and do the cpu detection.

      Edit: also…
      You should be able to load 15 x 256 bits and then test them.
      Try VPTEST
      https://www.intel.com/content/www/us/en/develop/documentation/cpp-compiler-developer-guide-and-reference/top/compiler-reference/intrinsics/intrinsics-for-intel-advanced-vector-extensions/intrinsics-for-packed-test-operations/mm256-testz-si256.html

    Related

    Fabian Giesenfgiesen.wordpress.com200 people

    Why do CPUs have multiple cache levels?

    Fabian Giesen
    Personal · last shared 2026
    Dougall Johnsondougallj.wordpress.com48 people

    Why is Rosetta 2 fast?

    Dougall Johnson
    Personal · last shared 2026
    Simon Byrnesimonbyrne.github.io15 people

    Beware of Fast-Math

    Simon Byrne
    Personal · last shared 2025
    Apfelmusapfelmus.nfshost.com22 people

    How Does Lazy Evaluation Work in Haskell? (2014)

    Apfelmus
    Personal · last shared 2023
    ThePhDthephd.dev112 people

    Embed is in C23

    ThePhD
    Personal · last shared 2026
    Nayukinayuki.io90 people

    Creating a QR Code step by step

    Nayuki
    Personal · last shared 2026
    Josh Habermanblog.reverberate.org105 people

    Parsing Protobuf at 2+GB/S: How I Learned to Love Tail Calls in C

    Josh Haberman
    Personal · last shared 2026
    Wouter van Oortmerssenstrlen.com113 people

    The Lobster Programming Language

    Wouter van Oortmerssen
    Personal · last shared 2026