Coder Social home page Coder Social logo

csharpewah's Introduction

CSharpEWAH

This is a compressed variant of the standard bitarray class. It uses a 64-bit RLE-like compression scheme. It can be used to implement bitmap indexes.

The goal of word-aligned compression is not to achieve the best compression, but rather to improve query processing time. Hence, we try to save CPU cycles, maybe at the expense of storage. However, the EWAH scheme we implemented is always more efficient storage-wise than an uncompressed bitarray.

Real-world usage

CSharpEWAH has been reviewed by Matt Warren as part of his work on the Stack Overflow tag system:

http://mattwarren.org/2015/10/29/the-stack-overflow-tag-engine-part-3/

The Java counterpart of this library (JavaEWAH) is part of Apache Hive and its derivatives (e.g., Apache Spark) and Eclipse JGit. It has been used in production systems for many years. It is part of major Linux distributions.

EWAH is used to accelerate the distributed version control system Git (http://githubengineering.com/counting-objects/). You can find the C port of EWAH written by the Git team at https://github.com/git/git/tree/master/ewah

When should you use a bitmap?

Sets are a fundamental abstraction in software. They can be implemented in various ways, as hash sets, as trees, and so forth. In databases and search engines, sets are often an integral part of indexes. For example, we may need to maintain a set of all documents or rows (represented by numerical identifier) that satisfy some property. Besides adding or removing elements from the set, we need fast functions to compute the intersection, the union, the difference between sets, and so on.

To implement a set of integers, a particularly appealing strategy is the bitmap (also called bitset or bit vector). Using n bits, we can represent any set made of the integers from the range [0,n): it suffices to set the ith bit is set to one if integer i is present in the set. Commodity processors use words of W=32 or W=64 bits. By combining many such words, we can support large values of n. Intersections, unions and differences can then be implemented as bitwise AND, OR and ANDNOT operations. More complicated set functions can also be implemented as bitwise operations.

When the bitset approach is applicable, it can be orders of magnitude faster than other possible implementation of a set (e.g., as a hash set) while using several times less memory.

When should you use compressed bitmaps?

An uncompress BitSet can use a lot of memory. For example, if you take a BitSet and set the bit at position 1,000,000 to true and you have just over 100kB. That's over 100kB to store the position of one bit. This is wasteful even if you do not care about memory: suppose that you need to compute the intersection between this BitSet and another one that has a bit at position 1,000,001 to true, then you need to go through all these zeroes, whether you like it or not. That can become very wasteful.

This being said, there are definitively cases where attempting to use compressed bitmaps is wasteful. For example, if you have a small universe size. E.g., your bitmaps represent sets of integers from [0,n) where n is small (e.g., n=64 or n=128). If you can use an uncompressed BitSet and it does not blow up your memory usage, then compressed bitmaps are probably not useful to you. In fact, if you do not need compression, then a BitSet offers remarkable speed. One of the downsides of a compressed bitmap like those provided by JavaEWAH is slower random access: checking whether a bit is set to true in a compressed bitmap takes longer.

How does EWAH compares with the alternatives?

EWAH is part of a larger family of compressed bitmaps that are run-length-encoded bitmaps. They identify long runs of 1s or 0s and they represent them with a marker word. If you have a local mix of 1s and 0, you use an uncompressed word.

There are many formats in this family beside EWAH:

  • Oracle's BBC is an obsolete format at this point: though it may provide good compression, it is likely much slower than more recent alternatives due to excessive branching.
  • WAH is a patented variation on BBC that provides better performance.
  • Concise is a variation on the patented WAH. It some specific instances, it can compress much better than WAH (up to 2x better), but it is generally slower.
  • EWAH is both free of patent, and it is faster than all the above. On the downside, it does not compress quite as well. It is faster because it allows some form of "skipping" over uncompressed words. So though none of these formats are great at random access, EWAH is better than the alternatives.

There are other alternatives however. For example, the Roaring format (https://github.com/lemire/RoaringBitmap) is not a run-length-encoded hybrid. It provides faster random access than even EWAH.

Data format

For more details regarding the compression format, please see Section 3 of the following paper:

Daniel Lemire, Owen Kaser, Kamel Aouiche, Sorting improves word-aligned bitmap indexes. Data & Knowledge Engineering 69 (1), pages 3-28, 2010.
http://arxiv.org/abs/0901.3751

(The PDF file is freely available on the arXiv site.)

Unit testing

Building using Mono

You can build CSharpEWAH using the open source Mono toolchain using the msbuild command. Then you can run the executable using the mono command:

$ nuget restore EWAH.sln
$ msbuild
$ mono ./EWAH.RunTests/bin/Debug/EWAH.RunTests.exe

This will run unit tests.

Usage

See example.cs.

Credit

(c) Kemal Erdogan, Daniel Lemire, Ciaran Jessup, Michael Rice, Matt Warren This code is licensed under the Apache License, Version 2.0 (ASL2.0)

csharpewah's People

Contributors

ciaranj avatar lemire avatar pashcovich avatar udaken avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

csharpewah's Issues

Clone method does not clone the _Rlw variable

The clone method in EwahCompresseBitArray does not clone the _Rlw variable and this causes some problems in some scenarios.

[Test]
private void TestCloneEwahCompressedBitArray()
{
    EwahCompressedBitArray a = new EwahCompressedBitArray();
    a.Set(410018);
    a.Set(410019);
    a.Set(410020);
    a.Set(410021);
    a.Set(410022);
    a.Set(410023);

    EwahCompressedBitArray b = (EwahCompressedBitArray)a.Clone();

    a.SetSizeInBits(487123, false);
    b.SetSizeInBits(487123, false);

    Assert.AreEqual(a, b);
}

Support for long

I have a quick clarification question. Do you have any plans for supporting longs (e.g., bitmap.Set(long)) or perhaps an alternate implementation that supports long?

Thank you!

We are not longer producing a test executable with mono

We used to be able to build merely by typing xbuild. The sequence "nuget restore EWAH.sln; msbuild" should build our tests, but it fails to do so.

$ nuget restore EWAH.sln
MSBuild auto-detection: using msbuild version '15.0' from '/Library/Frameworks/Mono.framework/Versions/5.18.1/lib/mono/msbuild/15.0/bin'.
Committing restore...
Assets file has not changed. Skipping assets file writing. Path: /Users/lemire/CVS/github/csharpewah/EWAH.Tests/obj/project.assets.json
Restore completed in 44.06 ms for /Users/lemire/CVS/github/csharpewah/EWAH.Tests/EWAH.Tests.csproj.

NuGet Config files used:
    /Users/lemire/.config/NuGet/NuGet.Config

Feeds used:
    https://api.nuget.org/v3/index.json

$ msbuild
Microsoft (R) Build Engine version 16.0.42-preview+g804bde742b for Mono
Copyright (C) Microsoft Corporation. All rights reserved.

Build started 2019-06-14 2:59:02 PM.
Project "/Users/lemire/CVS/github/csharpewah/EWAH.sln" on node 1 (default targets).
ValidateSolutionConfiguration:
  Building solution configuration "Debug|Mixed Platforms".
Project "/Users/lemire/CVS/github/csharpewah/EWAH.sln" (1) is building "/Users/lemire/CVS/github/csharpewah/EWAH/EWAH.csproj" (2) on node 1 (default targets).
GenerateTargetFrameworkMonikerAttribute:
Skipping target "GenerateTargetFrameworkMonikerAttribute" because all output files are up-to-date with respect to the input files.
CoreCompile:
Skipping target "CoreCompile" because all output files are up-to-date with respect to the input files.
CopyFilesToOutputDirectory:
  EWAH -> /Users/lemire/CVS/github/csharpewah/EWAH/bin/Debug/EWAH.dll
Done Building Project "/Users/lemire/CVS/github/csharpewah/EWAH/EWAH.csproj" (default targets).
Project "/Users/lemire/CVS/github/csharpewah/EWAH.sln" (1) is building "/Users/lemire/CVS/github/csharpewah/EWAH.Tests/EWAH.Tests.csproj" (3) on node 1 (default targets).
ResolveAssemblyReferences:
  Primary reference "MSTest.TestFramework".
/Library/Frameworks/Mono.framework/Versions/5.18.1/lib/mono/msbuild/15.0/bin/Microsoft.Common.CurrentVersion.targets(2130,5): warning MSB3245: Could not resolve this reference. Could not locate the assembly "MSTest.TestFramework". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors. [/Users/lemire/CVS/github/csharpewah/EWAH.Tests/EWAH.Tests.csproj]
          For SearchPath "{TargetFrameworkDirectory}".
          Considered "/Library/Frameworks/Mono.framework/Versions/5.18.1/lib/mono/xbuild-frameworks/.NETFramework/v4.5.2/MSTest.TestFramework.winmd", but it didn't exist.
          Considered "/Library/Frameworks/Mono.framework/Versions/5.18.1/lib/mono/xbuild-frameworks/.NETFramework/v4.5.2/MSTest.TestFramework.dll", but it didn't exist.
          Considered "/Library/Frameworks/Mono.framework/Versions/5.18.1/lib/mono/xbuild-frameworks/.NETFramework/v4.5.2/MSTest.TestFramework.exe", but it didn't exist.
          Considered "/Library/Frameworks/Mono.framework/Versions/5.18.1/lib/mono/4.5.2-api/MSTest.TestFramework.winmd", but it didn't exist.
          Considered "/Library/Frameworks/Mono.framework/Versions/5.18.1/lib/mono/4.5.2-api/MSTest.TestFramework.dll", but it didn't exist.
          Considered "/Library/Frameworks/Mono.framework/Versions/5.18.1/lib/mono/4.5.2-api/MSTest.TestFramework.exe", but it didn't exist.
          Considered "/Library/Frameworks/Mono.framework/Versions/5.18.1/lib/mono/4.5.2-api/Facades/MSTest.TestFramework.winmd", but it didn't exist.
          Considered "/Library/Frameworks/Mono.framework/Versions/5.18.1/lib/mono/4.5.2-api/Facades/MSTest.TestFramework.dll", but it didn't exist.
          Considered "/Library/Frameworks/Mono.framework/Versions/5.18.1/lib/mono/4.5.2-api/Facades/MSTest.TestFramework.exe", but it didn't exist.
          Considered "/Library/Frameworks/Mono.framework/Versions/5.18.1/lib/mono/4.5.2-api/Facades/MSTest.TestFramework.winmd", but it didn't exist.
          Considered "/Library/Frameworks/Mono.framework/Versions/5.18.1/lib/mono/4.5.2-api/Facades/MSTest.TestFramework.dll", but it didn't exist.
          Considered "/Library/Frameworks/Mono.framework/Versions/5.18.1/lib/mono/4.5.2-api/Facades/MSTest.TestFramework.exe", but it didn't exist.
          For SearchPath "{GAC}".
          Considered "MSTest.TestFramework", which was not found in the GAC.
          For SearchPath "{RawFileName}".
          Considered treating "MSTest.TestFramework" as a file name, but it didn't exist.
          For SearchPath "bin/Debug/".
          Considered "bin/Debug/MSTest.TestFramework.winmd", but it didn't exist.
          Considered "bin/Debug/MSTest.TestFramework.dll", but it didn't exist.
          Considered "bin/Debug/MSTest.TestFramework.exe", but it didn't exist.
GenerateTargetFrameworkMonikerAttribute:
Skipping target "GenerateTargetFrameworkMonikerAttribute" because all output files are up-to-date with respect to the input files.
CoreCompile:
Skipping target "CoreCompile" because all output files are up-to-date with respect to the input files.
_CopyFilesMarkedCopyLocal:
  Touching "/Users/lemire/CVS/github/csharpewah/EWAH.Tests/obj/x86/Debug/EWAH.Tests.csproj.CopyComplete".
_CopyAppConfigFile:
Skipping target "_CopyAppConfigFile" because all output files are up-to-date with respect to the input files.
CopyFilesToOutputDirectory:
  EWAH.Tests -> /Users/lemire/CVS/github/csharpewah/EWAH.Tests/bin/Debug/EWAH.Tests.dll
Done Building Project "/Users/lemire/CVS/github/csharpewah/EWAH.Tests/EWAH.Tests.csproj" (default targets).
Project "/Users/lemire/CVS/github/csharpewah/EWAH.sln" (1) is building "/Users/lemire/CVS/github/csharpewah/EWAH.RunTests/EWAH.RunTests.csproj" (4) on node 1 (default targets).
GenerateTargetFrameworkMonikerAttribute:
Skipping target "GenerateTargetFrameworkMonikerAttribute" because all output files are up-to-date with respect to the input files.
CoreCompile:
Skipping target "CoreCompile" because all output files are up-to-date with respect to the input files.
_CopyFilesMarkedCopyLocal:
  Touching "/Users/lemire/CVS/github/csharpewah/EWAH.RunTests/obj/x86/Debug/EWAH.RunTests.csproj.CopyComplete".
_CopyAppConfigFile:
Skipping target "_CopyAppConfigFile" because all output files are up-to-date with respect to the input files.
CopyFilesToOutputDirectory:
  EWAH.RunTests -> /Users/lemire/CVS/github/csharpewah/EWAH.RunTests/bin/Debug/EWAH.RunTests.dll
Done Building Project "/Users/lemire/CVS/github/csharpewah/EWAH.RunTests/EWAH.RunTests.csproj" (default targets).
Done Building Project "/Users/lemire/CVS/github/csharpewah/EWAH.sln" (default targets).

Build succeeded.

"/Users/lemire/CVS/github/csharpewah/EWAH.sln" (default target) (1) ->
"/Users/lemire/CVS/github/csharpewah/EWAH.Tests/EWAH.Tests.csproj" (default target) (3) ->
(ResolveAssemblyReferences target) ->
  /Library/Frameworks/Mono.framework/Versions/5.18.1/lib/mono/msbuild/15.0/bin/Microsoft.Common.CurrentVersion.targets(2130,5): warning MSB3245: Could not resolve this reference. Could not locate the assembly "MSTest.TestFramework". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors. [/Users/lemire/CVS/github/csharpewah/EWAH.Tests/EWAH.Tests.csproj]

    1 Warning(s)
    0 Error(s)

Time Elapsed 00:00:01.30

Tests failing when run from visual studio 2010

Hi,
I downloaded the latest csharpewah source (0.2.1 per the CHANGELOG entry), and built the solution in visual studio 2010.
When I run the tests, most of the tests fail. For example:
testing ArnonMoscona

System.ArgumentOutOfRangeException : Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
at System.Collections.Generic.List`1.get_Item(Int32 index)
at Ewah.EwahCompressedBitArrayTest.EwahIteratorProblem() in EWAHCompressedBitmapTest.cs: line 412

and here is another:
TestEwahCompressedBitArray : Failedtesting EWAH (basic)

System.IndexOutOfRangeException : Index was outside the bounds of the array.
at Ewah.EwahCompressedBitArray.GetPositions() in EwahCompressedBitArray.cs: line 677
at Ewah.EwahCompressedBitArrayTest.TestEwahCompressedBitArray() in EWAHCompressedBitmapTest.cs: line 499

Anything special I need to do before running the tests ?

Intersects doesn't work properly

var a1 = new EwahCompressedBitArray();
var a2 = new EwahCompressedBitArray();
a1.Set(5);
a1.Set(15);
a2.Set(5);
a1.Intersects(a2) == false;

but 2 bitmap array has common bit at position 5.

'Not' appears not to respect incomplete words.

Not sure of the specifics to be honest, but I intuitively expect the following test:

    [Test]
    public void TestNot()
    {
        var bmp= new EwahCompressedBitArray();
        for (int i = 0; i <= 183; i++) {
            bmp.Set(i);
        }
        Assert.AreEqual(184, bmp.GetCardinality());
        bmp.Not();
        Assert.AreEqual(0, bmp.GetCardinality());
    }

To pass. Unfortunately it doesn't as the negated cardinality is actually 8, not 0.

If I had to guess this is due to the negation seeing 'excess' 0 bits in the final word (taking it up to 192bits or 24 bytes.) I've briefly checked the Not code, and it looks like there is code in there to deal with this edge case in fact.

Alternatively this may be by design! Should I expect all my bit-masks to consume full words for negation (and mask against my previous known size of bitmask) ?

Minimal Serialization strategy, an approach

Hi, I'm sending these BitArrays along the wire so wish to conserve bytes wherever possible. As I know the type I will be sending and receiving on the wire, I'd ideally like to avoid any overhead due to the type-system used by the CLR serialization framework.

I can see how I would easily send the information down as raw bytes without issue, my 'issue' is therefore more of a question:

i) Would you be happy to accept a patch to provide this and
ii) Do you have a preference for how you want the API to look, my first guess would be a public constructor taking a single byte[] and a new instance method along the lines of 'GetObjectDataAsBytes()'

Thank you
-cj.

Bug fixes in javaewah are not present in csharpewah

Some bugs that are fixed in javaewah (https://github.com/lemire/javaewah version 0.66) are not fixed in csharpewah.

The ones I've found are these:

  • Off-by-one bug in setSizeInBits(final int size, final boolean defaultvalue).
  • Bug in IteratingBufferedRunningLengthWord.discharge that might cause "and" to return spurious values in some cases (issue #19)
  • Bug in IteratingBufferedRunningLengthWord.discardFirstWords that might cause "and" to return the empty set when there is actually a result (issue #18)

System.IndexOutOfRangeException on high volumetry

Hi,

I use the library to index message and then be able to launch queries. I had to deal with 100.000+ messages to index. But the problem arises with much lower volumetry.
The exception raises in:

    public ulong GetCardinality() {
                ulong counter = 0;
                var i = new EwahEnumerator(_Buffer, _ActualSizeInWords);
                while (i.HasNext()) {
                    RunningLengthWord localrlw = i.Next();
                    if (localrlw.RunningBit) {
                       counter += (ulong)(WordInBits * localrlw.RunningLength);
                    }
                   for (int j = 0; j < localrlw.NumberOfLiteralWords; ++j) {
                       long data = i.Buffer[i.DirtyWords + j];
                       counter += bitCount((ulong)data);
                   }
               }
              return counter;
           }

And more precisely in " i.Buffer[i.DirtyWords + j];".
Of course, I'm not able to reproduce outside my application.
I had the feeling that the bitarray is corrupted (at least EwahEnumerator behaves strangely), but can't prove it and can't explain it.

Does my problem ring the bell at someone?
Thanks.

Alexandre.

.NET Core on Windows 10

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.