Commit graph

642 commits

Author SHA1 Message Date
Seebs
1e00b50953 gratuitously fancy logic for array/array callbacks
When searching for a small array in a large array, scanning ahead
is productive. The switch from counting indexes to reslicing the
slice appears to improve performance in this case. The fairly arbitrary
value `na << 2` is like `nb / 4 > na` except that it computes faster,
and lets us avoid the expensive overhead unless we have reason to
expect that there's significantly more items in b than in a.

Improvements: Not huge in some cases, but sometimes quite noticeable,
especially as the frequency of overlap increases, which is also
the expensive case in other ways.

name                                              old time/op  new time/op  delta
ImportMutexSampleData/64K/2Kr/40/none/write-0-8    501ms ± 4%   486ms ± 2%     ~     (p=0.052 n=6+5)
ImportMutexSampleData/64K/2Kr/40/none/write-1-8    756ms ± 5%   698ms ± 5%   -7.62%  (p=0.002 n=6+6)
ImportMutexSampleData/64K/2Kr/80/none/write-0-8    292ms ± 3%   276ms ± 4%   -5.46%  (p=0.002 n=6+6)
ImportMutexSampleData/64K/2Kr/80/none/write-1-8    511ms ± 6%   482ms ± 4%   -5.72%  (p=0.015 n=6+6)
ImportMutexSampleData/64K/2Kr/240/none/write-0-8   153ms ± 3%   132ms ± 5%  -13.91%  (p=0.008 n=5+5)
ImportMutexSampleData/64K/2Kr/240/none/write-1-8   354ms ± 2%   215ms ± 6%  -39.41%  (p=0.004 n=5+6)
ImportMutexSampleData/1K/2Kr/40/none/write-0-8     565ms ± 3%   543ms ± 3%   -3.89%  (p=0.015 n=6+6)
ImportMutexSampleData/1K/2Kr/40/none/write-1-8     807ms ± 6%   778ms ± 3%     ~     (p=0.180 n=6+6)
ImportMutexSampleData/1K/2Kr/80/none/write-0-8     317ms ± 3%   300ms ± 1%   -5.40%  (p=0.002 n=6+6)
ImportMutexSampleData/1K/2Kr/80/none/write-1-8     462ms ± 3%   437ms ± 4%   -5.31%  (p=0.009 n=6+6)
ImportMutexSampleData/1K/2Kr/240/none/write-0-8    141ms ± 1%   119ms ± 2%  -15.85%  (p=0.004 n=5+6)
ImportMutexSampleData/1K/2Kr/240/none/write-1-8    213ms ± 3%   171ms ± 3%  -19.70%  (p=0.002 n=6+6)
2021-05-10 11:58:18 -05:00
Seebs
54f5cc799c performance hackery: add intersectCallback for use in running callbacks
In BitmapBitmapFilter.ConsiderData, we intersect things solely in order
to perform callbacks on them. Creating these intermediate arrays is
actually somewhat expensive, and all we're going to do with them is
make callbacks anyway.

So, we add a new `intersectCallback`, which behaves similarly to
`intersectionCount`, but which dramatically reduces the amount of memory
allocation associated with doing the callbacks; in some test cases
on mutex data, this code was >90% of all memory allocations, and
getting rid of that helps a lot.

At that point, we no longer need the separate intersectAny check,
because it doesn't save us any time anymore.
2021-05-10 11:58:18 -05:00
Seebs
e93d2fe06c bitmap unmarshalling and testing bug fixes
When unmarshalling ops, we weren't adding a meaningful OpN to them,
resulting in misleading reports from `pilosa inspect`. Also, we were
mistakenly reporting things as "mapped" when they were actually
using their internal storage (as with small array containers).

Add the "sanity check" to `pilosa inspect` so that errors like the
above get noticed more easily and corrected. Also, to make that work,
have roaring.InspectBinary actually put containers in the bitmap
it creates rather than just creating info entries for them.
2021-04-20 12:01:21 -05:00
Seebs
ca216a14c5 fix bitmap.BitwiseEqual bugs
bitmap.BitwiseEqual had a couple of subtle bugs, and the net result
is that if the bitmap you were comparing to had an empty container after
the original bitmap ran out of containers, we'd spuriously report
the container as existing and being... the last container in the original,
actually.

