Commit graph

358 commits

Author SHA1 Message Date
Seebs
44314fc32f drop unused row
This looks like leftover code from an earlier draft. We weren't
using this value.
2022-09-30 11:25:27 -07:00
Seebs
ea69b0637d significant refactor of test setup and teardown
We centralize the creation paths for test indexes, fields,
etcetera so they all have a common path, all using standard
test holders. There's still two versions, one for test.* functions
and one for internal. They do share a TestHolderConfig though.

Large hunks of the related APIs are simplified/streamlined.
* Fragments are always created with a Field and don't need
  a workaround in case they don't have it.
* Creation of test fragments, etc., use optional FieldOptions
  but don't specify names because they're all using new holders
  for each thing created anyway. This dramatically reduces
  the complexity of the calls.
* test fragments are created inside test views which are created
  inside test fields, etcetera, so everything is using the same
  logic; test views aren't bypassing the other layers, they're
  creating themselves normally within a field.
* Quite a few things now use the standard runtime/production
  logic instead of being custom workarounds; for instance, instead
  of `mustOpenMutexFragment` creating a fragment and then creating
  a mutex vector for it, we just create a mutex-typed field and
  have the normal runtime code do this.
* Similarly, we now use the same field creation logic that production
  does, instead of having our own test-only thing that validates
  field names directly, so our test that we're validating field names
  is actually testing the runtime code. Yay.
* fragSpec goes away. it was a replacement for fragProxy which existed
  to solve memory allocation problems but replaced them with interface
  overhead problems. Now we just have pointers to things and maintain
  valid data structures.
* Many panics are now Fatal or Fatalf calls.
* Some specific bugs fixed, like a cluster which was requested and
  then had its first node directly overwritten, which isn't valid with
  shared clusters.
* Drop the temp-dir test flag and TempDir variable, we can just use
  $TMPDIR.
* Drop a benchmark of "write file to disk" that was purely a benchmark
  of file write speed, not a benchmark of rendering the data that needs
  to be written.
* Drop the unused "flags" parameter to fragment creation, which was
  only used back when we changed the BSI format.
* Use holder.Txf() rather than index.Txf(). The TxFactory has to be
  holder-level anyway, referring to it via the index is misleading.
* Test holders automatically close themselves and delete themselves,
  we remove various other things that thought they were responsible
  for deleting themselves.
2022-09-30 11:25:27 -07:00
Seebs
e8e655cf05 continue removing Tx parameters to view-type functions
A few view functions were taking a Tx, which had to be shard-specific,
but that's sort of awkward -- the view is inherently not shard-specific,
so it should be handling sharding internally.

