-
Notifications
You must be signed in to change notification settings - Fork 272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
64-bit Roaring Bitmaps in C #534
Conversation
We have some support for big endian systems. As far as I can tell, we have no big-endian user, but we ensure that it runs nonetheless, except for serialization and deserialization. You could just declare that you don't support big endian systems for this particular feature, that's fine. My expectation is that the few people who need big endian support should chip in and help provide it. This being said, there is no harm in supporting big endian systems from the get go. A macro is available... #if CROARING_IS_BIG_ENDIAN You can roll your own byte reversal routines if you need them... uint16_t swap_bytes(const uint16_t word) {
return (word >> 8) | (word << 8);
} (Same for any word size.) It will compile to efficient code. I don't think you need system-specific functions. |
This is great work. We will be happy to merge this!!! |
5f340b5
to
4716345
Compare
Removed the slightly larger tests. They only performed 300 iterations, which seemed like it would've been small enough! In the A question before merging: how do you feel about |
I have a little worry about exposing names quite so generic, I think it's not impossible that someone wanting to use CRoaring might already have a |
7c952c1
to
fe5ebb1
Compare
Thanks for the review @Dr-Emann, the code is better for it. I also realized we can entirely hide |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think we need to add this to the amalgamation
script as well
I'll create a separate PR to add it to the amalgamation script. |
Looks like the test added in #540 is causing failures in sanitized tests. |
Yes. I introduced a memory leak. |
See #541 |
This will be used to store the high 48 bits of 64 bit roaring bitmap entries. For more details, see include/roaring/art/art.h
* Change art_compare_prefix to take a single length rather than two. * Use art_compare_keys where possible. * Use art_val_t directly (through an alias) rather than defining a separate type. * Remove key_chunk from art_indexed_child_t. * Use node->base where possible. * Merge art_create_iterator into art_init_iterator.
Are we good to merge? |
I think I'd be okay to merge, and add the todos in separate PRs (especially I'm excited to add this to the croaring-rs bindings for rust, as well. |
Question: is there any thought to switching the existing 64bit C++ support to use this new facility? Today IIRC 64bit support in C++ is implemented very simply by having a std::map<> which maps the high-order 32 bits to a 32bit Roaring for the lower 32bits. |
That would be an obvious next step. It would also impact other wrappers. This could become more widely available. |
Another obvious todo would be to add serialization and deserialization, ideally in a way that is compatible with the Java code. |
@SLieve There is a bunch of work remaining, @Dr-Emann and @madscientist pointed at some things, but I think that there is agreement that we can merge. Can you confirm that you are fine with merging at this time? I want you to look at the last comments before we merge for real. :-) When I do so, I will have to add a bunch of new issues to complete the work. (Not that you did not do a lot, you did... there is just more to do...) |
Yes, I'm fine merging this code as it is functional as-is. I intend to continue work on this, so feel free to assign the new issues to me. C++ 64-bit support will have to wait until this implementation has feature parity with the existing one. |
Merging. |
@SLieve Please check your email, as I have sent you an invite for the org. I have created two new issues but I can't assign them to you because you are not part of the org at this time. |
I've joined the org now and assigned the issues to myself. |
Hi, Is there any benchmark compare art version against |
The only comparative benchmark with the C++ 64-bit version is currently |
The following blog post could be relevant: https://lemire.me/blog/2016/09/15/the-memory-usage-of-stl-containers-can-be-surprising/ An std::set used something like 32 bytes per entry while an std::unordered_set used 36 bytes per entry. This was for 4-byte payloads but the results could only be worse for 8-byte payloads. |
I agree that "benchmarks" is too abstract a term: what are you measuring? Pure lookup speed? Insert speed? Delete speed? Size? All of these will be important in different ways to different workloads. @lemire (or anyone) have you done any experimentation with Roaring vs. specifically STL maps/sets/vectors of |
Yes. In the 32-bit case, we have written a paper that covers various alternatives way back in 2018...
It covers uncompressed bitsets, std::set, and so forth. Since then, there has been great many other benchmarks published, including different implementations of 64-bit Roaring. Of course, the newly contributed 64-bit Roaring bitmaps have not been benchmarked.
A set of bool it can be empty, have true, fast, just true or false. So you can represent it using 2 bits. You can use Benchmarking thoroughly the new 64-bit bitmaps (using a rich set of metrics) would be important and I think that we will eagerly consider a pull request that provides these benchmarks. For tracking memory usage, what we did in the paper was to implement a custom allocator which allows us to track what is allocated... that's not perfect because it only measures virtual memory, not actual physical memory usage, but in our context, I think it is sufficient (calling I stress that it is not a simple endeavour to use microbenchmarks to assess such data structures. It requires some care. |
#elif defined(__has_include) && \ | ||
__has_include(<byteswap.h>) // CROARING_IS_BIG_ENDIAN | ||
#include <byteswap.h> | ||
#define htobe64(x) __bswap_64(x) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to break Android NDK r26 builds.
FAILED: src/CMakeFiles/roaring.dir/roaring64.c.o
/vcpkg/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=armv7-none-linux-androideabi21 --sysroot=/vcpkg/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/sysroot -I/mnt/vcpkg-ci/b/roaring/src/v3.0.0-d8b12d4628.clean/include -I/mnt/vcpkg-ci/b/roaring/src/v3.0.0-d8b12d4628.clean/include/roaring -I/mnt/vcpkg-ci/b/roaring/src/v3.0.0-d8b12d4628.clean/cpp -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security -fPIC -Wall -Wmissing-braces -Wextra -Wsign-compare -Wshadow -Wwrite-strings -Wpointer-arith -Winit-self -fno-limit-debug-info -std=gnu11 -fPIC -MD -MT src/CMakeFiles/roaring.dir/roaring64.c.o -MF src/CMakeFiles/roaring.dir/roaring64.c.o.d -o src/CMakeFiles/roaring.dir/roaring64.c.o -c /mnt/vcpkg-ci/b/roaring/src/v3.0.0-d8b12d4628.clean/src/roaring64.c
/mnt/vcpkg-ci/b/roaring/src/v3.0.0-d8b12d4628.clean/src/roaring64.c:63:20: error: call to undeclared function '__bswap_64'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
uint64_t tmp = croaring_htobe64(key);
^
/mnt/vcpkg-ci/b/roaring/src/v3.0.0-d8b12d4628.clean/include/roaring/portability.h:442:29: note: expanded from macro 'croaring_htobe64'
#define croaring_htobe64(x) __bswap_64(x)
^
What I find in that header is:
#define bswap_64(x) __swap64(x)
(Does it need to use __
prefixed identifier?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code is incorrect. Thanks for reporting the issue.
This copies the idea from the Java version of Roaring Bitmaps, using an Adaptive Radix Trie (ART) for the high 48 bits of Roaring Bitmap entries, and the existing 16-bit containers for the low 16 bits.
This PR includes an implementation of an ART slightly specialized for Roaring Bitmaps. The performance of
roaring64
seems to be roughly twice as slow as the 32-bit implementation, according to the microbenchmarks on my machine, but there's likely plenty of room for optimization.I normally write C++ code, so please point out any c-isms that I've missed!
TODO:
byteswap.h
, which assumes Linux + little endian.roaring64.h
. Right nowart_t
,art_val_t
, andleaf_t
are exposed.roaring64_bitmap_intersect_with_range
.