Issues are both that we were grabbing the value from the wrong iterator,
and also that we were iterating twice per loop, and thus could also
have missed a non-empty container immediately following an empty one.
2021-04-20 12:01:13 -05:00
Seebs
269837414e rbf/intoContainer: ensure correct N, avoid recounting
The remake container logic (used to avoid allocating extra containers while
applying filters) relied on roaring recomputing N, which it did for bitmaps
but didn't do for runs. Fix this both ways; it would now do that for runs,
but also we add "with explicit N" variants and use those since we have a
correct count already, and don't need it. This means fewer popcounts on
bitmaps, and working at all on runs.
2021-04-12 16:13:16 -05:00
Todd Gruben
d220426686 doc comment 2021-02-22 11:50:01 -06:00
tgruben
18e31a63b6
Update roaring/roaring.go
Co-authored-by: Matthew Jaffee <matthew.jaffee@gmail.com>
2021-02-22 11:42:48 -06:00
Todd Gruben
6219b4ca8b add optional UpdateExistence on importRoaring 2021-02-19 17:47:28 -06:00
Nia Weiss
0d9179f10c
roaring: fix intersectionAnyRunBitmap when processing single-word runs
When a run started and ended within a single word, the entirety of the word would be checked.
This would cause small runs to be processed incorrectly, and caused Distinct-on-sets to select rows that did not match the specified filter.
2021-01-21 18:09:27 -05:00
Jason E. Aten
0db4914bc4 add tests for NewBitmapBitmapFilter constructor
- document sort.Stable need
2020-12-17 00:27:34 +00:00
Seebs
4ddbadcea7 review issues: fix unclearSets (now sliceDifference) and prune/fullPrune
unclearSets was completely broken and I have no idea why the test I thought
was testing it didn't actually catch that problem. Added unit tests and fixed
the logic. Improved/clarified prune and fullPrune, and unexported their
names because why export methods on an unexported type.

Also improve some comments and rename a variable or two to improve clarity.
2020-12-16 13:18:18 -06:00
Seebs
de14762661 create Tx tests for CountRange
CountRange for RBF had a subtle bug which wasn't noticed, so, let's
have some CountRange testing and also a benchmark.

We also fix a couple of subtle bugs caught in the process of developing
and testing this.

SliceContainers will allow nil containers, but doesn't return them when
iterating because there's various things that can panic if called on a nil
container. Since countEmptyContainers() has to traverse the whole bitmap
anyway, it doesn't matter which it counts, so we replace it with
countNonEmptyContainers(), and adjust test cases accordingly. This fixes
an issue where if roaring is smart enough to insert a nil container
into a SliceContainers, trying to write it to a file produces an invalid
bitmap with offsets off by 16 and one container fewer than its header predicts.

RBF: don't try to count 0 bits in a container

If we're to the "last container", and we'd be counting all the bits less than
zero, we can skip that. This avoids hitting a bug, which is that c.countRange
doesn't handle BitmapPtr.
2020-12-16 13:16:46 -06:00
Seebs
dec0a00155 add container N to ConsiderKey 2020-12-16 13:16:46 -06:00
Seebs
7c415b4217 Implement rbf-specific ApplyFilter
This gives RBF an ApplyFilter that can run without instantiating containers
when the filter it's using doesn't need them instantiated. We can also seek
ahead in cases where we know the next key we care about is not just the next
key numerically.
2020-12-16 13:16:46 -06:00
Seebs
59d89dda99 Allow arbitrary and potentially more efficient filtering of bitmaps
This is a partial solution to a nasty performance problem, which is that
a ContainerIterator has to *generate* all the containers. With roaring, this
was cheap because they already exist in memory; with transactional backends,
it's an allocation per container, *even for the containers we don't use*.

This design admits filters which can distinguish between answers they
can give just based on keys and times when they actually need containers
instantiated, and can also give hints as to future answers -- saying "yes"
or "no" to entire rows at a time, or indicating when they're done.

This is only part of the solution; we also need a Tx API hook for
doing scans like this which doesn't rely on ContainerIterator.
2020-12-16 13:16:46 -06:00
Jason E. Aten
1a6f573739 roaring: print utility AsContainerMatrixString for diagnostics
AsContainerMatrixString returns a string showing
 the matrix of rows in a shard, showing the count of hot (1) bits
 in each container.
2020-12-16 18:50:45 +00:00
Jason E. Aten
82d07bc123 debugstats and rbf tooling for enhanced debugging/diagnostics 2020-12-08 22:47:40 +00:00
Jason E. Aten
6f4ca78bc4 RoaringIterator.ContainerKeySpan method
- enables rbf ingest optimization. When we know there won't be
   updates involved we can bulk import faster.