There were also a couple of remaining obsolete checks for whether a
Tx was nil, at least two of which were in contexts where it absolutely
can't be. Remove all of them, and also the function itself.
2022-09-30 11:25:27 -07:00
CLoZengineer
f9ddb5d5c1
fix: updating code to meet linting requirements (#2171)
* removes unused filesize function

* removes ioutil usage

* updates ioutil.ReadAll to io.ReadAll

* updates ioutil.TempFile to os.CreateTemp

* updates ioutil.TempDir to os.MkdirTemp

* updates ioutil.ReadAll to os.ReadAll

* update ioutil.WriteFile to os.WriteFile

* updates ioutil.Discard to io.Discard

* updates ioutil.ReadDir to os.ReadDir where applicable

* removes unused code in idk

* creates type to use for context value keys

* replaces assert.Nil with assert.NoError for error checks
2022-09-29 12:34:29 -04:00
Fletcher Haynes
da9b57bd45 Updated dependency paths to reflect new repo location 2022-09-06 09:39:22 -07:00
Fletcher Haynes
eb06bb50ae Updated code to latest version for open-sourcing. 2022-09-02 13:23:39 -07:00
Travis Turner
56adbfedfd
Fix off-by-one maxRowID in block limits 2020-05-04 17:29:53 -05:00
Travis Turner
020b72abbf
reset fragment.rowCache after importValue 2019-11-06 13:19:12 -06:00
Ben Johnson
c7c9c1e1d7
v2.0.0
Co-authored-by: Cody Soyland <codysoyland@gmail.com>
2019-10-08 14:56:17 -06:00
Seebs
b04037900c move to using roaring iterators for UnmarshalBinary
The new roaring iterator used for the remap and importroaring
things could also be used for unmarshalling roaring streams,
and it's a slightly simpler design that doesn't need two passes
through the data. This patch cleans that up a bit, makes it work
better with ops logs, and uses that instead. It appears to
noticably but not immensely reduce the time imports take, but it
also gets us back down to one thing parsing roaring formats.

There are a couple of subtle changes to errors we were testing
for in various tests, and one of the fuzz tests goes away because
it was actually itself an erroneous error message -- it was reporting
the header of a roaring file as an invalid op because the op log
reader was running on the header for roaring files with zero
containers. Oops.
2019-07-25 16:03:18 -05:00
Seebs
0960d66c94
update diagnostic message, use read locks for read
Annoyingly, this is actually the only place we can make
a read-only lock, because the row() call might write to
the row cache, so it needs the write lock. We might be
able to fix that later, though.
2019-07-01 13:16:03 -05:00
Seebs
b74956e48e
drop no-longer-used timeout case 2019-07-01 13:16:02 -05:00
Seebs
17eb13702e
address lint concerns
Addressing various lint.

incrementOpN no longer returns errors, because it no longer waits for
the snapshot, so checking those errors is unnecessary.

Several fields in a common embedded structure were "unused" according
to a naive checker.

Other tiny style things, and one actual unchecked error. Yay linters!
2019-07-01 13:16:02 -05:00
Seebs
5e3d01febe
lock fragment to compute rows
If you don't hold the fragment lock when computing rows, it's
pretty reasonable for other stuff to be able to modify it -- which
could invalidate or race the enumeration.

Some calls to f.rows were being made with the lock held, others
weren't, so we introduce `f.unprotectedRows` which has the obvious
semantics. (Without which this looked great except that several
of the tests deadlocked.)
2019-07-01 13:16:02 -05:00
Seebs
4b657c1962
use a queue for snapshot operations
As the size of a fragment grows, the cost of snapshots
increases; with a large fragment getting a lot of large writes,
every write will trigger a snapshot, while any other writes have
to wait for that snapshot before they, too, can trigger a snapshot.

To address this, we introduce a background queue of snapshots.
In general, operations which were omitting their ops log writes
and just snapshotting no longer do; they emit an ops log. This does
mean that, in some cases, the ops log is written and then a snapshot
takes place essentially immediately, which costs us some performance.
However, that only actually happens under very light load; under
heavier load, there's generally going to be multiple writes coalesced
into each snapshot, and the ops log writes for them will be much
cheaper than a full snapshot.
2019-07-01 13:16:02 -05:00
Seebs
b369dace69
remap storage on reopen, instead of remarshalling it
When we do a snapshot, we may end up with containers which are
mmapped to the old file, and containers which have allocated storage
identical to the contents of the new file. It would be nicer if they
were mapped to it. But unmarshalling the entire file is expensive.

Instead, we remap it. (Or, if we couldn't mmap it, just make sure
the old stuff is no longer using the old storage space before we
munmap it.)
2019-07-01 13:16:02 -05:00
Seebs
565288f6c2
use ImportRoaringBits to implement importRoaring
Instead of fancy bitmap ops or ImportPositions, we use the
recently-added ImportRoaringBits operations, which can dump
themselves to op logs much more efficiently, and which are
also usually much more efficient than things like "create a
new bitmap which is a copy of the old one".
2019-07-01 13:16:02 -05:00
Yuce Tekol
dec665ac75
Merge branch 'master' into min-max-rowid 2019-06-17 22:44:33 +03:00
Yuce Tekol
06aa2cf98e
updated for feedback from PR 1983 2019-06-15 15:15:20 +03:00
Yuce Tekol
c9854c00fb
updated with atomic writes 2019-06-12 16:46:18 +03:00
Yuce Tekol
b64a3e0c68
adds filter support to MinRow and MaxRow 2019-06-03 16:29:04 +03:00
Yuce Tekol
08f4ccb29b
Fixed conflicts; Merged with master 2019-05-31 17:16:54 +03:00
Yuce Tekol
dd728f28ed
remove unused code 2019-05-31 17:13:25 +03:00
Yuce Tekol
d2aca3bbfc
Added MinRow and MaxRow calls 2019-05-31 15:32:15 +03:00
Seebs
c133ce0376 Make containers copy-on-write
This patch replaces a lot of circumstances in which containers
were being copied with circumstances in which they are shared,
using copy-on-write semantics.

To achieve this, we emulate somewhat the design of go's
native `append` function. Operations on a container may optionally
yield a new container. A container can be marked "frozen",
after which no operation should ever write to it in any way;
that applies both to the container itself and the backing store
it refers to, if any. So for instance, instead of:

	c.arrayToBitmap()

we now write:

	c = c.arrayToBitmap()

Operations which need to modify a container in any way
need to be able to return a new container, which is a modified
copy of the previous container. This applies to operations
like add/remove, but also to things like unmapping memory-mapped
storage, or changing a container's type.

Bitmaps do not support the same copy-on-write semantics,
currently, but "copying" a bitmap and sharing the containers
instead of duplicating them is *much* cheaper than copying
the containers.

Bitmaps do support a .Freeze method, which currently copies
the previous bitmap, making a new one with the same container
pointers, and freezes the individual containers. Use this
if you need a writeable copy of a bitmap -- the resulting
bitmap can safely have its set of containers modified, and
bitmap operators that would want to modify the containers
will use copy-on-write for that.

The primary motivation of this is to reduce the cost of the
row cache used by fragments. As a secondary issue, the row cache
is no longer updated on writes -- that update was actually a
race condition waiting to happen. Rather, writes to a row
invalidate the cache entry for that row. The row cache is
created by creating a new bitmap, and freezing the relevant
containers from the fragment's storage. In the case where
nothing is being written, the row cache grows to contain
bitmaps containing all those containers, but never copies
any containers. If nothing's being read, the row cache is
never created, and the containers are in general not getting
frozen. The only circumstance where copies have to happen is
when things are read (and thus stored in the row cache) and
later modified. In that case, each read freezes objects, and
the first write to a container after it's been frozen will
create a new copy.

We drop the enterprise/b btree implementation, because we
don't really need it anymore -- we now provide that
implementation by default in the open source product anyway.

Along with this, there's a lot of other changes which
improve support for nil containers, as a cheaper representation
for empty containers. Operations which we know will provide
an empty container can always short-circuit and just yield
a nil *Container. Similarly, operations which would provide
a full container can return a single shared full container
object (which is frozen). The higher-level (non type-specific)
container ops are now using that logic to short-circuit
operations for empty and full containers. (For instance,
difference of anything minus an empty container is the
original thing, union of anything and empty is the original
thing, and so on.)

The Containers interface adds "Update" and "UpdateEvery"
methods, based in part on the "Put" interface provided
by the underlying btree implementation; Update performs
a possible update in-place of a container for a given
key, bypassing the need to replicate the search for that
key in the container. UpdateEvery loops through all the
containers.

Containers do not strictly guarantee that they won't
return nil `*Container` objects. However, the container
iterators won't return those -- empty containers aren't
interesting. Some tests are updated to reflect this.

Some of the container internals, like N(), or the isArray()
and related functions, accept nil container pointers. Some,
like Thaw(), do not. For the array(), bitmap(), and runs()
methods, roaringparanoia enables an explicit panic on a nil
container explaining the problem, but the intent is that those
should never be called unless you already know you have the
right kind of container, so by default they don't perform
the extra checks. In most cases, this is already covered
because a nil container is empty, and there's no operation
we can perform that requires us to inspect the contents of
an empty container. This is passing a fair amount of testing,
but the testing may not be comprehensive enough.

The overall impact of this is pretty trivial performance-wise.
In our default roaring/ benchmarks, a few things get a few
percent faster, or slower. The advantage is that, with
read-heavy workloads, the row cache no longer eats up incredible
amounts of memory.

For a smallish test case, pilosa's memory usage (RES in top) after
startup was ~2.5GB. Without this patch, simply reading every
row a few times got memory usage to about 9GB, which seemed
reasonably stable. With this patch, memory usage went to about
3GB. This will be less noticeable in mixed read/write loads,
but it should be consistently significantly lower.

In addition to dropping things from the rowCache on modifications,
we also stopped performing a full count on a modified row when
not using a cache of a kind that would use that count, and don't
repopulate the rowCache regardless. We don't want every write
to imply a corresponding read after it.

There's a lot of room for possible future optimizations in
terms of things like in-place operations, and some of the
row/rowSegment code is a little suspicious to me, but I don't
think it should be *worse* in any cases.
2019-05-30 16:36:20 -05:00
Ben Johnson
d4de122549
Add min/max constraints 2019-05-17 15:52:17 -06:00
Ben Johnson
7ed9fba335
Unbounded BSI w/ sign magnitude
This commit implements BSI with variable bit depth using a
sign magnitudeto indicate whether a value is positive or negative.
This also rearranges the existence bit to be the first bit instead
of the last bit.
2019-05-17 15:52:17 -06:00
Matt Jaffee
00911d024b
add span around fragment lock, bytes written metadata 2019-04-30 16:55:46 -05:00
Matt Jaffee
61bf3d929d
Add more tracing and metdata to importRoaring 2019-04-30 15:49:52 -05:00
Travis Turner
875c95b2c3
add more Debugf() statements to the holder open process 2019-04-30 15:16:10 -05:00
Travis Turner
b46ff7b990
fix some lint warnings raised in VS-Code 2019-04-17 18:10:05 -05:00
Seebs
77d49ded64 so much lint
So with the switch to a new linter, we get a lot of new warnings,
and the majority of them are harmless probably, but a few might be
real. Variously just use _ to suppress warnings, or report errors.
There's probably things here that deserve better fixes, but we can
always revisit it.
2019-04-16 12:07:18 -05:00
Matt Jaffee
811f1b4124
move build-tagged shardwidth files to subpackage 2019-04-04 14:27:52 -05:00
Matt Jaffee
836b467d3d
add support to modify shard width at build time
use "make <x> SHARD_WIDTH=nn"

fix tests to run and pass at different shardwidths

add shardwidth22 test to circle ci
2019-04-04 13:46:26 -05:00
Matt Jaffee
6130764ede
fix data loss bug and robustify test
Data loss was occuring after a cluster restart. The issue was during the
unmarshaling of the op log when multiple values had been written to the log. The
lines in question were like "changed = changed || b.DirectAdd(v)" in which the
DirectAdd would only be executed when changed was initially false, once it was
true, it would never be executed again.
2019-04-01 14:14:26 -05:00
Matt Jaffee
207b39717b
test both importValue write paths and fix bug
fix large write path—there was a bug because we were iterating backwards over
the small write path to fix that bug, but the large write path needs to iterate
forward. There is enough code difference between the two paths that they are now
two separate methods (which are probably easier to read).
2019-03-29 14:11:06 -05:00
Matt Jaffee
cde954e12f
importValue only considers the last instance of a column id
included test demonstrates bug
2019-03-29 13:37:22 -05:00
Matt Jaffee
c651ff9299
use BTree bitmap in importRoaring
sliceContainers very slow to union into
2019-03-28 13:49:01 -05:00
Matt Jaffee
714f89c65c
simplify locking in importValue
may be a slight perf cost, but the simplicity is well worth it
2019-03-25 14:27:05 -05:00
Matt Jaffee
4420d72196
test concurrent value imports, fix race 2019-03-25 14:25:22 -05:00
Matt Jaffee
e7f65cf7be
implement global open file counter using syswrap
close files after using them if global max is passed.

I originally implemented this without the global count—just always closing files
when done with them, and reopening for new writes. This was crazy slow for that
one test that uses mustSetBits in a big loop. I modified the test to use
importRoaring and everything worked better (though much more slowly).

After adding the global counter, I ran the tests with that one test using
mustSetBits again, and the performance was similar to master. After completing
this PR, I ran the tests with the max limit set to 5—they still passed but were
much slower.
2019-03-23 14:52:16 -05:00
Matt Jaffee
226f15446b
lock MaxMapCount and fix unused var 2019-03-19 12:55:26 -05:00
Matt Jaffee
e469285fe3
add fragment mmap tracking and limiting
in the case that the map limit is reached, we'll fall back to reading the file
into memory normally.
2019-03-19 12:55:26 -05:00
Todd Gruben
327aa70924
add failure path for mmap 2019-03-19 12:55:25 -05:00
Seebs
054cb206d5 improve union-related benchmarking
Add a benchmark to test a specific case where UnionInPlace is
underperforming the naive union operation badly.

Also, the UnionBulk test was reusing a bitmap, meaning that it ended
up doing a lot of unions into a bitmap that already had all the
bits it was supposed to have. This broke a couple of other tests
in unexpected ways.

We also now use UnionInPlace in importRoaring, and test it
in the container combinations tests via a wrapper.
2019-03-14 15:16:49 -05:00
Matt Jaffee
a28141c466
revert to Union for importRoaring
UnionInPlace is still heavily affected by
https://github.com/pilosa/pilosa/issues/1875 where containers that exist in an
incoming bitmap can cause massive unnecessary allocations of bitmap containers
when an array of short length is all that's needed.
2019-03-11 17:43:55 -05:00
Matt Jaffee
52d43fb4e2
add smallPath for importRoaring
this converts the rowSet to a map from a slice which might be bad... benchmarks
will tell.
2019-03-11 17:43:55 -05:00
Matt Jaffee
19807ff3a7
use num containers to decide which direction to union
avoids doing a potentially expensive f.storage.Count()
2019-03-11 17:43:55 -05:00
Matt Jaffee
e33ca2d0ae
use UnionInPlace in import-roaring
get the count of the existing fragment and compare it to the incoming bits to
decide which should be unioned into the other. This should generally result in
far fewer allocations, though there is much work that needs to be done within
UnionInPlace to further improve things.

unrelatedly, I added a TODO to change the long-query-time option to move it out
of cluster. It should probably be happening at the API level so that different
handlers can reuse it, but if we're going to do that we'll want to make sure
that any potentially time intensive operations are pulled into api from
handler (e.g. protobuf decoding)
2019-03-11 17:43:55 -05:00
Matt Jaffee
e54dbd6731
simplify row/lastRow comparison in bulkImport 2019-03-05 12:20:21 -06:00