Compare commits
29 Commits
c11b4714b5
...
erase-betw
Author | SHA1 | Date | |
---|---|---|---|
5a132799a4 | |||
72469ebb6e | |||
6c79847a42 | |||
405a2ca161 | |||
f93466316a | |||
5626cd09d9 | |||
41840220c3 | |||
7ff00e7846 | |||
6242f40d48 | |||
403d70a1d3 | |||
9763452713 | |||
73d0593fca | |||
23c2a3e1c6 | |||
a64e792964 | |||
5e362d5330 | |||
cc526cb6ba | |||
7e49888bec | |||
e64ebabced | |||
1e34951a77 | |||
baf64520d6 | |||
3499626127 | |||
b7f9084694 | |||
4b82502946 | |||
68bbacb69a | |||
3078845673 | |||
43f6126cc4 | |||
b911d87d55 | |||
0c65a82b78 | |||
e024cb8291 |
16
Bench.cpp
16
Bench.cpp
@@ -361,7 +361,21 @@ void benchWorstCaseForRadixRangeRead() {
|
||||
void benchCreateAndDestroy() {
|
||||
ankerl::nanobench::Bench bench;
|
||||
|
||||
bench.run("create and destroy", [&]() { ConflictSet cs{0}; });
|
||||
bench.run("create and destroy", [&]() {
|
||||
ConflictSet cs{0};
|
||||
ConflictSet::WriteRange w;
|
||||
uint8_t b[9];
|
||||
b[8] = 0;
|
||||
for (int64_t i = 0; i < 1000; i += 7) {
|
||||
auto x = __builtin_bswap64(i);
|
||||
memcpy(b, &x, 8);
|
||||
w.begin.p = b;
|
||||
w.begin.len = 8;
|
||||
w.end.len = 0;
|
||||
w.end.p = b;
|
||||
cs.addWrites(&w, 1, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
|
698
ConflictSet.cpp
698
ConflictSet.cpp
@@ -195,7 +195,6 @@ struct Node {
|
||||
/* end section that's copied to the next node */
|
||||
|
||||
uint8_t *partialKey();
|
||||
size_t size() const;
|
||||
|
||||
Type getType() const { return type; }
|
||||
int32_t getCapacity() const { return partialKeyCapacity; }
|
||||
@@ -224,6 +223,9 @@ struct Node0 : Node {
|
||||
|
||||
void copyChildrenAndKeyFrom(const Node0 &other);
|
||||
void copyChildrenAndKeyFrom(const struct Node3 &other);
|
||||
void copyChildrenAndKeyFrom(const struct Node16 &other);
|
||||
void copyChildrenAndKeyFrom(const struct Node48 &other);
|
||||
void copyChildrenAndKeyFrom(const struct Node256 &other);
|
||||
|
||||
size_t size() const { return sizeof(Node0) + getCapacity(); }
|
||||
};
|
||||
@@ -240,6 +242,8 @@ struct Node3 : Node {
|
||||
void copyChildrenAndKeyFrom(const Node0 &other);
|
||||
void copyChildrenAndKeyFrom(const Node3 &other);
|
||||
void copyChildrenAndKeyFrom(const struct Node16 &other);
|
||||
void copyChildrenAndKeyFrom(const struct Node48 &other);
|
||||
void copyChildrenAndKeyFrom(const struct Node256 &other);
|
||||
|
||||
size_t size() const { return sizeof(Node3) + getCapacity(); }
|
||||
};
|
||||
@@ -256,6 +260,7 @@ struct Node16 : Node {
|
||||
void copyChildrenAndKeyFrom(const Node3 &other);
|
||||
void copyChildrenAndKeyFrom(const Node16 &other);
|
||||
void copyChildrenAndKeyFrom(const struct Node48 &other);
|
||||
void copyChildrenAndKeyFrom(const struct Node256 &other);
|
||||
|
||||
size_t size() const { return sizeof(Node16) + getCapacity(); }
|
||||
};
|
||||
@@ -313,6 +318,24 @@ inline void Node0::copyChildrenAndKeyFrom(const Node3 &other) {
|
||||
memcpy(partialKey(), &other + 1, partialKeyLen);
|
||||
}
|
||||
|
||||
inline void Node0::copyChildrenAndKeyFrom(const Node16 &other) {
|
||||
memcpy((char *)this + kNodeCopyBegin, (char *)&other + kNodeCopyBegin,
|
||||
kNodeCopySize);
|
||||
memcpy(partialKey(), &other + 1, partialKeyLen);
|
||||
}
|
||||
|
||||
inline void Node0::copyChildrenAndKeyFrom(const Node48 &other) {
|
||||
memcpy((char *)this + kNodeCopyBegin, (char *)&other + kNodeCopyBegin,
|
||||
kNodeCopySize);
|
||||
memcpy(partialKey(), &other + 1, partialKeyLen);
|
||||
}
|
||||
|
||||
inline void Node0::copyChildrenAndKeyFrom(const Node256 &other) {
|
||||
memcpy((char *)this + kNodeCopyBegin, (char *)&other + kNodeCopyBegin,
|
||||
kNodeCopySize);
|
||||
memcpy(partialKey(), &other + 1, partialKeyLen);
|
||||
}
|
||||
|
||||
inline void Node3::copyChildrenAndKeyFrom(const Node0 &other) {
|
||||
memcpy((char *)this + kNodeCopyBegin, (char *)&other + kNodeCopyBegin,
|
||||
kNodeCopySize);
|
||||
@@ -344,17 +367,53 @@ inline void Node3::copyChildrenAndKeyFrom(const Node16 &other) {
|
||||
}
|
||||
}
|
||||
|
||||
inline void Node3::copyChildrenAndKeyFrom(const Node48 &other) {
|
||||
memcpy((char *)this + kNodeCopyBegin, (char *)&other + kNodeCopyBegin,
|
||||
kNodeCopySize);
|
||||
int i = 0;
|
||||
other.bitSet.forEachSet([&](int c) {
|
||||
// Suppress a false positive -Waggressive-loop-optimizations warning
|
||||
// in gcc
|
||||
assume(i < kMaxNodes);
|
||||
index[i] = c;
|
||||
children[i] = other.children[other.index[c]];
|
||||
childMaxVersion[i] = other.childMaxVersion[other.index[c]];
|
||||
assert(children[i]->parent == &other);
|
||||
children[i]->parent = this;
|
||||
++i;
|
||||
});
|
||||
memcpy(partialKey(), &other + 1, partialKeyLen);
|
||||
}
|
||||
|
||||
inline void Node3::copyChildrenAndKeyFrom(const Node256 &other) {
|
||||
memcpy((char *)this + kNodeCopyBegin, (char *)&other + kNodeCopyBegin,
|
||||
kNodeCopySize);
|
||||
int i = 0;
|
||||
other.bitSet.forEachSet([&](int c) {
|
||||
// Suppress a false positive -Waggressive-loop-optimizations warning
|
||||
// in gcc
|
||||
assume(i < kMaxNodes);
|
||||
index[i] = c;
|
||||
children[i] = other.children[c];
|
||||
childMaxVersion[i] = other.childMaxVersion[c];
|
||||
assert(children[i]->parent == &other);
|
||||
children[i]->parent = this;
|
||||
++i;
|
||||
});
|
||||
memcpy(partialKey(), &other + 1, partialKeyLen);
|
||||
}
|
||||
|
||||
inline void Node16::copyChildrenAndKeyFrom(const Node3 &other) {
|
||||
memcpy((char *)this + kNodeCopyBegin, (char *)&other + kNodeCopyBegin,
|
||||
kNodeCopySize);
|
||||
memcpy(index, other.index, Node3::kMaxNodes);
|
||||
memcpy(index, other.index, other.kMaxNodes);
|
||||
memcpy(children, other.children,
|
||||
Node3::kMaxNodes * sizeof(children[0])); // NOLINT
|
||||
other.kMaxNodes * sizeof(children[0])); // NOLINT
|
||||
memcpy(childMaxVersion, other.childMaxVersion,
|
||||
Node3::kMaxNodes * sizeof(childMaxVersion[0]));
|
||||
other.kMaxNodes * sizeof(childMaxVersion[0]));
|
||||
memcpy(partialKey(), &other + 1, partialKeyLen);
|
||||
assert(numChildren == Node3::kMaxNodes);
|
||||
for (int i = 0; i < Node3::kMaxNodes; ++i) {
|
||||
assert(numChildren == other.kMaxNodes);
|
||||
for (int i = 0; i < other.kMaxNodes; ++i) {
|
||||
assert(children[i]->parent == &other);
|
||||
children[i]->parent = this;
|
||||
}
|
||||
@@ -380,7 +439,7 @@ inline void Node16::copyChildrenAndKeyFrom(const Node48 &other) {
|
||||
other.bitSet.forEachSet([&](int c) {
|
||||
// Suppress a false positive -Waggressive-loop-optimizations warning
|
||||
// in gcc
|
||||
assume(i < Node16::kMaxNodes);
|
||||
assume(i < kMaxNodes);
|
||||
index[i] = c;
|
||||
children[i] = other.children[other.index[c]];
|
||||
childMaxVersion[i] = other.childMaxVersion[other.index[c]];
|
||||
@@ -391,10 +450,28 @@ inline void Node16::copyChildrenAndKeyFrom(const Node48 &other) {
|
||||
memcpy(partialKey(), &other + 1, partialKeyLen);
|
||||
}
|
||||
|
||||
inline void Node16::copyChildrenAndKeyFrom(const Node256 &other) {
|
||||
memcpy((char *)this + kNodeCopyBegin, (char *)&other + kNodeCopyBegin,
|
||||
kNodeCopySize);
|
||||
int i = 0;
|
||||
other.bitSet.forEachSet([&](int c) {
|
||||
// Suppress a false positive -Waggressive-loop-optimizations warning
|
||||
// in gcc
|
||||
assume(i < kMaxNodes);
|
||||
index[i] = c;
|
||||
children[i] = other.children[c];
|
||||
childMaxVersion[i] = other.childMaxVersion[c];
|
||||
assert(children[i]->parent == &other);
|
||||
children[i]->parent = this;
|
||||
++i;
|
||||
});
|
||||
memcpy(partialKey(), &other + 1, partialKeyLen);
|
||||
}
|
||||
|
||||
inline void Node48::copyChildrenAndKeyFrom(const Node16 &other) {
|
||||
memcpy((char *)this + kNodeCopyBegin, (char *)&other + kNodeCopyBegin,
|
||||
kNodeCopySize);
|
||||
assert(numChildren == Node16::kMaxNodes);
|
||||
assert(numChildren == other.kMaxNodes);
|
||||
memset(index, -1, sizeof(index));
|
||||
memset(children, 0, sizeof(children));
|
||||
const auto z = InternalVersionT::zero;
|
||||
@@ -403,7 +480,7 @@ inline void Node48::copyChildrenAndKeyFrom(const Node16 &other) {
|
||||
}
|
||||
memcpy(partialKey(), &other + 1, partialKeyLen);
|
||||
bitSet.init();
|
||||
nextFree = Node16::kMaxNodes;
|
||||
nextFree = other.kMaxNodes;
|
||||
int i = 0;
|
||||
for (auto x : other.index) {
|
||||
bitSet.set(x);
|
||||
@@ -413,8 +490,8 @@ inline void Node48::copyChildrenAndKeyFrom(const Node16 &other) {
|
||||
assert(children[i]->parent == &other);
|
||||
children[i]->parent = this;
|
||||
reverseIndex[i] = x;
|
||||
maxOfMax[i >> Node48::kMaxOfMaxShift] =
|
||||
std::max(maxOfMax[i >> Node48::kMaxOfMaxShift], childMaxVersion[i]);
|
||||
maxOfMax[i >> kMaxOfMaxShift] =
|
||||
std::max(maxOfMax[i >> kMaxOfMaxShift], childMaxVersion[i]);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
@@ -456,15 +533,15 @@ inline void Node48::copyChildrenAndKeyFrom(const Node256 &other) {
|
||||
bitSet.forEachSet([&](int c) {
|
||||
// Suppress a false positive -Waggressive-loop-optimizations warning
|
||||
// in gcc.
|
||||
assume(i < Node48::kMaxNodes);
|
||||
assume(i < kMaxNodes);
|
||||
index[c] = i;
|
||||
children[i] = other.children[c];
|
||||
childMaxVersion[i] = other.childMaxVersion[c];
|
||||
assert(children[i]->parent == &other);
|
||||
children[i]->parent = this;
|
||||
reverseIndex[i] = c;
|
||||
maxOfMax[i >> Node48::kMaxOfMaxShift] =
|
||||
std::max(maxOfMax[i >> Node48::kMaxOfMaxShift], childMaxVersion[i]);
|
||||
maxOfMax[i >> kMaxOfMaxShift] =
|
||||
std::max(maxOfMax[i >> kMaxOfMaxShift], childMaxVersion[i]);
|
||||
++i;
|
||||
});
|
||||
memcpy(partialKey(), &other + 1, partialKeyLen);
|
||||
@@ -487,8 +564,8 @@ inline void Node256::copyChildrenAndKeyFrom(const Node48 &other) {
|
||||
childMaxVersion[c] = other.childMaxVersion[other.index[c]];
|
||||
assert(children[c]->parent == &other);
|
||||
children[c]->parent = this;
|
||||
maxOfMax[c >> Node256::kMaxOfMaxShift] =
|
||||
std::max(maxOfMax[c >> Node256::kMaxOfMaxShift], childMaxVersion[c]);
|
||||
maxOfMax[c >> kMaxOfMaxShift] =
|
||||
std::max(maxOfMax[c >> kMaxOfMaxShift], childMaxVersion[c]);
|
||||
});
|
||||
memcpy(partialKey(), &other + 1, partialKeyLen);
|
||||
}
|
||||
@@ -693,23 +770,6 @@ uint8_t *Node::partialKey() {
|
||||
}
|
||||
}
|
||||
|
||||
size_t Node::size() const {
|
||||
switch (type) {
|
||||
case Type_Node0:
|
||||
return ((Node0 *)this)->size();
|
||||
case Type_Node3:
|
||||
return ((Node3 *)this)->size();
|
||||
case Type_Node16:
|
||||
return ((Node16 *)this)->size();
|
||||
case Type_Node48:
|
||||
return ((Node48 *)this)->size();
|
||||
case Type_Node256:
|
||||
return ((Node256 *)this)->size();
|
||||
default: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
// A type that's plumbed along the check call tree. Lifetime ends after each
|
||||
// check call.
|
||||
struct ReadContext {
|
||||
@@ -1544,6 +1604,46 @@ void rezero(Node *n, InternalVersionT z) {
|
||||
}
|
||||
}
|
||||
|
||||
void mergeWithChild(Node *&self, WriteContext *tls, ConflictSet::Impl *impl,
|
||||
Node *&dontInvalidate, Node3 *self3) {
|
||||
assert(!self3->entryPresent);
|
||||
auto *child = self3->children[0];
|
||||
int minCapacity = self3->partialKeyLen + 1 + child->partialKeyLen;
|
||||
|
||||
if (minCapacity > child->getCapacity()) {
|
||||
const bool update = child == dontInvalidate;
|
||||
freeAndMakeCapacityAtLeast(child, minCapacity, tls, impl, true);
|
||||
if (update) {
|
||||
dontInvalidate = child;
|
||||
}
|
||||
}
|
||||
|
||||
// Merge partial key with child
|
||||
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
||||
fprintf(stderr, "Merge %s into %s\n", getSearchPathPrintable(self).c_str(),
|
||||
getSearchPathPrintable(child).c_str());
|
||||
#endif
|
||||
|
||||
InternalVersionT childMaxVersion = self3->childMaxVersion[0];
|
||||
|
||||
// Construct new partial key for child
|
||||
memmove(child->partialKey() + self3->partialKeyLen + 1, child->partialKey(),
|
||||
child->partialKeyLen);
|
||||
memcpy(child->partialKey(), self3->partialKey(), self->partialKeyLen);
|
||||
child->partialKey()[self3->partialKeyLen] = self3->index[0];
|
||||
child->partialKeyLen += 1 + self3->partialKeyLen;
|
||||
|
||||
child->parent = self->parent;
|
||||
child->parentsIndex = self->parentsIndex;
|
||||
|
||||
// Max versions are stored in the parent, so we need to update it now
|
||||
// that we have a new parent.
|
||||
setMaxVersion(child, impl, std::max(childMaxVersion, tls->zero));
|
||||
|
||||
self = child;
|
||||
tls->release(self3);
|
||||
}
|
||||
|
||||
void maybeDownsize(Node *self, WriteContext *tls, ConflictSet::Impl *impl,
|
||||
Node *&dontInvalidate) {
|
||||
|
||||
@@ -1557,50 +1657,13 @@ void maybeDownsize(Node *self, WriteContext *tls, ConflictSet::Impl *impl,
|
||||
case Type_Node3: {
|
||||
auto *self3 = (Node3 *)self;
|
||||
if (self->numChildren == 0) {
|
||||
assert(self->entryPresent);
|
||||
auto *newSelf = tls->allocate<Node0>(self->partialKeyLen);
|
||||
newSelf->copyChildrenAndKeyFrom(*self3);
|
||||
getInTree(self, impl) = newSelf;
|
||||
tls->release(self3);
|
||||
} else if (self->numChildren == 1 && !self->entryPresent) {
|
||||
auto *child = self3->children[0];
|
||||
int minCapacity = self3->partialKeyLen + 1 + child->partialKeyLen;
|
||||
|
||||
if (minCapacity > child->getCapacity()) {
|
||||
const bool update = child == dontInvalidate;
|
||||
freeAndMakeCapacityAtLeast(child, minCapacity, tls, impl, true);
|
||||
if (update) {
|
||||
dontInvalidate = child;
|
||||
}
|
||||
}
|
||||
|
||||
// Merge partial key with child
|
||||
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
||||
fprintf(stderr, "Merge %s into %s\n",
|
||||
getSearchPathPrintable(self).c_str(),
|
||||
getSearchPathPrintable(child).c_str());
|
||||
#endif
|
||||
|
||||
InternalVersionT childMaxVersion = maxVersion(child, impl);
|
||||
|
||||
// Construct new partial key for child
|
||||
memmove(child->partialKey() + self3->partialKeyLen + 1,
|
||||
child->partialKey(), child->partialKeyLen);
|
||||
memcpy(child->partialKey(), self3->partialKey(), self->partialKeyLen);
|
||||
child->partialKey()[self3->partialKeyLen] = self3->index[0];
|
||||
child->partialKeyLen += 1 + self3->partialKeyLen;
|
||||
|
||||
child->parent = self->parent;
|
||||
child->parentsIndex = self->parentsIndex;
|
||||
|
||||
// Max versions are stored in the parent, so we need to update it now
|
||||
// that we have a new parent.
|
||||
setMaxVersion(child, impl, childMaxVersion);
|
||||
if (child->parent) {
|
||||
rezero(child->parent, tls->zero);
|
||||
}
|
||||
|
||||
getInTree(self, impl) = child;
|
||||
tls->release(self3);
|
||||
mergeWithChild(getInTree(self, impl), tls, impl, dontInvalidate, self3);
|
||||
}
|
||||
} break;
|
||||
case Type_Node16:
|
||||
@@ -1635,10 +1698,266 @@ void maybeDownsize(Node *self, WriteContext *tls, ConflictSet::Impl *impl,
|
||||
}
|
||||
}
|
||||
|
||||
void eraseTree(Node *root, WriteContext *tls) {
|
||||
Arena arena;
|
||||
auto toFree = vector<Node *>(arena);
|
||||
toFree.push_back(root);
|
||||
|
||||
while (toFree.size() > 0) {
|
||||
auto *n = toFree.back();
|
||||
toFree.pop_back();
|
||||
tls->accum.entries_erased += n->entryPresent;
|
||||
++tls->accum.nodes_released;
|
||||
|
||||
removeNode(n);
|
||||
removeKey(n);
|
||||
|
||||
switch (n->getType()) {
|
||||
case Type_Node0: {
|
||||
auto *n0 = static_cast<Node0 *>(n);
|
||||
tls->release(n0);
|
||||
} break;
|
||||
case Type_Node3: {
|
||||
auto *n3 = static_cast<Node3 *>(n);
|
||||
toFree.append(std::span<Node *>(n3->children, n3->numChildren));
|
||||
tls->release(n3);
|
||||
} break;
|
||||
case Type_Node16: {
|
||||
auto *n16 = static_cast<Node16 *>(n);
|
||||
toFree.append(std::span<Node *>(n16->children, n16->numChildren));
|
||||
tls->release(n16);
|
||||
} break;
|
||||
case Type_Node48: {
|
||||
auto *n48 = static_cast<Node48 *>(n);
|
||||
toFree.append(std::span<Node *>(n48->children, n48->numChildren));
|
||||
tls->release(n48);
|
||||
} break;
|
||||
case Type_Node256: {
|
||||
auto *n256 = static_cast<Node256 *>(n);
|
||||
auto *out = toFree.unsafePrepareAppend(n256->numChildren).data();
|
||||
n256->bitSet.forEachSet([&](int i) { *out++ = n256->children[i]; });
|
||||
assert(out == toFree.end());
|
||||
tls->release(n256);
|
||||
} break;
|
||||
default: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void eraseBetween(Node **inTree, Node3 *n, int begin, int end,
|
||||
WriteContext *tls) {
|
||||
const unsigned shiftUpperBound = end - begin;
|
||||
const unsigned shiftAmount = begin;
|
||||
auto inBounds = [&](unsigned c) { return c - shiftAmount < shiftUpperBound; };
|
||||
Node **nodeOut = n->children;
|
||||
uint8_t *indexOut = n->index;
|
||||
InternalVersionT *maxVOut = n->childMaxVersion;
|
||||
for (int i = 0; i < n->numChildren; ++i) {
|
||||
if (inBounds(n->index[i])) {
|
||||
eraseTree(n->children[i], tls);
|
||||
} else {
|
||||
*nodeOut++ = n->children[i];
|
||||
*indexOut++ = n->index[i];
|
||||
*maxVOut++ = n->childMaxVersion[i];
|
||||
}
|
||||
}
|
||||
n->numChildren = nodeOut - n->children;
|
||||
|
||||
if (n->numChildren == 0) {
|
||||
auto *newNode = tls->allocate<Node0>(n->partialKeyLen);
|
||||
newNode->copyChildrenAndKeyFrom(*n);
|
||||
tls->release(n);
|
||||
*inTree = newNode;
|
||||
}
|
||||
}
|
||||
|
||||
void eraseBetween(Node **inTree, Node16 *n, int begin, int end,
|
||||
WriteContext *tls) {
|
||||
if (end - begin == 256) {
|
||||
for (int i = 0; i < n->numChildren; ++i) {
|
||||
eraseTree(n->children[i], tls);
|
||||
}
|
||||
n->numChildren = 0;
|
||||
auto *newNode = tls->allocate<Node0>(n->partialKeyLen);
|
||||
newNode->copyChildrenAndKeyFrom(*n);
|
||||
tls->release(n);
|
||||
*inTree = newNode;
|
||||
return;
|
||||
}
|
||||
assert(end - begin < 256);
|
||||
|
||||
#ifdef HAS_ARM_NEON
|
||||
uint8x16_t indices;
|
||||
memcpy(&indices, n->index, 16);
|
||||
// 0xff for each in bounds
|
||||
auto results =
|
||||
vcltq_u8(vsubq_u8(indices, vdupq_n_u8(begin)), vdupq_n_u8(end - begin));
|
||||
// 0xf for each 0xff
|
||||
uint64_t mask = vget_lane_u64(
|
||||
vreinterpret_u64_u8(vshrn_n_u16(vreinterpretq_u16_u8(results), 4)), 0);
|
||||
#elif defined(HAS_AVX)
|
||||
__m128i indices;
|
||||
memcpy(&indices, n->index, 16);
|
||||
indices = _mm_sub_epi8(indices, _mm_set1_epi8(begin));
|
||||
uint32_t mask = ~_mm_movemask_epi8(_mm_cmpeq_epi8(
|
||||
indices, _mm_max_epu8(indices, _mm_set1_epi8(end - begin))));
|
||||
#else
|
||||
const unsigned shiftUpperBound = end - begin;
|
||||
const unsigned shiftAmount = begin;
|
||||
auto inBounds = [&](unsigned c) { return c - shiftAmount < shiftUpperBound; };
|
||||
uint32_t mask = 0;
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
mask |= inBounds(is[i]) << i;
|
||||
}
|
||||
#endif
|
||||
mask &= (decltype(mask)(1) << n->numChildren) - 1;
|
||||
|
||||
if (!mask) {
|
||||
return;
|
||||
}
|
||||
|
||||
int first = std::countr_zero(mask);
|
||||
int count = std::popcount(mask);
|
||||
n->numChildren -= count;
|
||||
for (int i = first; i < first + count; ++i) {
|
||||
eraseTree(n->children[i], tls);
|
||||
}
|
||||
for (int i = first; i < n->numChildren; ++i) {
|
||||
n->children[i] = n->children[i + count];
|
||||
n->childMaxVersion[i] = n->childMaxVersion[i + count];
|
||||
n->index[i] = n->index[i + count];
|
||||
}
|
||||
|
||||
if (n->numChildren + n->entryPresent >= kMinChildrenNode16) {
|
||||
// nop
|
||||
} else if (n->numChildren > 0) {
|
||||
auto *newNode = tls->allocate<Node3>(n->partialKeyLen);
|
||||
newNode->copyChildrenAndKeyFrom(*n);
|
||||
tls->release(n);
|
||||
*inTree = newNode;
|
||||
} else {
|
||||
auto *newNode = tls->allocate<Node0>(n->partialKeyLen);
|
||||
newNode->copyChildrenAndKeyFrom(*n);
|
||||
tls->release(n);
|
||||
*inTree = newNode;
|
||||
}
|
||||
}
|
||||
|
||||
void eraseBetween(Node **inTree, Node48 *n, int begin, int end,
|
||||
WriteContext *tls) {
|
||||
for (int i = n->bitSet.firstSetGeq(begin); i >= 0 && i < end;
|
||||
i = n->bitSet.firstSetGeq(i)) {
|
||||
n->bitSet.reset(i);
|
||||
int8_t toRemoveChildrenIndex = std::exchange(n->index[i], -1);
|
||||
int8_t lastChildrenIndex = --n->nextFree;
|
||||
assert(toRemoveChildrenIndex >= 0);
|
||||
assert(lastChildrenIndex >= 0);
|
||||
eraseTree(n->children[toRemoveChildrenIndex], tls);
|
||||
if (toRemoveChildrenIndex != lastChildrenIndex) {
|
||||
n->children[toRemoveChildrenIndex] = n->children[lastChildrenIndex];
|
||||
n->childMaxVersion[toRemoveChildrenIndex] =
|
||||
n->childMaxVersion[lastChildrenIndex];
|
||||
n->maxOfMax[toRemoveChildrenIndex >> Node48::kMaxOfMaxShift] =
|
||||
std::max(n->maxOfMax[toRemoveChildrenIndex >> Node48::kMaxOfMaxShift],
|
||||
n->childMaxVersion[toRemoveChildrenIndex]);
|
||||
auto parentIndex = n->children[toRemoveChildrenIndex]->parentsIndex;
|
||||
n->index[parentIndex] = toRemoveChildrenIndex;
|
||||
n->reverseIndex[toRemoveChildrenIndex] = parentIndex;
|
||||
}
|
||||
n->childMaxVersion[lastChildrenIndex] = tls->zero;
|
||||
--n->numChildren;
|
||||
}
|
||||
|
||||
if (n->numChildren + n->entryPresent >= kMinChildrenNode48) {
|
||||
// nop
|
||||
} else if (n->numChildren > Node3::kMaxNodes) {
|
||||
auto *newNode = tls->allocate<Node16>(n->partialKeyLen);
|
||||
newNode->copyChildrenAndKeyFrom(*n);
|
||||
tls->release(n);
|
||||
*inTree = newNode;
|
||||
} else if (n->numChildren > 0) {
|
||||
auto *newNode = tls->allocate<Node3>(n->partialKeyLen);
|
||||
newNode->copyChildrenAndKeyFrom(*n);
|
||||
tls->release(n);
|
||||
*inTree = newNode;
|
||||
} else {
|
||||
auto *newNode = tls->allocate<Node0>(n->partialKeyLen);
|
||||
newNode->copyChildrenAndKeyFrom(*n);
|
||||
tls->release(n);
|
||||
*inTree = newNode;
|
||||
}
|
||||
}
|
||||
|
||||
void eraseBetween(Node **inTree, Node256 *n, int begin, int end,
|
||||
WriteContext *tls) {
|
||||
for (int i = n->bitSet.firstSetGeq(begin); i >= 0 && i < end;
|
||||
i = n->bitSet.firstSetGeq(i)) {
|
||||
assert(n->children[i] != nullptr);
|
||||
eraseTree(std::exchange(n->children[i], nullptr), tls);
|
||||
n->bitSet.reset(i);
|
||||
--n->numChildren;
|
||||
}
|
||||
if (n->numChildren + n->entryPresent >= kMinChildrenNode256) {
|
||||
// nop
|
||||
} else if (n->numChildren > Node16::kMaxNodes) {
|
||||
auto *newNode = tls->allocate<Node48>(n->partialKeyLen);
|
||||
newNode->copyChildrenAndKeyFrom(*n);
|
||||
tls->release(n);
|
||||
*inTree = newNode;
|
||||
} else if (n->numChildren > Node3::kMaxNodes) {
|
||||
auto *newNode = tls->allocate<Node16>(n->partialKeyLen);
|
||||
newNode->copyChildrenAndKeyFrom(*n);
|
||||
tls->release(n);
|
||||
*inTree = newNode;
|
||||
} else if (n->numChildren > 0) {
|
||||
auto *newNode = tls->allocate<Node3>(n->partialKeyLen);
|
||||
newNode->copyChildrenAndKeyFrom(*n);
|
||||
tls->release(n);
|
||||
*inTree = newNode;
|
||||
} else {
|
||||
auto *newNode = tls->allocate<Node0>(n->partialKeyLen);
|
||||
newNode->copyChildrenAndKeyFrom(*n);
|
||||
tls->release(n);
|
||||
*inTree = newNode;
|
||||
}
|
||||
}
|
||||
|
||||
// Erase all nodes with a search path starting with n + [child],
|
||||
// where child in [begin, end). To avoid the need to propagate erases up the
|
||||
// search path, the caller must ensure that the result has at least one child or
|
||||
// has entryPresent.
|
||||
void eraseBetween(Node *&n, int begin, int end, WriteContext *tls) {
|
||||
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
||||
fprintf(stderr, "eraseBetween: %s + [%d,%d)\n",
|
||||
getSearchPathPrintable(n).c_str(), begin, end);
|
||||
#endif
|
||||
switch (n->getType()) {
|
||||
case Type_Node0:
|
||||
break;
|
||||
case Type_Node3:
|
||||
eraseBetween(&n, (Node3 *)n, begin, end, tls);
|
||||
break;
|
||||
case Type_Node16:
|
||||
eraseBetween(&n, (Node16 *)n, begin, end, tls);
|
||||
break;
|
||||
case Type_Node48:
|
||||
eraseBetween(&n, (Node48 *)n, begin, end, tls);
|
||||
break;
|
||||
case Type_Node256:
|
||||
eraseBetween(&n, (Node256 *)n, begin, end, tls);
|
||||
break;
|
||||
default: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
}
|
||||
assert(n->numChildren > 0 || n->entryPresent);
|
||||
}
|
||||
|
||||
// Precondition: self is not the root. May invalidate nodes along the search
|
||||
// path to self. May invalidate children of self->parent. Returns a pointer to
|
||||
// the node after self. If erase invalidates the pointee of `dontInvalidate`, it
|
||||
// will update it to its new pointee as well. Precondition: `self->entryPresent`
|
||||
// the node after self. If erase invalidates the pointee of `dontInvalidate`,
|
||||
// it will update it to its new pointee as well. Precondition:
|
||||
// `self->entryPresent`
|
||||
Node *erase(Node *self, WriteContext *tls, ConflictSet::Impl *impl,
|
||||
bool logical, Node *&dontInvalidate) {
|
||||
++tls->accum.entries_erased;
|
||||
@@ -1892,8 +2211,8 @@ bool checkPrefixRead(Node *n, const std::span<const uint8_t> key,
|
||||
remaining = remaining.subspan(commonLen, remaining.size() - commonLen);
|
||||
} else if (n->partialKeyLen > int(remaining.size())) {
|
||||
// n is the first physical node greater than remaining, and there's no
|
||||
// eq node. All physical nodes that start with prefix are reachable from
|
||||
// n.
|
||||
// eq node. All physical nodes that start with prefix are reachable
|
||||
// from n.
|
||||
if (maxVersion(n, impl) > readVersion) {
|
||||
return false;
|
||||
}
|
||||
@@ -1942,8 +2261,8 @@ compare16_32bit_avx512(const InternalVersionT *vs, InternalVersionT rv) {
|
||||
#endif
|
||||
// GCOVR_EXCL_STOP
|
||||
|
||||
// Returns true if v[i] <= readVersion for all i such that begin <= is[i] < end
|
||||
// Preconditions: begin <= end, end - begin < 256
|
||||
// Returns true if v[i] <= readVersion for all i such that begin <= is[i] <
|
||||
// end Preconditions: begin <= end, end - begin < 256
|
||||
template <bool kAVX512>
|
||||
bool scan16(const InternalVersionT *vs, const uint8_t *is, int begin, int end,
|
||||
InternalVersionT readVersion) {
|
||||
@@ -2074,9 +2393,10 @@ bool scan16(const InternalVersionT *vs, int begin, int end,
|
||||
#endif
|
||||
}
|
||||
|
||||
// Return whether or not the max version among all keys starting with the search
|
||||
// path of n + [child], where child in (begin, end) is <= readVersion. Does not
|
||||
// account for the range version of firstGt(searchpath(n) + [end - 1])
|
||||
// Return whether or not the max version among all keys starting with the
|
||||
// search path of n + [child], where child in (begin, end) is <= readVersion.
|
||||
// Does not account for the range version of firstGt(searchpath(n) + [end -
|
||||
// 1])
|
||||
template <bool kAVX512>
|
||||
bool checkMaxBetweenExclusiveImpl(Node *n, int begin, int end,
|
||||
InternalVersionT readVersion,
|
||||
@@ -2245,8 +2565,8 @@ bool checkMaxBetweenExclusiveImpl(Node *n, int begin, int end,
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
// [begin, end) is now the half-open interval of children we're interested
|
||||
// in.
|
||||
// [begin, end) is now the half-open interval of children we're
|
||||
// interested in.
|
||||
assert(begin < end);
|
||||
}
|
||||
|
||||
@@ -2281,8 +2601,8 @@ bool checkMaxBetweenExclusiveImpl(Node *n, int begin, int end,
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
// [begin, end) is now the half-open interval of children we're interested
|
||||
// in.
|
||||
// [begin, end) is now the half-open interval of children we're
|
||||
// interested in.
|
||||
assert(begin < end);
|
||||
}
|
||||
|
||||
@@ -2339,8 +2659,9 @@ checkMaxBetweenExclusive(Node *n, int begin, int end,
|
||||
// GCOVR_EXCL_STOP
|
||||
__attribute__((target("default")))
|
||||
#endif
|
||||
bool checkMaxBetweenExclusive(Node *n, int begin, int end,
|
||||
InternalVersionT readVersion, ReadContext *tls) {
|
||||
bool
|
||||
checkMaxBetweenExclusive(Node * n, int begin, int end,
|
||||
InternalVersionT readVersion, ReadContext *tls) {
|
||||
return checkMaxBetweenExclusiveImpl<false>(n, begin, end, readVersion, tls);
|
||||
}
|
||||
|
||||
@@ -2361,8 +2682,8 @@ Vector<uint8_t> getSearchPath(Arena &arena, Node *n) {
|
||||
return result;
|
||||
} // GCOVR_EXCL_LINE
|
||||
|
||||
// Return true if the max version among all keys that start with key + [child],
|
||||
// where begin < child < end, is <= readVersion.
|
||||
// Return true if the max version among all keys that start with key +
|
||||
// [child], where begin < child < end, is <= readVersion.
|
||||
//
|
||||
// Precondition: transitively, no child of n has a search path that's a longer
|
||||
// prefix of key than n
|
||||
@@ -2432,8 +2753,8 @@ downLeftSpine:
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Return true if the max version among all keys that start with key[:prefixLen]
|
||||
// that are >= key is <= readVersion
|
||||
// Return true if the max version among all keys that start with
|
||||
// key[:prefixLen] that are >= key is <= readVersion
|
||||
struct CheckRangeLeftSide {
|
||||
CheckRangeLeftSide(Node *n, std::span<const uint8_t> key, int prefixLen,
|
||||
InternalVersionT readVersion, ReadContext *tls)
|
||||
@@ -2547,8 +2868,8 @@ struct CheckRangeLeftSide {
|
||||
}
|
||||
};
|
||||
|
||||
// Return true if the max version among all keys that start with key[:prefixLen]
|
||||
// that are < key is <= readVersion
|
||||
// Return true if the max version among all keys that start with
|
||||
// key[:prefixLen] that are < key is <= readVersion
|
||||
struct CheckRangeRightSide {
|
||||
CheckRangeRightSide(Node *n, std::span<const uint8_t> key, int prefixLen,
|
||||
InternalVersionT readVersion, ReadContext *tls)
|
||||
@@ -2794,9 +3115,9 @@ checkMaxBetweenExclusiveImpl<true>(Node *n, int begin, int end,
|
||||
InternalVersionT readVersion, ReadContext *);
|
||||
#endif
|
||||
|
||||
// Returns a pointer the pointer to the newly inserted node in the tree. Caller
|
||||
// must set `entryPresent`, and `entry` fields. All nodes along the search path
|
||||
// of the result will have `maxVersion` set to `writeVersion` as a
|
||||
// Returns a pointer the pointer to the newly inserted node in the tree.
|
||||
// Caller must set `entryPresent`, and `entry` fields. All nodes along the
|
||||
// search path of the result will have `maxVersion` set to `writeVersion` as a
|
||||
// postcondition. Nodes along the search path may be invalidated.
|
||||
[[nodiscard]]
|
||||
Node **insert(Node **self, std::span<const uint8_t> key,
|
||||
@@ -2812,31 +3133,6 @@ Node **insert(Node **self, std::span<const uint8_t> key,
|
||||
return self;
|
||||
}
|
||||
|
||||
void destroyTree(Node *root) {
|
||||
Arena arena;
|
||||
auto toFree = vector<Node *>(arena);
|
||||
toFree.push_back(root);
|
||||
|
||||
#if SHOW_MEMORY
|
||||
for (auto *iter = root; iter != nullptr; iter = nextPhysical(iter)) {
|
||||
removeNode(iter);
|
||||
removeKey(iter);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (toFree.size() > 0) {
|
||||
auto *n = toFree.back();
|
||||
toFree.pop_back();
|
||||
// Add all children to toFree
|
||||
for (auto c = getChildGeq(n, 0); c != nullptr;
|
||||
c = getChildGeq(n, c->parentsIndex + 1)) {
|
||||
assert(c != nullptr);
|
||||
toFree.push_back(c);
|
||||
}
|
||||
safe_free(n, n->size());
|
||||
}
|
||||
}
|
||||
|
||||
void addPointWrite(Node *&root, std::span<const uint8_t> key,
|
||||
InternalVersionT writeVersion, WriteContext *tls,
|
||||
ConflictSet::Impl *impl) {
|
||||
@@ -2911,55 +3207,93 @@ void addWriteRange(Node *&root, std::span<const uint8_t> begin,
|
||||
|
||||
Node **useAsRoot =
|
||||
insert(&root, begin.subspan(0, lcp), writeVersion, tls, impl);
|
||||
begin = begin.subspan(lcp, begin.size() - lcp);
|
||||
end = end.subspan(lcp, end.size() - lcp);
|
||||
|
||||
int consumed = lcp;
|
||||
|
||||
begin = begin.subspan(consumed, begin.size() - consumed);
|
||||
end = end.subspan(consumed, end.size() - consumed);
|
||||
|
||||
auto *beginNode = *insert(useAsRoot, begin, writeVersion, tls, impl);
|
||||
|
||||
const bool insertedBegin = !beginNode->entryPresent;
|
||||
|
||||
addKey(beginNode);
|
||||
beginNode->entryPresent = true;
|
||||
|
||||
if (insertedBegin) {
|
||||
++tls->accum.entries_inserted;
|
||||
auto *p = nextLogical(beginNode);
|
||||
beginNode->entry.rangeVersion =
|
||||
p == nullptr ? tls->zero : std::max(p->entry.rangeVersion, tls->zero);
|
||||
if (beginIsPrefix) {
|
||||
auto *beginNode = *useAsRoot;
|
||||
addKey(beginNode);
|
||||
if (!beginNode->entryPresent) {
|
||||
++tls->accum.entries_inserted;
|
||||
auto *p = nextLogical(beginNode);
|
||||
beginNode->entry.rangeVersion =
|
||||
p == nullptr ? tls->zero : std::max(p->entry.rangeVersion, tls->zero);
|
||||
beginNode->entryPresent = true;
|
||||
}
|
||||
beginNode->entry.pointVersion = writeVersion;
|
||||
}
|
||||
assert(writeVersion >= beginNode->entry.pointVersion);
|
||||
beginNode->entry.pointVersion = writeVersion;
|
||||
|
||||
auto *endNode = *insert(useAsRoot, end, writeVersion, tls, impl);
|
||||
|
||||
const bool insertedEnd = !endNode->entryPresent;
|
||||
|
||||
addKey(endNode);
|
||||
endNode->entryPresent = true;
|
||||
|
||||
if (insertedEnd) {
|
||||
++tls->accum.entries_inserted;
|
||||
auto *p = nextLogical(endNode);
|
||||
endNode->entry.pointVersion =
|
||||
p == nullptr ? tls->zero : std::max(p->entry.rangeVersion, tls->zero);
|
||||
if (beginIsPrefix) {
|
||||
auto *endNode = *insert(useAsRoot, end, writeVersion, tls, impl);
|
||||
addKey(endNode);
|
||||
if (!endNode->entryPresent) {
|
||||
++tls->accum.entries_inserted;
|
||||
auto *p = nextLogical(endNode);
|
||||
endNode->entry.pointVersion =
|
||||
p == nullptr ? tls->zero : std::max(p->entry.rangeVersion, tls->zero);
|
||||
// beginNode may have been invalidated when inserting end
|
||||
beginNode = *useAsRoot;
|
||||
assert(beginNode->entryPresent);
|
||||
endNode->entryPresent = true;
|
||||
}
|
||||
}
|
||||
endNode->entry.rangeVersion = writeVersion;
|
||||
endNode->entry.rangeVersion = writeVersion;
|
||||
|
||||
for (beginNode = nextLogical(beginNode); beginNode != endNode;
|
||||
beginNode = erase(beginNode, tls, impl, /*logical*/ true, endNode)) {
|
||||
}
|
||||
for (beginNode = nextLogical(beginNode); beginNode != endNode;
|
||||
beginNode = erase(beginNode, tls, impl, /*logical*/ true, endNode)) {
|
||||
}
|
||||
|
||||
// Inserting end trashed endNode's maxVersion. Fix that
|
||||
fixupMaxVersion(endNode, impl, tls);
|
||||
// Inserting end trashed endNode's maxVersion. Fix that
|
||||
fixupMaxVersion(endNode, impl, tls);
|
||||
} else /*!beginIsPrefix*/ {
|
||||
auto *beginNode = *insert(useAsRoot, begin, writeVersion, tls, impl);
|
||||
addKey(beginNode);
|
||||
if (!beginNode->entryPresent) {
|
||||
++tls->accum.entries_inserted;
|
||||
auto *p = nextLogical(beginNode);
|
||||
beginNode->entry.rangeVersion =
|
||||
p == nullptr ? tls->zero : std::max(p->entry.rangeVersion, tls->zero);
|
||||
beginNode->entryPresent = true;
|
||||
}
|
||||
beginNode->entry.pointVersion = writeVersion;
|
||||
|
||||
auto *endNode = *insert(useAsRoot, end, writeVersion, tls, impl);
|
||||
addKey(endNode);
|
||||
if (!endNode->entryPresent) {
|
||||
++tls->accum.entries_inserted;
|
||||
auto *p = nextLogical(endNode);
|
||||
endNode->entry.pointVersion =
|
||||
p == nullptr ? tls->zero : std::max(p->entry.rangeVersion, tls->zero);
|
||||
endNode->entryPresent = true;
|
||||
}
|
||||
endNode->entry.rangeVersion = writeVersion;
|
||||
|
||||
eraseBetween(*useAsRoot, begin[0] + 1, end[0], tls);
|
||||
|
||||
// // Erase along left spine
|
||||
// for (auto [n, key] = std::make_tuple(useAsRoot, begin);;) {
|
||||
// auto before = key;
|
||||
// auto **child = &getOrCreateChild(*n, key, writeVersion, tls);
|
||||
// if (key.size() > 0) {
|
||||
// eraseBetween(*child, int(key[0]) + 1, 256, tls);
|
||||
// if ((*child)->numChildren == 1 && !(*child)->entryPresent) {
|
||||
// Node *dummy = nullptr;
|
||||
// mergeWithChild(*child, tls, impl, dummy,
|
||||
// static_cast<Node3 *>(*child));
|
||||
// key = before;
|
||||
// continue;
|
||||
// }
|
||||
// } else {
|
||||
// eraseBetween(*child, 0, 256, tls);
|
||||
// beginNode = *child;
|
||||
// break;
|
||||
// }
|
||||
// n = child;
|
||||
// }
|
||||
|
||||
for (beginNode = nextLogical(beginNode); beginNode != endNode;
|
||||
beginNode = erase(beginNode, tls, impl, /*logical*/ true, endNode)) {
|
||||
}
|
||||
|
||||
// Inserting end trashed endNode's maxVersion. Fix that
|
||||
fixupMaxVersion(endNode, impl, tls);
|
||||
}
|
||||
}
|
||||
|
||||
Node *firstGeqPhysical(Node *n, const std::span<const uint8_t> key) {
|
||||
@@ -3070,7 +3404,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||
if (oldestExtantVersion < writeVersion - kMaxCorrectVersionWindow)
|
||||
[[unlikely]] {
|
||||
if (writeVersion > newestVersionFullPrecision + kNominalVersionWindow) {
|
||||
destroyTree(root);
|
||||
eraseTree(root, &tls);
|
||||
init(writeVersion - kNominalVersionWindow);
|
||||
}
|
||||
|
||||
@@ -3133,17 +3467,17 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||
int64_t set_oldest_iterations_accum = 0;
|
||||
for (; fuel > 0 && n != nullptr; ++set_oldest_iterations_accum) {
|
||||
rezero(n, oldestVersion);
|
||||
// The "make sure gc keeps up with writes" calculations assume that we're
|
||||
// scanning key by key, not node by node. Make sure we only spend fuel
|
||||
// when there's a logical entry.
|
||||
// The "make sure gc keeps up with writes" calculations assume that
|
||||
// we're scanning key by key, not node by node. Make sure we only spend
|
||||
// fuel when there's a logical entry.
|
||||
fuel -= n->entryPresent;
|
||||
if (n->entryPresent && std::max(n->entry.pointVersion,
|
||||
n->entry.rangeVersion) <= oldestVersion) {
|
||||
// Any transaction n would have prevented from committing is
|
||||
// going to fail with TooOld anyway.
|
||||
|
||||
// There's no way to insert a range such that range version of the right
|
||||
// node is greater than the point version of the left node
|
||||
// There's no way to insert a range such that range version of the
|
||||
// right node is greater than the point version of the left node
|
||||
assert(n->entry.rangeVersion <= oldestVersion);
|
||||
Node *dummy = nullptr;
|
||||
n = erase(n, &tls, this, /*logical*/ false, dummy);
|
||||
@@ -3180,9 +3514,9 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||
this->oldestVersion = oldestVersion;
|
||||
InternalVersionT::zero = tls.zero = oldestVersion;
|
||||
#ifdef NDEBUG
|
||||
// This is here for performance reasons, since we want to amortize the cost
|
||||
// of storing the search path as a string. In tests, we want to exercise the
|
||||
// rest of the code often.
|
||||
// This is here for performance reasons, since we want to amortize the
|
||||
// cost of storing the search path as a string. In tests, we want to
|
||||
// exercise the rest of the code often.
|
||||
if (keyUpdates < 100) {
|
||||
return;
|
||||
}
|
||||
@@ -3238,7 +3572,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||
initMetrics();
|
||||
}
|
||||
~Impl() {
|
||||
destroyTree(root);
|
||||
eraseTree(root, &tls);
|
||||
safe_free(metrics, metricsCount * sizeof(metrics[0]));
|
||||
}
|
||||
|
||||
@@ -3306,8 +3640,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||
"Total number of checks where the result is \"too old\"");
|
||||
COUNTER(check_bytes_total, "Total number of key bytes checked");
|
||||
COUNTER(point_writes_total, "Total number of point writes");
|
||||
COUNTER(range_writes_total,
|
||||
"Total number of range writes (includes prefix writes)");
|
||||
COUNTER(range_writes_total, "Total number of range writes");
|
||||
GAUGE(memory_bytes, "Total number of bytes in use");
|
||||
COUNTER(nodes_allocated_total,
|
||||
"The total number of physical tree nodes allocated");
|
||||
@@ -3321,16 +3654,14 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||
"The total number of entries inserted in the tree");
|
||||
COUNTER(entries_erased_total,
|
||||
"The total number of entries erased from the tree");
|
||||
COUNTER(
|
||||
gc_iterations_total,
|
||||
"The total number of iterations of the main loop for garbage collection");
|
||||
COUNTER(gc_iterations_total, "The total number of iterations of the main "
|
||||
"loop for garbage collection");
|
||||
COUNTER(write_bytes_total, "Total number of key bytes in calls to addWrites");
|
||||
GAUGE(oldest_version,
|
||||
"The lowest version that doesn't result in \"TooOld\" for checks");
|
||||
GAUGE(newest_version, "The version of the most recent call to addWrites");
|
||||
GAUGE(
|
||||
oldest_extant_version,
|
||||
"A lower bound on the lowest version associated with an existing entry");
|
||||
GAUGE(oldest_extant_version, "A lower bound on the lowest version "
|
||||
"associated with an existing entry");
|
||||
// ==================== END METRICS DEFINITIONS ====================
|
||||
#undef GAUGE
|
||||
#undef COUNTER
|
||||
@@ -3416,6 +3747,7 @@ InternalVersionT exchangeMaxVersion(Node *n, InternalVersionT newMax) {
|
||||
}
|
||||
|
||||
void setMaxVersion(Node *n, ConflictSet::Impl *impl, InternalVersionT newMax) {
|
||||
assert(newMax >= InternalVersionT::zero);
|
||||
int index = n->parentsIndex;
|
||||
n = n->parent;
|
||||
if (n == nullptr) {
|
||||
@@ -3705,8 +4037,8 @@ std::string strinc(std::string_view str, bool &ok) {
|
||||
if ((uint8_t &)(str[index]) != 255)
|
||||
break;
|
||||
|
||||
// Must not be called with a string that consists only of zero or more '\xff'
|
||||
// bytes.
|
||||
// Must not be called with a string that consists only of zero or more
|
||||
// '\xff' bytes.
|
||||
if (index < 0) {
|
||||
ok = false;
|
||||
return {};
|
||||
@@ -3926,7 +4258,7 @@ checkMaxVersion(Node *root, Node *node, InternalVersionT oldestVersion,
|
||||
bool success = true;
|
||||
|
||||
if (node->partialKeyLen > 0) {
|
||||
fprintf(stderr, "Root cannot have a partial key");
|
||||
fprintf(stderr, "Root cannot have a partial key\n");
|
||||
success = false;
|
||||
}
|
||||
checkParentPointers(node, success);
|
||||
|
10
Internal.h
10
Internal.h
@@ -273,6 +273,16 @@ template <class T> struct Vector {
|
||||
size_ += slice.size();
|
||||
}
|
||||
|
||||
// Caller must write to the returned slice
|
||||
std::span<T> unsafePrepareAppend(int appendSize) {
|
||||
if (size_ + appendSize > capacity) {
|
||||
grow(std::max<int>(size_ + appendSize, capacity * 2));
|
||||
}
|
||||
auto result = std::span<T>(t + size_, appendSize);
|
||||
size_ += appendSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
void push_back(const T &t) { append(std::span<const T>(&t, 1)); }
|
||||
|
||||
T *begin() { return t; }
|
||||
|
@@ -164,6 +164,63 @@ double toSeconds(timeval t) {
|
||||
return double(t.tv_sec) + double(t.tv_usec) * 1e-6;
|
||||
}
|
||||
|
||||
#include <linux/perf_event.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __linux__
|
||||
struct PerfCounter {
|
||||
explicit PerfCounter(int event) {
|
||||
struct perf_event_attr pe;
|
||||
|
||||
memset(&pe, 0, sizeof(pe));
|
||||
pe.type = PERF_TYPE_HARDWARE;
|
||||
pe.size = sizeof(pe);
|
||||
pe.config = event;
|
||||
pe.inherit = 1;
|
||||
pe.exclude_kernel = 1;
|
||||
pe.exclude_hv = 1;
|
||||
|
||||
fd = perf_event_open(&pe, 0, -1, -1, 0);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Error opening leader %llx\n", pe.config);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
int64_t total() {
|
||||
int64_t count;
|
||||
if (read(fd, &count, sizeof(count)) != sizeof(count)) {
|
||||
perror("read instructions from perf");
|
||||
abort();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
~PerfCounter() { close(fd); }
|
||||
|
||||
private:
|
||||
int fd;
|
||||
static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
|
||||
int cpu, int group_fd, unsigned long flags) {
|
||||
int ret;
|
||||
|
||||
ret = syscall(SYS_perf_event_open, hw_event, pid, cpu, group_fd, flags);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
#else
|
||||
struct PerfCounter {
|
||||
explicit PerPerfCounter(int) {}
|
||||
int64_t total() { return 0; }
|
||||
};
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 3) {
|
||||
goto fail;
|
||||
@@ -176,6 +233,8 @@ int main(int argc, char **argv) {
|
||||
int metricsCount;
|
||||
cs.getMetricsV1(&metrics, &metricsCount);
|
||||
|
||||
PerfCounter instructions{PERF_COUNT_HW_INSTRUCTIONS};
|
||||
PerfCounter cycles{PERF_COUNT_HW_CPU_CYCLES};
|
||||
auto w = std::thread{workload, &cs};
|
||||
|
||||
for (;;) {
|
||||
@@ -203,6 +262,16 @@ int main(int argc, char **argv) {
|
||||
"transactions_total ";
|
||||
body += std::to_string(transactions.load(std::memory_order_relaxed));
|
||||
body += "\n";
|
||||
body += "# HELP instructions_total Total number of instructions\n"
|
||||
"# TYPE instructions_total counter\n"
|
||||
"instructions_total ";
|
||||
body += std::to_string(instructions.total());
|
||||
body += "\n";
|
||||
body += "# HELP cycles_total Total number of cycles\n"
|
||||
"# TYPE cycles_total counter\n"
|
||||
"cycles_total ";
|
||||
body += std::to_string(cycles.total());
|
||||
body += "\n";
|
||||
|
||||
for (int i = 0; i < metricsCount; ++i) {
|
||||
body += "# HELP ";
|
||||
|
BIN
corpus/00109d195ce4e826feb08448d822f7ad925fa763
Normal file
BIN
corpus/00109d195ce4e826feb08448d822f7ad925fa763
Normal file
Binary file not shown.
BIN
corpus/0369048a3408822fdfb7e4250a850e263481544b
Normal file
BIN
corpus/0369048a3408822fdfb7e4250a850e263481544b
Normal file
Binary file not shown.
BIN
corpus/04d8a5799db6740450a758d973610b39719493dd
Normal file
BIN
corpus/04d8a5799db6740450a758d973610b39719493dd
Normal file
Binary file not shown.
BIN
corpus/0510903db2331a8ac8de00768131b184d5871e64
Normal file
BIN
corpus/0510903db2331a8ac8de00768131b184d5871e64
Normal file
Binary file not shown.
BIN
corpus/0594eed24298634b028ccafaf284afb5a6acf940
Normal file
BIN
corpus/0594eed24298634b028ccafaf284afb5a6acf940
Normal file
Binary file not shown.
BIN
corpus/084e4406b0be350bb06ea41a4fa08ee4edf2b3c5
Normal file
BIN
corpus/084e4406b0be350bb06ea41a4fa08ee4edf2b3c5
Normal file
Binary file not shown.
BIN
corpus/0d94e23cb04bdaa083df8c0eb9a37d56c1d72b08
Normal file
BIN
corpus/0d94e23cb04bdaa083df8c0eb9a37d56c1d72b08
Normal file
Binary file not shown.
BIN
corpus/0e03a31dd94cd404f9559ee3041937418a5d6e73
Normal file
BIN
corpus/0e03a31dd94cd404f9559ee3041937418a5d6e73
Normal file
Binary file not shown.
BIN
corpus/0e4d2f5bc16bb65322c976e1c40d8aa8ee83bef0
Normal file
BIN
corpus/0e4d2f5bc16bb65322c976e1c40d8aa8ee83bef0
Normal file
Binary file not shown.
BIN
corpus/0e5ef615ee3864cffe276899f998ef9de68d792d
Normal file
BIN
corpus/0e5ef615ee3864cffe276899f998ef9de68d792d
Normal file
Binary file not shown.
BIN
corpus/1276c544ff45483d27ba32242fff1f4db3cfda3f
Normal file
BIN
corpus/1276c544ff45483d27ba32242fff1f4db3cfda3f
Normal file
Binary file not shown.
BIN
corpus/14675a1f433ad02a993ee402c562f19b39a69896
Normal file
BIN
corpus/14675a1f433ad02a993ee402c562f19b39a69896
Normal file
Binary file not shown.
BIN
corpus/15ef9579e5fa538b38b74e134c86bbfce4eea462
Normal file
BIN
corpus/15ef9579e5fa538b38b74e134c86bbfce4eea462
Normal file
Binary file not shown.
BIN
corpus/182793674308ba671193c5cdd9750e03a2889235
Normal file
BIN
corpus/182793674308ba671193c5cdd9750e03a2889235
Normal file
Binary file not shown.
BIN
corpus/1be0db1f3b34f05c856bb1f87337c1c5ad2c1051
Normal file
BIN
corpus/1be0db1f3b34f05c856bb1f87337c1c5ad2c1051
Normal file
Binary file not shown.
BIN
corpus/1e0cc87f3aeef1f66b1cf58007854fc5404e5700
Normal file
BIN
corpus/1e0cc87f3aeef1f66b1cf58007854fc5404e5700
Normal file
Binary file not shown.
BIN
corpus/1eb1dd4a29b56aae35a607593cf5c7a1b56868f3
Normal file
BIN
corpus/1eb1dd4a29b56aae35a607593cf5c7a1b56868f3
Normal file
Binary file not shown.
BIN
corpus/1ec9a7689eceb2a68b703619c6302147f258d088
Normal file
BIN
corpus/1ec9a7689eceb2a68b703619c6302147f258d088
Normal file
Binary file not shown.
BIN
corpus/1f4bd753e184a7e81d0c26b43ca18a3e8cfee86f
Normal file
BIN
corpus/1f4bd753e184a7e81d0c26b43ca18a3e8cfee86f
Normal file
Binary file not shown.
BIN
corpus/248bb4518929f33a266eae8e1d233958f7330198
Normal file
BIN
corpus/248bb4518929f33a266eae8e1d233958f7330198
Normal file
Binary file not shown.
BIN
corpus/29f42e23253dbbff5fce83cc09004704c6c18c1c
Normal file
BIN
corpus/29f42e23253dbbff5fce83cc09004704c6c18c1c
Normal file
Binary file not shown.
BIN
corpus/2db7bb596dfbaff4c7f68584f47ca49c6550b171
Normal file
BIN
corpus/2db7bb596dfbaff4c7f68584f47ca49c6550b171
Normal file
Binary file not shown.
BIN
corpus/2e1c8f40585dd31e6d1b0db564fc7a4c4983d7e3
Normal file
BIN
corpus/2e1c8f40585dd31e6d1b0db564fc7a4c4983d7e3
Normal file
Binary file not shown.
BIN
corpus/2e5f150272808fe332c6861fb1b3cad26827091a
Normal file
BIN
corpus/2e5f150272808fe332c6861fb1b3cad26827091a
Normal file
Binary file not shown.
BIN
corpus/2f01ecff62d1174bd3d29311a6c7ed830234feb1
Normal file
BIN
corpus/2f01ecff62d1174bd3d29311a6c7ed830234feb1
Normal file
Binary file not shown.
BIN
corpus/2f52518baf38b56e013170e88f40705c4c62fdf8
Normal file
BIN
corpus/2f52518baf38b56e013170e88f40705c4c62fdf8
Normal file
Binary file not shown.
BIN
corpus/2f55cc9c0979af56b253b41b572477170d233450
Normal file
BIN
corpus/2f55cc9c0979af56b253b41b572477170d233450
Normal file
Binary file not shown.
BIN
corpus/3020790285b3a34ef756d982502594517e6cc535
Normal file
BIN
corpus/3020790285b3a34ef756d982502594517e6cc535
Normal file
Binary file not shown.
BIN
corpus/324b414c0c0fe8aa042b6b3d38a8687a7d98bf3f
Normal file
BIN
corpus/324b414c0c0fe8aa042b6b3d38a8687a7d98bf3f
Normal file
Binary file not shown.
BIN
corpus/3380368f7a3b74bb98e8077e2e98d8f25a5f687a
Normal file
BIN
corpus/3380368f7a3b74bb98e8077e2e98d8f25a5f687a
Normal file
Binary file not shown.
BIN
corpus/377e85079bc11aa87600024852e9933b428fdbfa
Normal file
BIN
corpus/377e85079bc11aa87600024852e9933b428fdbfa
Normal file
Binary file not shown.
BIN
corpus/3aed9ae1320b244d4fccc5da70a788dc5a86c501
Normal file
BIN
corpus/3aed9ae1320b244d4fccc5da70a788dc5a86c501
Normal file
Binary file not shown.
BIN
corpus/3b1b54256c016f3ef2c5b82811937d1c1fa19a04
Normal file
BIN
corpus/3b1b54256c016f3ef2c5b82811937d1c1fa19a04
Normal file
Binary file not shown.
BIN
corpus/3d945fa5dedbbf67585f16917fbc6a49995ad658
Normal file
BIN
corpus/3d945fa5dedbbf67585f16917fbc6a49995ad658
Normal file
Binary file not shown.
BIN
corpus/3e32897a108d7df921659463f5ba301634bc278c
Normal file
BIN
corpus/3e32897a108d7df921659463f5ba301634bc278c
Normal file
Binary file not shown.
BIN
corpus/3f35e2bcd8857d807dd5c8e4a04f2dad19103efa
Normal file
BIN
corpus/3f35e2bcd8857d807dd5c8e4a04f2dad19103efa
Normal file
Binary file not shown.
BIN
corpus/3f6efe293f6347c0d960918e84a7adc5341d5295
Normal file
BIN
corpus/3f6efe293f6347c0d960918e84a7adc5341d5295
Normal file
Binary file not shown.
BIN
corpus/43b87330229d21961a7df933b2be9da65d71bcb1
Normal file
BIN
corpus/43b87330229d21961a7df933b2be9da65d71bcb1
Normal file
Binary file not shown.
BIN
corpus/44038657af1b2a3398a0c39bcab8f6e4b24d218d
Normal file
BIN
corpus/44038657af1b2a3398a0c39bcab8f6e4b24d218d
Normal file
Binary file not shown.
BIN
corpus/459d9bc23bfdabdf74fba5f5847e607e58dc4db8
Normal file
BIN
corpus/459d9bc23bfdabdf74fba5f5847e607e58dc4db8
Normal file
Binary file not shown.
BIN
corpus/45ec4091345676324b4bf22da4902e2ad688ea5c
Normal file
BIN
corpus/45ec4091345676324b4bf22da4902e2ad688ea5c
Normal file
Binary file not shown.
BIN
corpus/471d91e159052a7f3b84c92b5b9c8aa23e7eb11b
Normal file
BIN
corpus/471d91e159052a7f3b84c92b5b9c8aa23e7eb11b
Normal file
Binary file not shown.
BIN
corpus/483b083c153baea1a8ab33f45ba4e9e557e393c0
Normal file
BIN
corpus/483b083c153baea1a8ab33f45ba4e9e557e393c0
Normal file
Binary file not shown.
BIN
corpus/496e3f23a395a7d97a97cc85579cbc62c81b235a
Normal file
BIN
corpus/496e3f23a395a7d97a97cc85579cbc62c81b235a
Normal file
Binary file not shown.
BIN
corpus/4a5483ae597c5dd4fc5399e443bc3a37d74262d9
Normal file
BIN
corpus/4a5483ae597c5dd4fc5399e443bc3a37d74262d9
Normal file
Binary file not shown.
BIN
corpus/4afa69032fccc9656084fb3270741f2b54151ff7
Normal file
BIN
corpus/4afa69032fccc9656084fb3270741f2b54151ff7
Normal file
Binary file not shown.
BIN
corpus/4b63e6921e4eb916e1fbb54216fda91592a143b4
Normal file
BIN
corpus/4b63e6921e4eb916e1fbb54216fda91592a143b4
Normal file
Binary file not shown.
BIN
corpus/4bbac79eee1faff1411c3c647564f44b79ea4ac5
Normal file
BIN
corpus/4bbac79eee1faff1411c3c647564f44b79ea4ac5
Normal file
Binary file not shown.
BIN
corpus/4cf352b417f9dd32264537a55d47e0426ff160f7
Normal file
BIN
corpus/4cf352b417f9dd32264537a55d47e0426ff160f7
Normal file
Binary file not shown.
BIN
corpus/4d001fdceb7f2f8d1f3f3bf364cd80cbafdbc3d0
Normal file
BIN
corpus/4d001fdceb7f2f8d1f3f3bf364cd80cbafdbc3d0
Normal file
Binary file not shown.
BIN
corpus/4d1c5b691dbf5890d6a928472ffa7c81761915ac
Normal file
BIN
corpus/4d1c5b691dbf5890d6a928472ffa7c81761915ac
Normal file
Binary file not shown.
BIN
corpus/4f5e9ed1806b5af386b7e83b28f4899944077798
Normal file
BIN
corpus/4f5e9ed1806b5af386b7e83b28f4899944077798
Normal file
Binary file not shown.
BIN
corpus/54329c178f480fd5f6f022bb0d068ed1aeac0f4d
Normal file
BIN
corpus/54329c178f480fd5f6f022bb0d068ed1aeac0f4d
Normal file
Binary file not shown.
BIN
corpus/5565a49b50e3adfe26f4b8bdabb8125c6218eff8
Normal file
BIN
corpus/5565a49b50e3adfe26f4b8bdabb8125c6218eff8
Normal file
Binary file not shown.
BIN
corpus/57d44ba3f5975972af796d66724bfe06b32d1703
Normal file
BIN
corpus/57d44ba3f5975972af796d66724bfe06b32d1703
Normal file
Binary file not shown.
BIN
corpus/588e6d64afa6f2254eb5a4a783a5c9f422e7ab07
Normal file
BIN
corpus/588e6d64afa6f2254eb5a4a783a5c9f422e7ab07
Normal file
Binary file not shown.
BIN
corpus/5895d13e12f33e42e12242cefb847b6597de1125
Normal file
BIN
corpus/5895d13e12f33e42e12242cefb847b6597de1125
Normal file
Binary file not shown.
BIN
corpus/5929ccae6c6afd3c651ec714db33edbbe048aa24
Normal file
BIN
corpus/5929ccae6c6afd3c651ec714db33edbbe048aa24
Normal file
Binary file not shown.
BIN
corpus/5b72d1275fe41a0f4268db7118f7cbbd8dec5664
Normal file
BIN
corpus/5b72d1275fe41a0f4268db7118f7cbbd8dec5664
Normal file
Binary file not shown.
BIN
corpus/5d977fcf911a1af2fc35f1acd2917d04610fda27
Normal file
BIN
corpus/5d977fcf911a1af2fc35f1acd2917d04610fda27
Normal file
Binary file not shown.
BIN
corpus/5e6440b4f696be2724b24ce322332fde0526c47e
Normal file
BIN
corpus/5e6440b4f696be2724b24ce322332fde0526c47e
Normal file
Binary file not shown.
BIN
corpus/5f5396dfa0c2c980e1639ca5ed5acdb62426814a
Normal file
BIN
corpus/5f5396dfa0c2c980e1639ca5ed5acdb62426814a
Normal file
Binary file not shown.
BIN
corpus/6464d68e415e85657bdaf32a7c382a07fcc2ab08
Normal file
BIN
corpus/6464d68e415e85657bdaf32a7c382a07fcc2ab08
Normal file
Binary file not shown.
BIN
corpus/6641e52e0598415dcb942fd8341acba46bb3c80a
Normal file
BIN
corpus/6641e52e0598415dcb942fd8341acba46bb3c80a
Normal file
Binary file not shown.
BIN
corpus/694981aecb0b085aaa439bf9060bb9963a3cbc1c
Normal file
BIN
corpus/694981aecb0b085aaa439bf9060bb9963a3cbc1c
Normal file
Binary file not shown.
BIN
corpus/69db4d9277b327e1d7e474f85c205ef00309bf72
Normal file
BIN
corpus/69db4d9277b327e1d7e474f85c205ef00309bf72
Normal file
Binary file not shown.
BIN
corpus/6c6d33ece7ff6d93b98410a1cecf0b62e3ecc24d
Normal file
BIN
corpus/6c6d33ece7ff6d93b98410a1cecf0b62e3ecc24d
Normal file
Binary file not shown.
BIN
corpus/738b50c663d76c1a388b8c924c525f6b379584b5
Normal file
BIN
corpus/738b50c663d76c1a388b8c924c525f6b379584b5
Normal file
Binary file not shown.
BIN
corpus/759e6f65d0f4d3a77b93e7d975786255e32026bd
Normal file
BIN
corpus/759e6f65d0f4d3a77b93e7d975786255e32026bd
Normal file
Binary file not shown.
BIN
corpus/765ebb331233de0c5564be9d3ead01b344272093
Normal file
BIN
corpus/765ebb331233de0c5564be9d3ead01b344272093
Normal file
Binary file not shown.
BIN
corpus/77797d03e3a0538b0837a88a3e800a62c72f0829
Normal file
BIN
corpus/77797d03e3a0538b0837a88a3e800a62c72f0829
Normal file
Binary file not shown.
BIN
corpus/77cbfb5d27c19ee3a90a9fefdfcc6c9e1a511d16
Normal file
BIN
corpus/77cbfb5d27c19ee3a90a9fefdfcc6c9e1a511d16
Normal file
Binary file not shown.
BIN
corpus/77d5f793a71dd423d66f5f8c16258d8a55bb355a
Normal file
BIN
corpus/77d5f793a71dd423d66f5f8c16258d8a55bb355a
Normal file
Binary file not shown.
BIN
corpus/79132e64b834dc3e72d6502e7f4ffa1d8230876f
Normal file
BIN
corpus/79132e64b834dc3e72d6502e7f4ffa1d8230876f
Normal file
Binary file not shown.
BIN
corpus/7ca93e389e709f042644f02ff75fad7183558fa6
Normal file
BIN
corpus/7ca93e389e709f042644f02ff75fad7183558fa6
Normal file
Binary file not shown.
BIN
corpus/7d60449476ee4b8316ee62c9ce78a7d8ef4ccd58
Normal file
BIN
corpus/7d60449476ee4b8316ee62c9ce78a7d8ef4ccd58
Normal file
Binary file not shown.
BIN
corpus/7da1ebc7b5e251c9f1685ef6bdf61130db7ec06b
Normal file
BIN
corpus/7da1ebc7b5e251c9f1685ef6bdf61130db7ec06b
Normal file
Binary file not shown.
BIN
corpus/7f1db19e8d40fb5816703d9febe4019d815e9993
Normal file
BIN
corpus/7f1db19e8d40fb5816703d9febe4019d815e9993
Normal file
Binary file not shown.
BIN
corpus/809f69002e4f4d13ca8493a0a1bddf1b7bddc6dd
Normal file
BIN
corpus/809f69002e4f4d13ca8493a0a1bddf1b7bddc6dd
Normal file
Binary file not shown.
BIN
corpus/817af305c9bdd4df50086974fe220d89294fdf7a
Normal file
BIN
corpus/817af305c9bdd4df50086974fe220d89294fdf7a
Normal file
Binary file not shown.
BIN
corpus/85d8c1c151e94398e90c525a0a56e83a66e55b95
Normal file
BIN
corpus/85d8c1c151e94398e90c525a0a56e83a66e55b95
Normal file
Binary file not shown.
BIN
corpus/8b424a838a30bacef141ede5b487d9b4fd1d3b5c
Normal file
BIN
corpus/8b424a838a30bacef141ede5b487d9b4fd1d3b5c
Normal file
Binary file not shown.
BIN
corpus/8c23fc1b51f8b70f959cb22e0cb050d5e077c37e
Normal file
BIN
corpus/8c23fc1b51f8b70f959cb22e0cb050d5e077c37e
Normal file
Binary file not shown.
BIN
corpus/916d002d6d0b2a0ecd08321e234de66ef5928b3f
Normal file
BIN
corpus/916d002d6d0b2a0ecd08321e234de66ef5928b3f
Normal file
Binary file not shown.
BIN
corpus/920a776693d4437eeca2a1b02433a86265f74845
Normal file
BIN
corpus/920a776693d4437eeca2a1b02433a86265f74845
Normal file
Binary file not shown.
BIN
corpus/95a5e9d18312d747e275e7f0db61d6e1a2cce898
Normal file
BIN
corpus/95a5e9d18312d747e275e7f0db61d6e1a2cce898
Normal file
Binary file not shown.
BIN
corpus/9742cd44047659c81e78c79490fe09b2a496b923
Normal file
BIN
corpus/9742cd44047659c81e78c79490fe09b2a496b923
Normal file
Binary file not shown.
BIN
corpus/98798c935df0d24c46d56b6c9ebf3aec1996e74c
Normal file
BIN
corpus/98798c935df0d24c46d56b6c9ebf3aec1996e74c
Normal file
Binary file not shown.
BIN
corpus/9b49466a14883c625e16aaaf75e565e5f42833b4
Normal file
BIN
corpus/9b49466a14883c625e16aaaf75e565e5f42833b4
Normal file
Binary file not shown.
BIN
corpus/a0cd874b610c27ed3529bb5f660774631f9849e6
Normal file
BIN
corpus/a0cd874b610c27ed3529bb5f660774631f9849e6
Normal file
Binary file not shown.
BIN
corpus/a0de49bb69c8c6be8a6fe118bd9d11056f4c2de9
Normal file
BIN
corpus/a0de49bb69c8c6be8a6fe118bd9d11056f4c2de9
Normal file
Binary file not shown.
BIN
corpus/a110eeeb2e79180efbe5b07da4ba2e4521d7f915
Normal file
BIN
corpus/a110eeeb2e79180efbe5b07da4ba2e4521d7f915
Normal file
Binary file not shown.
BIN
corpus/a3d3d78aa99ba78b5cffeadb70d58b29a42fe684
Normal file
BIN
corpus/a3d3d78aa99ba78b5cffeadb70d58b29a42fe684
Normal file
Binary file not shown.
BIN
corpus/a50a416acf318dac2375be712dea420cb23bc376
Normal file
BIN
corpus/a50a416acf318dac2375be712dea420cb23bc376
Normal file
Binary file not shown.
BIN
corpus/a703d765db8649e30377adf3e78e182a35c1cf78
Normal file
BIN
corpus/a703d765db8649e30377adf3e78e182a35c1cf78
Normal file
Binary file not shown.
BIN
corpus/a95ccb66e6f469945b1559660c53b46e7235a574
Normal file
BIN
corpus/a95ccb66e6f469945b1559660c53b46e7235a574
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user