2020-12-01 01:52:58 +00:00
Nia Weiss
f9c196e418
skip roaring add test in race
Otherwise it overloads the race detector.
2020-11-20 12:16:09 -05:00
Nia Weiss
46818863e8
implement TopK on time
This replaces the former TopK BSI building algorithm, as the row cache was too expensive.
Additionally, BSI addition has been optimized with specialized adders inside of roaring.
2020-11-20 11:06:55 -05:00
Jason E. Aten
eae82b72c2 rbf: use a red-black tree to manage the root records list
- 40% faster on ingest_test when putting 10K roots/containers.
 - 15% fewer bytes allocated total
 - clarifying renames leafCell.N -> ElemN, allocate -> allocatePgno,
   deallocate -> freePgno
2020-11-13 16:49:26 +00:00
Seebs
a2151358ba Partial implementation: Distinct() supporting set fields
Add an exported IntersectionAny() from roaring to let us quickly
check whether two containers have overlap, so we can avoid performing
intersections we don't need to when evaluating containers within
the same row as a previous match. (IntersectionCount on the whole
bitmap would imply doing up to 16 intersections even if we find a bit
right away.)

We also allow ForeignIndex to be set on set, mutex, and time fields,
since all of those could now be reasonable operands for Distinct
ops.

Not yet present: Handling time quantums, but that seems really
desireable.
2020-10-23 13:36:40 -05:00
Seebs
8095455355 container performance benchmarking
This adds a series of archetypal containers that represent the
common use cases (arrays, bitmaps, or runs of various cardinalities)
and runs the basic operations against them for benchmarking purposes.

`benchpretty` is an app to snatch the BenchmarkCt* lines from
benchmark runs and display them in a possibly more usable form,
mostly as a precursor to cool analysis things.

This also adds a test to verify that intersectionCount(a, b)
is the same as intersect(a, b).N() for all the archetypal
containers.

This also includes a performance fix for intersectBitmapRun which
was spotted while running these tests.
2020-10-22 14:33:03 -05:00
Seebs
76fe49d390 un-disable checkptr by fixing the memory problems
Step one: switch to etcd.io's bbolt fork of boltdb.

The etcd-io fork of boltdb isn't archived, and has fixes for boltdb's
interactions with checkptr, allowing us to drop the checkptr-disabling
hackery.

This seems to be a drop-in replacement; etcd/bbolt says that the file
format is "fixed" (I believe in the sense of "unchanging"), and I can
run pilosa on an existing data directory with this.

Step two:

Fix missing caps in roaring.go that were also triggering the same
issues.
2020-10-15 19:12:47 -05:00
jaten-molecula
eb4b9974ac
Merge branch 'master' into impossible 2020-10-14 18:40:50 -05:00
Seebs
c88192b4ac Check more carefully for, and also fix, containers with invalid N
In rare cases, RBF can produce containers which have a recorded N value which
is incorrect. This rarely affects anything, but on some particular queries,
this can result in very strange outcomes, like array containers with more
than 1<<16 entries.

To fix this, we have toContainer specify that it doesn't know the correct
N for the bitmap containers it's creating, which costs extra time for counting,
and should be considered a temporary workaround.

Also, we add a CheckN() function which is controlled by the
roaringparanoia flag, and add a number of calls to it, for instance, as
deferred calls after every container operation when roaringparanoia is
enabled. This means that we get improved confidence that we've caught
the relevant errors, but is not suitable for production use.
2020-10-14 10:03:18 -05:00
Seebs
fbb648b1fb enforce append-like semantics for *Container more consistently
The copy-on-write/rowCache changes require that functions that
modify containers be able to generate new containers. Once that
became possible, some significant pool of other operations
started relying on it -- for instance, operations might return
a new container even though they're in theory "in place" operations.

I developed a tool for checking for unused function return
values (github.com/molecula/noticeme), and ran it on this, and
picked out the places where `*Container` values were generated
but not used, and some of them seem to be potentially-real
bugs, and a few are probably harmless. Updated code to make
those diagnostics go away.
2020-09-28 12:19:24 -05:00
Jason Aten
7ae8accfa8 Bitmap.DirectAdd avoids returning overfull containers
- log Debugf when we repair a fragment block
- better run-run roaring testing for over-sized containers
- add which fragment path to panic on container too big
- include container contents in roaring hash for pilosa-chk/pilosa-check-backup
2020-09-23 17:13:25 -05:00
Seebs
8ab9174a09 export SetMapped from roaring, use it in Tx stores
Thaw() is supposed to always provide writable storage, which it does
by ensuring that containers aren't frozen, but also by cloning or
copying their data if the data is marked as being memory-mapped.

