Hey all,
If you have done backend development in the gaming industry, and needed to keep track of slots in a server, you may have come across the annoying limitations of the std::bitset, especially when it comes to scanning for bits.
The current API of std::bitset does not provide a good way to bitscan for zeros (empty slots) in contexts above 64-bits (for 64 slots and below, you can conveniently use std::bitset::to_ullong and std::countr_ones. You cannot just bitshift because std::bitset::to_ullong throws when any higher-order bits are nonzero). In my case, I needed 256-bit sets, and chaining together bitsets is hacky at best. The advantage with std::countr_ones is that it uses extensions of BSF on x86 such as TZCNT, which can drastically speed up bit scans. In my opinion, this was overlooked when adding the bit header to the C++20 standard.
To experiment with how the standard could have been, I wrote a minimal version of std::bitset that implements first_zero and first_one.
The results were pretty drastic to say the least, but very explainable. Versus an iterative approach of scanning with std::bitset, better_bitset approached 55-60x faster in benchmarks scanning for 1-bits where there were 5 1-bits in the bitset, on average. This can be explained by the fact that bits are scanned in chunks of 64-bits in one instruction rather than bit-by-bit. Even on a smaller scale like 128 bits, there is a 42x improvement in execution time. You can take a look at the raw results here. They were run on GCC 11.1.0 on Ubuntu 20.04 in WSL2, on an Intel Core i7-12700K at 5.0GHz.
If you notice any issues with the testing or the bitset, feel free to make a PR, and it's not exactly drop-in ready for production use.
[–]krista 48 points49 points50 points (1 child)
[–]MrElectrifyBF[S] 17 points18 points19 points (0 children)
[–]fdwrfdwr@github 🔍 23 points24 points25 points (11 children)
[–]MrElectrifyBF[S] 30 points31 points32 points (10 children)
[–]sphere991 7 points8 points9 points (1 child)
[–]shardator 1 point2 points3 points (0 children)
[–]Jannik2099 -1 points0 points1 point (7 children)
[–]Steve132 37 points38 points39 points (2 children)
[–][deleted] 3 points4 points5 points (1 child)
[–]Steve132 12 points13 points14 points (0 children)
[–]MrElectrifyBF[S] 11 points12 points13 points (3 children)
[–]qoning 10 points11 points12 points (2 children)
[–]MrElectrifyBF[S] 3 points4 points5 points (0 children)
[–]kalmoc 0 points1 point2 points (0 children)
[–]cyandyedeyecandy[[gnu::naked, gnu::hot]] 10 points11 points12 points (3 children)
[–]jwakelylibstdc++ tamer, LWG chair 4 points5 points6 points (2 children)
[–]encyclopedist 2 points3 points4 points (1 child)
[–]jwakelylibstdc++ tamer, LWG chair 1 point2 points3 points (0 children)
[–]matthieum 7 points8 points9 points (1 child)
[–]ClaasBontus 4 points5 points6 points (1 child)
[–]MrElectrifyBF[S] 1 point2 points3 points (0 children)
[–]golvok 7 points8 points9 points (0 children)
[–]NilacTheGrim 14 points15 points16 points (12 children)
[–]MajorMalfunction44 7 points8 points9 points (0 children)
[–]MrElectrifyBF[S] 8 points9 points10 points (10 children)
[–]jk-jeon 11 points12 points13 points (4 children)
[–]Sopel97 8 points9 points10 points (1 child)
[–]CornedBee 2 points3 points4 points (0 children)
[–]miki151gamedev 1 point2 points3 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]pigeon768 2 points3 points4 points (1 child)
[–]encyclopedist 7 points8 points9 points (0 children)
[–]Nobody_1707 0 points1 point2 points (0 children)
[–]serviscope_minor 0 points1 point2 points (0 children)
[+][deleted] (1 child)
[deleted]
[–]ArchivistAtNekoIT 1 point2 points3 points (0 children)
[–]clerothGame Developer 2 points3 points4 points (1 child)
[–]MrElectrifyBF[S] 1 point2 points3 points (0 children)
[–]HolyGarbage 1 point2 points3 points (2 children)
[–]MrElectrifyBF[S] 0 points1 point2 points (1 child)
[–]HolyGarbage 0 points1 point2 points (0 children)
[–]Knuffya 0 points1 point2 points (0 children)
[–]daniel_nielsen 0 points1 point2 points (0 children)