But only the roaring backend had the ability to mark data as memory-mapped,
because that wasn't exported. Fixed this, and added corresponding code
to badger, lmdb, and rbf.
2020-09-14 14:08:00 -05:00
Jason Aten
2eb097c14d blue_green migration. holdbkg.go holder goroutine.
- blue_green for doing migration. Called before Holder.Open finishes.
- holdbkg.go added for index lookup. Less wedging between a deadlock and a race.
- fix fault under read-only map under lmdb at
  TestExecutor_Execute_Row_Range/RowIDColumnID by doing cow in roaring.
- roaring -tags gofuzz builds again
- roaringparanoia build tag added to make test targets in Makefile
- add rbf.NewDBWithAllocZero for out-of-bounds memory checks
- .circleci/config.yml test-shardwidth-22 with large run container, kept OOM-ing we suspect.

Fixes #819
2020-09-11 14:24:15 -05:00
Seebs
c079d4764b Check for possibly-dirty N values in containers modified in-place
After documenting the semantics, I noticed an arguable hole in them,
which is that you could Freeze() a dirty container, and then Repair()
wouldn't work on it. On further study, I added a roaringparanoia
check for attempts to access the N of dirty containers.

It turns out there's several such. But also, it turns out, there's
circumstances where unionInPlace is relying on the assumption that
N is valid, which it isn't always for dirty containers. Also, there's
at least one case where we rely on the assumption that forcibly
thawing a container, then calling unionInPlace on it, always modifies
that container. But that's not supposed to be true for an empty
container -- an empty container might be better handled by just
returning the container it's being unioned with. So, we drop the
unnecessary thaw (all the *InPlace ops are already thawing if/when
they need to), but we use the return from unionInPlace.
2020-09-08 13:16:54 -05:00
Seebs
17ba2e35a9 call helper functions every time to get new run slices
If you just stash the results of the function when defining the test cases, the
outcome is in part that you are reusing the same slices for multiple things. So,
for instance, if you perform a union on the OddBitsSet slice, with the EvenBitsSet
slice, the result is to overwrite the first entry in that slice with the 0-ffff
run... But the original slice still exists, and then we reuse it and get a slice
with a bit count of around 98,000. The underlying issue is that doContainer()
is calling NewContainerRun(), which is simply using the provided slice, not
copying it -- which is intentional, but the test has to be careful about it.

We call repair on the one we think should be a bitmap. Theoretically
maybe we should also repair the other one in case unionRunRun some day
starts returning unrepaired bitmaps, which in principle it's allowed to
do...
2020-09-08 12:38:49 -05:00
Seebs
ecacbf65d4 Document copy-on-write semantics, at all.
The copy-on-write semantics were previously documented only in
the 125-line commit log from the patch which introduced them. Add
documentation for them in a few likely places.
2020-09-08 11:44:56 -05:00
Nia Weiss
6e06cc0c30
speed up xorArrayArray 2020-08-26 17:14:24 -04:00
Jason Aten
ca7552b4a8 test that roaring.Container.UnionInPlace does
not overflow two big arrays into an invalid array.

recreate badloader from git history, at 85fa67e8. Could not
reproduce this, but lots of container usage
also got updated in the meantime.

Fixes #683
2020-08-24 17:06:41 -05:00
Jason Aten
123ce41840 add lmdb, Tx call stats, and prep for db/shard.
- lmdb as a backend (lmdb.go)
   (lmdb is the fastest known transactional storage backend)
 - per Tx call statics report enabled with PILOSA_CALLSTAT=true (stattx.go)
 - framework for per-shard db (dbshard.go)
 - txfactory handles any pair under blue-green testing (txfactory.go)
 - enable CGO in Dockerfiles for lmdb
2020-08-17 18:26:58 -05:00
Seebs
16ba54293a when updating a container, drop the single-container cache
This can cause incredibly weird and hard-to-debug problems if the previous
container value is still in the cache after an update, and in particular,
can result in having a stale container value cached after a roaring import
that modified the container. Coupled with another bug which could corrupt
containers on a delete, this produces a very strange bug where a value is
present in a fragment, but an attempt to delete it reports failure.
2020-08-17 11:23:47 -05:00
Travis
ff5925aa8b
stop setting N on a frozen container 2020-08-14 17:25:14 -05:00
Todd Gruben
547ee14f5b all test green on rbf. WOOT.
- rbf had races around the new rootRecords cache in tx
 - rbf tx needed a write lock on the db now that rootRecords are written
 - added a global registry for rbfDB to correctly dedup instances
 - implement DeleteFragment, DeleteIndex for rbf
 - use badger style keys for rbf to allow content checksumming to be list
    containers in the same order
 - lots of other integration of rbf into pilosa layer.
2020-08-12 21:08:30 +00:00
Jason Aten
394b8522d1 Follow roaring.Union() with optimize() to avoid overly large containers.
The cmd/loader is a preliminary sketch of the load testing tool.
2020-07-31 20:10:43 -04:00
Jason Aten
72c893a3d1 blueGreenTx roaring vs badger is all tests green (atg).
back to github.com/dgraph-io/badger/v2 v2.0.1-rc1.0.20200709123515-8e896a7af361  b/c github.com/dgraph-io/badger/v2 v2.0.1-rc1.0.20200718033852-37ee16d8ad1c had issues with CI on 386 and arm
2020-07-30 11:50:25 -04:00
Ben Johnson
64de208170 Implement pilosa.Tx for RBF 2020-07-29 11:25:41 -06:00
Jason Aten
ac7be132ef Tx integration milestone
a) All tests green under -race for both PILOSA_TXSRC=roaring and PILOSA_TXSRC=badger.

b) Distinct is merged back into mainline pilosa.

Seebs notes on the Distinct work:

merge Distinct plugin back into main source tree, convert to Tx

We drop all references to the Preemptively Deprecated Don't You Dare
Use This extension interface, and move the one and only extension we had
(Distinct) into the main executor.

Also this fixes an arguable bug, which is that Container.AsBitmap()
would panic on a nil parameter, but it should have returned an empty
bitmap, because a nil *Ccontainer is a valid empty container. This
simplifies logic significantly in Distinct.

Fixes #569 #570 #571 #572 #573 #584 #585
2020-07-27 19:29:46 -04:00
Jason Aten
97b530ca78 integration of Tx, RoaringTx and BadgerTx implementations.
- all tests green on RoaringTx
  - RoaringTx on by default
  - blueGreenTx testing framework available for A-vs-B comparison
    of Tx implementations
  - flag -tx added to server command line but not wired to
    change NewIndex() selection yet.
  - 918 green tests, 14 tests red on BadgerTx.

    A full list of the 14 red tests on BadgerTx follows.
    Note that these red tests represent not defects in BadgerDB
    or BadgerTx but rather failures of the pre-existing pilosa infrastructure to yet
    be fully adapted from files to using a transactional storage engine.

    As such these are tests that RBF should not be expected to
    pass yet either.

    Fixing the pilosa infrastructure to allow these tests
    to go green under Badger is the next and highest priority
    order of business, but RBF can get much testing benefit
    from the 918 green tests we do have, and hence we merge
    as much as we have today.

    The 14 red tests when NewIndex() is set to use
    BadgerTx are as follows. Note in particular
    that pilosa cluster resizing is not working yet under a
    transactional store.

     TestCluster_ResizeStates/Multiple_nodes,_with_data
     TestImportClearRestart/0MaxOpN10000
     TestImportClearRestart/1MaxOpN10000
     TestImportClearRestart/2MaxOpN10000
     TestImportClearRestart/3MaxOpN10000
     TestExecutor_Execute_Existence/Row
     TestExecutor_ForeignIndex
     TestExecutor_Execute_CountDistinct/Distinct
     TestExecutor_Execute_CountDistinct/Count(Distinct)
     TestExecutor_Execute_CountDistinct/GroupBy(Distinct)
     TestExecutor_BareDistinct
     TestExecutor_Execute_TopNDistinct/TopN
     TestHolderSyncer_IntField/BasicSync
     TestHolderSyncer_IntField/MultiShard
2020-07-20 15:50:08 -04:00
Todd Gruben
374a4ec9ce fixed missing refactor test;refactor GetBitmap 2020-07-14 07:57:02 -05:00
Todd Gruben
b11b43af43 refactor putleaf 2020-07-13 10:48:25 -05:00
Ben Johnson
bf55bbc717 Tx Interface
This commit adds a transaction interface which will be used in the
future to add support to RBF (Roaring B-tree Format).
2020-07-02 10:43:15 -06:00
Kuba Podgórski
751383ecb1
Merge branch 'master' into union-run-run 2020-07-02 10:52:59 +02:00
Kuba Podgórski
ec73bf5906
Merge branch 'master' into union-run-run 2020-07-01 22:25:06 +02:00
Jaden Weiss
3e0ce32d00
roaring cleanup 2020-06-30 16:38:16 -04:00