mirror of
https://github.com/apple/foundationdb.git
synced 2025-05-28 02:48:09 +08:00
clang-format
This commit is contained in:
parent
fa51a1abc5
commit
f5be0db366
@ -43,7 +43,8 @@ struct ConflictBatch {
|
||||
};
|
||||
|
||||
void addTransaction(const CommitTransactionRef& transaction);
|
||||
void detectConflicts(Version now, Version newOldestVersion, std::vector<int>& nonConflicting, std::vector<int>* tooOldTransactions = NULL);
|
||||
void detectConflicts(Version now, Version newOldestVersion, std::vector<int>& nonConflicting,
|
||||
std::vector<int>* tooOldTransactions = nullptr);
|
||||
void GetTooOldTransactions(std::vector<int>& tooOldTransactions);
|
||||
|
||||
private:
|
||||
@ -59,7 +60,8 @@ private:
|
||||
void combineWriteConflictRanges();
|
||||
void checkReadConflictRanges();
|
||||
void mergeWriteConflictRanges(Version now);
|
||||
void addConflictRanges(Version now, std::vector< std::pair<StringRef,StringRef> >::iterator begin, std::vector< std::pair<StringRef,StringRef> >::iterator end, class SkipList* part);
|
||||
void addConflictRanges(Version now, std::vector<std::pair<StringRef, StringRef>>::iterator begin,
|
||||
std::vector<std::pair<StringRef, StringRef>>::iterator end, class SkipList* part);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -40,10 +40,11 @@
|
||||
#include "fdbclient/SystemData.h"
|
||||
#include "fdbserver/Knobs.h"
|
||||
|
||||
#define PARALLEL_THREAD_COUNT 0 // FIXME: When >1, program execution (e.g. random numbers) is/was nondeterministic. Why?
|
||||
#define PARALLEL_THREAD_COUNT \
|
||||
0 // FIXME: When >1, program execution (e.g. random numbers) is/was nondeterministic. Why?
|
||||
|
||||
using std::min;
|
||||
using std::max;
|
||||
using std::min;
|
||||
|
||||
static std::vector<PerfDoubleCounter*> skc;
|
||||
|
||||
@ -70,8 +71,7 @@ bool SlowConflictSet::is_conflict( const VectorRef<KeyRangeRef>& readRanges, Ver
|
||||
for (auto range = readRanges.begin(); range != readRanges.end(); ++range) {
|
||||
auto intersecting = age.intersectingRanges(*range);
|
||||
for (auto it = intersecting.begin(); it != intersecting.end(); ++it)
|
||||
if ( it.value() > read_snapshot )
|
||||
return true;
|
||||
if (it.value() > read_snapshot) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -80,35 +80,20 @@ void SlowConflictSet::clear( Version now ) {
|
||||
age.insert(allKeys, now);
|
||||
}
|
||||
|
||||
void SlowConflictSet::add( const VectorRef<KeyRangeRef>& clearRanges, const VectorRef<KeyValueRef>& setValues, Version now ) {
|
||||
for(auto c = clearRanges.begin(); c != clearRanges.end(); ++c)
|
||||
age.insert( *c, now );
|
||||
for(auto s = setValues.begin(); s != setValues.end(); ++s)
|
||||
age.insert( s->key, now );
|
||||
void SlowConflictSet::add(const VectorRef<KeyRangeRef>& clearRanges, const VectorRef<KeyValueRef>& setValues,
|
||||
Version now) {
|
||||
for (auto c = clearRanges.begin(); c != clearRanges.end(); ++c) age.insert(*c, now);
|
||||
for (auto s = setValues.begin(); s != setValues.end(); ++s) age.insert(s->key, now);
|
||||
}
|
||||
|
||||
|
||||
PerfDoubleCounter
|
||||
g_buildTest("Build", skc),
|
||||
g_add("Add", skc),
|
||||
g_add_sort("A.Sort", skc),
|
||||
g_detectConflicts("Detect", skc),
|
||||
g_sort("D.Sort", skc),
|
||||
g_combine("D.Combine", skc),
|
||||
g_checkRead("D.CheckRead", skc),
|
||||
g_checkBatch("D.CheckIntraBatch", skc),
|
||||
g_merge("D.MergeWrite", skc),
|
||||
g_merge_launch("D.Merge.Launch", skc),
|
||||
g_merge_fork("D.Merge.Fork", skc),
|
||||
g_merge_start_var("D.Merge.StartVariance", skc),
|
||||
g_merge_end_var("D.Merge.EndVariance", skc),
|
||||
g_merge_run_var("D.Merge.RunVariance", skc),
|
||||
g_merge_run_shortest("D.Merge.ShortestRun", skc),
|
||||
g_merge_run_longest("D.Merge.LongestRun", skc),
|
||||
g_merge_run_total("D.Merge.TotalRun", skc),
|
||||
g_merge_join("D.Merge.Join", skc),
|
||||
g_removeBefore("D.RemoveBefore", skc)
|
||||
;
|
||||
PerfDoubleCounter g_buildTest("Build", skc), g_add("Add", skc), g_add_sort("A.Sort", skc),
|
||||
g_detectConflicts("Detect", skc), g_sort("D.Sort", skc), g_combine("D.Combine", skc),
|
||||
g_checkRead("D.CheckRead", skc), g_checkBatch("D.CheckIntraBatch", skc), g_merge("D.MergeWrite", skc),
|
||||
g_merge_launch("D.Merge.Launch", skc), g_merge_fork("D.Merge.Fork", skc),
|
||||
g_merge_start_var("D.Merge.StartVariance", skc), g_merge_end_var("D.Merge.EndVariance", skc),
|
||||
g_merge_run_var("D.Merge.RunVariance", skc), g_merge_run_shortest("D.Merge.ShortestRun", skc),
|
||||
g_merge_run_longest("D.Merge.LongestRun", skc), g_merge_run_total("D.Merge.TotalRun", skc),
|
||||
g_merge_join("D.Merge.Join", skc), g_removeBefore("D.RemoveBefore", skc);
|
||||
|
||||
static force_inline int compare(const StringRef& a, const StringRef& b) {
|
||||
int c = memcmp(a.begin(), b.begin(), min(a.size(), b.size()));
|
||||
@ -124,13 +109,10 @@ struct ReadConflictRange {
|
||||
Version version;
|
||||
int transaction;
|
||||
ReadConflictRange(StringRef begin, StringRef end, Version version, int transaction)
|
||||
: begin(begin), end(end), version(version), transaction(transaction)
|
||||
{
|
||||
}
|
||||
: begin(begin), end(end), version(version), transaction(transaction) {}
|
||||
bool operator<(const ReadConflictRange& rhs) const { return compare(begin, rhs.begin) < 0; }
|
||||
};
|
||||
|
||||
|
||||
struct KeyInfo {
|
||||
StringRef key;
|
||||
int* pIndex;
|
||||
@ -140,7 +122,8 @@ struct KeyInfo {
|
||||
int transaction;
|
||||
|
||||
KeyInfo(){};
|
||||
KeyInfo( StringRef key, bool nextKey, bool begin, bool write, int transaction, int* pIndex ) : key(key), nextKey(nextKey), begin(begin), write(write), transaction(transaction), pIndex(pIndex) {}
|
||||
KeyInfo(StringRef key, bool nextKey, bool begin, bool write, int transaction, int* pIndex)
|
||||
: key(key), nextKey(nextKey), begin(begin), write(write), transaction(transaction), pIndex(pIndex) {}
|
||||
};
|
||||
|
||||
// returns true if done with string
|
||||
@ -210,11 +193,9 @@ void swapSort(std::vector<KeyInfo>& points, int a, int b){
|
||||
|
||||
void smallSort(std::vector<KeyInfo>& points, int start, int N) {
|
||||
for (int i = 1; i < N; i++)
|
||||
for (int j=i;j>0;j-=2)
|
||||
swapSort(points, start+j-1, start+j);
|
||||
for (int j = i; j > 0; j -= 2) swapSort(points, start + j - 1, start + j);
|
||||
for (int i = N - 2; i > 0; i--)
|
||||
for (int j=i;j>0;j-=2)
|
||||
swapSort(points, start+j-1, start+j);
|
||||
for (int j = i; j > 0; j -= 2) swapSort(points, start + j - 1, start + j);
|
||||
}
|
||||
|
||||
struct SortTask {
|
||||
@ -251,15 +232,13 @@ void sortPoints(std::vector<KeyInfo>& points){
|
||||
allDone &= getCharacter(points[i], st.character, c);
|
||||
counts[c]++;
|
||||
}
|
||||
if (allDone)
|
||||
continue;
|
||||
if (allDone) continue;
|
||||
|
||||
// calculate offsets from counts and build next level of tasks
|
||||
int total = 0;
|
||||
for (int i = 0; i < counts.size(); i++) {
|
||||
int temp = counts[i];
|
||||
if (temp > 1)
|
||||
tasks.emplace_back(st.begin+total, temp, st.character+1);
|
||||
if (temp > 1) tasks.emplace_back(st.begin + total, temp, st.character + 1);
|
||||
counts[i] = total;
|
||||
total += temp;
|
||||
}
|
||||
@ -271,15 +250,13 @@ void sortPoints(std::vector<KeyInfo>& points){
|
||||
}
|
||||
|
||||
// copy back into original points array
|
||||
for (int i=0;i<st.size;i++)
|
||||
points[st.begin+i] = newPoints[i];
|
||||
for (int i = 0; i < st.size; i++) points[st.begin + i] = newPoints[i];
|
||||
}
|
||||
|
||||
// cout << endl << "Radix sort done" << endl;
|
||||
}
|
||||
|
||||
class SkipList : NonCopyable
|
||||
{
|
||||
class SkipList : NonCopyable {
|
||||
private:
|
||||
static const int MaxLevels = 26;
|
||||
|
||||
@ -371,11 +348,11 @@ private:
|
||||
INSTRUMENT_RELEASE("SkipListNodeLarge");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int getNodeSize() { return sizeof(Node) + valueLength + nPointers * (sizeof(Node*) + sizeof(Version)); }
|
||||
uint8_t* end() { return (uint8_t*)(this + 1); }
|
||||
int nPointers,
|
||||
valueLength;
|
||||
int nPointers, valueLength;
|
||||
};
|
||||
|
||||
static force_inline bool less(const uint8_t* a, int aLen, const uint8_t* b, int bLen) {
|
||||
@ -401,6 +378,7 @@ private:
|
||||
x->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
struct Finger {
|
||||
Node* finger[MaxLevels]; // valid for levels >= level
|
||||
@ -411,11 +389,7 @@ public:
|
||||
|
||||
Finger() : level(MaxLevels), x(NULL), alreadyChecked(NULL) {}
|
||||
|
||||
Finger( Node* header, const StringRef& ptr ) :
|
||||
value(ptr), level(MaxLevels),
|
||||
alreadyChecked(NULL), x(header)
|
||||
{
|
||||
}
|
||||
Finger(Node* header, const StringRef& ptr) : value(ptr), level(MaxLevels), alreadyChecked(NULL), x(header) {}
|
||||
|
||||
void init(const StringRef& value, Node* header) {
|
||||
this->value = value;
|
||||
@ -454,12 +428,11 @@ public:
|
||||
|
||||
// pre: !finished()
|
||||
force_inline void nextLevel() {
|
||||
while (!advance());
|
||||
while (!advance())
|
||||
;
|
||||
}
|
||||
|
||||
force_inline bool finished(){
|
||||
return level == 0;
|
||||
}
|
||||
force_inline bool finished() { return level == 0; }
|
||||
|
||||
force_inline Node* found() const {
|
||||
// valid after finished returns true
|
||||
@ -493,30 +466,21 @@ public:
|
||||
header->setMaxVersion(l, version);
|
||||
}
|
||||
}
|
||||
~SkipList() {
|
||||
destroy();
|
||||
}
|
||||
SkipList(SkipList&& other) BOOST_NOEXCEPT
|
||||
: header(other.header)
|
||||
{
|
||||
other.header = NULL;
|
||||
}
|
||||
~SkipList() { destroy(); }
|
||||
SkipList(SkipList&& other) BOOST_NOEXCEPT : header(other.header) { other.header = NULL; }
|
||||
void operator=(SkipList&& other) BOOST_NOEXCEPT {
|
||||
destroy();
|
||||
header = other.header;
|
||||
other.header = NULL;
|
||||
}
|
||||
void swap( SkipList& other ) {
|
||||
std::swap(header, other.header);
|
||||
}
|
||||
void swap(SkipList& other) { std::swap(header, other.header); }
|
||||
|
||||
void addConflictRanges(const Finger* fingers, int rangeCount, Version version) {
|
||||
for (int r = rangeCount - 1; r >= 0; r--) {
|
||||
const Finger& startF = fingers[r * 2];
|
||||
const Finger& endF = fingers[r * 2 + 1];
|
||||
|
||||
if (endF.found()==NULL)
|
||||
insert(endF, endF.finger[0]->getMaxVersion(0));
|
||||
if (endF.found() == NULL) insert(endF, endF.finger[0]->getMaxVersion(0));
|
||||
|
||||
remove(startF, endF);
|
||||
insert(startF, version);
|
||||
@ -545,8 +509,7 @@ public:
|
||||
if (prevJob == job) break;
|
||||
nextJob[prevJob] = nextJob[job];
|
||||
job = prevJob;
|
||||
}
|
||||
else
|
||||
} else
|
||||
inProgress[job].init(ranges[started++], header, transactionConflictStatus);
|
||||
}
|
||||
prevJob = job;
|
||||
@ -563,8 +526,7 @@ public:
|
||||
void partition(StringRef* begin, int splitCount, SkipList* output) {
|
||||
for (int i = splitCount - 1; i >= 0; i--) {
|
||||
Finger f(header, begin[i]);
|
||||
while (!f.finished())
|
||||
f.nextLevel();
|
||||
while (!f.finished()) f.nextLevel();
|
||||
split(f, output[i + 1]);
|
||||
}
|
||||
swap(output[0]);
|
||||
@ -572,14 +534,12 @@ public:
|
||||
|
||||
void concatenate(SkipList* input, int count) {
|
||||
std::vector<Finger> ends(count - 1);
|
||||
for(int i=0; i<ends.size(); i++)
|
||||
input[i].getEnd( ends[i] );
|
||||
for (int i = 0; i < ends.size(); i++) input[i].getEnd(ends[i]);
|
||||
|
||||
for (int l = 0; l < MaxLevels; l++) {
|
||||
for (int i = ends.size() - 1; i >= 0; i--) {
|
||||
ends[i].finger[l]->setNext(l, input[i + 1].header->getNext(l));
|
||||
if (l && (!i || ends[i].finger[l] != input[i].header))
|
||||
ends[i].finger[l]->calcVersionForLevel(l);
|
||||
if (l && (!i || ends[i].finger[l] != input[i].header)) ends[i].finger[l]->calcVersionForLevel(l);
|
||||
input[i + 1].header->setNext(l, NULL);
|
||||
}
|
||||
}
|
||||
@ -596,8 +556,7 @@ public:
|
||||
while (results[0].level > 1) {
|
||||
results[0].nextLevel();
|
||||
Node* ac = results[0].alreadyChecked;
|
||||
if (ac && less(ac->value(), ac->length(), endValue.begin(), endValue.size()))
|
||||
break;
|
||||
if (ac && less(ac->value(), ac->length(), endValue.begin(), endValue.size())) break;
|
||||
}
|
||||
|
||||
// Init all the other fingers to start descending where we stopped
|
||||
@ -612,13 +571,11 @@ public:
|
||||
results[i].x = x;
|
||||
results[i].alreadyChecked = NULL;
|
||||
results[i].value = values[i];
|
||||
for(int j=startLevel; j<MaxLevels; j++)
|
||||
results[i].finger[j] = results[0].finger[j];
|
||||
for (int j = startLevel; j < MaxLevels; j++) results[i].finger[j] = results[0].finger[j];
|
||||
}
|
||||
|
||||
int* nextJob = temp;
|
||||
for (int i=0;i<count-1;i++)
|
||||
nextJob[i] = i+1;
|
||||
for (int i = 0; i < count - 1; i++) nextJob[i] = i + 1;
|
||||
nextJob[count - 1] = 0;
|
||||
|
||||
int prevJob = count - 1;
|
||||
@ -631,8 +588,7 @@ public:
|
||||
if (f->finished()) {
|
||||
if (prevJob == job) break;
|
||||
nextJob[prevJob] = nextJob[job];
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
f->prefetch();
|
||||
prevJob = job;
|
||||
}
|
||||
@ -687,12 +643,10 @@ public:
|
||||
|
||||
bool isAbove = x->getMaxVersion(0) >= v;
|
||||
if (isAbove || wasAbove) { // f.nextItem
|
||||
for(int l=0; l<=x->level(); l++)
|
||||
f.finger[l] = x;
|
||||
for (int l = 0; l <= x->level(); l++) f.finger[l] = x;
|
||||
} else { // f.eraseItem
|
||||
removedCount++;
|
||||
for(int l=0; l<=x->level(); l++)
|
||||
f.finger[l]->setNext(l, x->getNext(l));
|
||||
for (int l = 0; l <= x->level(); l++) f.finger[l]->setNext(l, x->getNext(l));
|
||||
for (int i = 1; i <= x->level(); i++)
|
||||
f.finger[i]->setMaxVersion(i, max(f.finger[i]->getMaxVersion(i), x->getMaxVersion(i)));
|
||||
x->destroy();
|
||||
@ -705,15 +659,13 @@ public:
|
||||
|
||||
private:
|
||||
void remove(const Finger& start, const Finger& end) {
|
||||
if (start.finger[0] == end.finger[0])
|
||||
return;
|
||||
if (start.finger[0] == end.finger[0]) return;
|
||||
|
||||
Node* x = start.finger[0]->getNext(0);
|
||||
|
||||
// vtune says: this loop is the expensive parts (6 parts)
|
||||
for (int i = 0; i < MaxLevels; i++)
|
||||
if (start.finger[i] != end.finger[i])
|
||||
start.finger[i]->setNext(i, end.finger[i]->getNext(i));
|
||||
if (start.finger[i] != end.finger[i]) start.finger[i]->setNext(i, end.finger[i]->getNext(i));
|
||||
|
||||
while (true) {
|
||||
Node* next = x->getNext(0);
|
||||
@ -748,8 +700,7 @@ private:
|
||||
|
||||
void insert(const StringRef& value, Version version) {
|
||||
Finger f(header, value);
|
||||
while (!f.finished())
|
||||
f.nextLevel();
|
||||
while (!f.finished()) f.nextLevel();
|
||||
// SOMEDAY: equality?
|
||||
insert(f, version);
|
||||
}
|
||||
@ -769,7 +720,10 @@ private:
|
||||
}
|
||||
|
||||
bool noConflict() { return true; }
|
||||
bool conflict() { *result = true; return true; }
|
||||
bool conflict() {
|
||||
*result = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return true if finished
|
||||
force_inline bool advance() {
|
||||
@ -782,30 +736,25 @@ private:
|
||||
return false;
|
||||
}
|
||||
end.x = start.x;
|
||||
while (!end.advance());
|
||||
while (!end.advance())
|
||||
;
|
||||
|
||||
int l = start.level;
|
||||
if (start.finger[l] != end.finger[l])
|
||||
break;
|
||||
if (start.finger[l] != end.finger[l]) break;
|
||||
// accept if the range spans the check range, but does not have a greater version
|
||||
if (start.finger[l]->getMaxVersion(l) <= version)
|
||||
return noConflict();
|
||||
if (l==0)
|
||||
return conflict();
|
||||
if (start.finger[l]->getMaxVersion(l) <= version) return noConflict();
|
||||
if (l == 0) return conflict();
|
||||
}
|
||||
state = 1;
|
||||
case 1:
|
||||
{
|
||||
case 1: {
|
||||
// check the end side of the pyramid
|
||||
Node* e = end.finger[end.level];
|
||||
while (e->getMaxVersion(end.level) > version) {
|
||||
if (end.finished())
|
||||
return conflict();
|
||||
if (end.finished()) return conflict();
|
||||
end.nextLevel();
|
||||
Node* f = end.finger[end.level];
|
||||
while (e != f) {
|
||||
if (e->getMaxVersion(end.level) > version)
|
||||
return conflict();
|
||||
if (e->getMaxVersion(end.level) > version) return conflict();
|
||||
e = e->getNext(end.level);
|
||||
}
|
||||
}
|
||||
@ -816,15 +765,14 @@ private:
|
||||
Node* nextS = start.finger[start.level]->getNext(start.level);
|
||||
Node* p = nextS;
|
||||
while (p != s) {
|
||||
if (p->getMaxVersion(start.level) > version)
|
||||
return conflict();
|
||||
if (p->getMaxVersion(start.level) > version) return conflict();
|
||||
p = p->getNext(start.level);
|
||||
}
|
||||
if (start.finger[start.level]->getMaxVersion(start.level) <= version)
|
||||
return noConflict();
|
||||
if (start.finger[start.level]->getMaxVersion(start.level) <= version) return noConflict();
|
||||
s = nextS;
|
||||
if (start.finished()) {
|
||||
if (nextS->length() == start.value.size() && !memcmp(nextS->value(), start.value.begin(), start.value.size()))
|
||||
if (nextS->length() == start.value.size() &&
|
||||
!memcmp(nextS->value(), start.value.begin(), start.value.size()))
|
||||
return noConflict();
|
||||
else
|
||||
return conflict();
|
||||
@ -856,8 +804,7 @@ private:
|
||||
Node* node = header;
|
||||
for (int l = MaxLevels - 1; l >= 0; l--) {
|
||||
Node* next;
|
||||
while ( (next=node->getNext(l)) != NULL )
|
||||
node = next;
|
||||
while ((next = node->getNext(l)) != NULL) node = next;
|
||||
end.finger[l] = node;
|
||||
}
|
||||
end.level = 0;
|
||||
@ -877,7 +824,10 @@ template <class F>
|
||||
PAction action(F&& f) {
|
||||
struct FAction : Action, F, FastAllocated<FAction> {
|
||||
FAction(F&& f) : F(std::move(f)) {}
|
||||
virtual void operator()() { F::operator()(); delete this; }
|
||||
virtual void operator()() {
|
||||
F::operator()();
|
||||
delete this;
|
||||
}
|
||||
};
|
||||
return new FAction(std::move(f));
|
||||
};
|
||||
@ -915,10 +865,8 @@ StringRef setK( Arena& arena, int i ) {
|
||||
const int keySize = 16;
|
||||
|
||||
char* ss = new (arena) char[keySize];
|
||||
for(int c=0; c<keySize-sizeof(i); c++)
|
||||
ss[c] = '.';
|
||||
for(int c=0; c<sizeof(i); c++)
|
||||
ss[c+keySize-sizeof(i)] = t[sizeof(i)-1-c];
|
||||
for (int c = 0; c < keySize - sizeof(i); c++) ss[c] = '.';
|
||||
for (int c = 0; c < sizeof(i); c++) ss[c + keySize - sizeof(i)] = t[sizeof(i) - 1 - c];
|
||||
|
||||
return StringRef((const uint8_t*)ss, keySize);
|
||||
}
|
||||
@ -928,7 +876,8 @@ StringRef setK( Arena& arena, int i ) {
|
||||
struct ConflictSet {
|
||||
ConflictSet() : oldestVersion(0) {
|
||||
static_assert(PARALLEL_THREAD_COUNT == 0, "workerThread() not implemented");
|
||||
static_assert(PARALLEL_THREAD_COUNT == 0 || FASTALLOC_THREAD_SAFE, "Thread safe fast allocator required for multithreaded conflict set");
|
||||
static_assert(PARALLEL_THREAD_COUNT == 0 || FASTALLOC_THREAD_SAFE,
|
||||
"Thread safe fast allocator required for multithreaded conflict set");
|
||||
for (int i = 0; i < PARALLEL_THREAD_COUNT; i++) {
|
||||
worker_nextAction.push_back(NULL);
|
||||
worker_ready.push_back(new Event);
|
||||
@ -943,8 +892,7 @@ struct ConflictSet {
|
||||
worker_ready[i]->set();
|
||||
}
|
||||
// Wait for workers to terminate; otherwise can get crashes at shutdown time
|
||||
for(int i=0; i<worker_finished.size(); i++)
|
||||
worker_finished[i]->block();
|
||||
for (int i = 0; i < worker_finished.size(); i++) worker_finished[i]->block();
|
||||
}
|
||||
|
||||
SkipList versionHistory;
|
||||
@ -955,7 +903,9 @@ struct ConflictSet {
|
||||
std::vector<Event*> worker_finished;
|
||||
};
|
||||
|
||||
ConflictSet* newConflictSet() { return new ConflictSet; }
|
||||
ConflictSet* newConflictSet() {
|
||||
return new ConflictSet;
|
||||
}
|
||||
void clearConflictSet(ConflictSet* cs, Version v) {
|
||||
SkipList(v).swap(cs->versionHistory);
|
||||
}
|
||||
@ -963,14 +913,9 @@ void destroyConflictSet(ConflictSet* cs) {
|
||||
delete cs;
|
||||
}
|
||||
|
||||
ConflictBatch::ConflictBatch( ConflictSet* cs )
|
||||
: cs(cs), transactionCount(0)
|
||||
{
|
||||
}
|
||||
ConflictBatch::ConflictBatch(ConflictSet* cs) : cs(cs), transactionCount(0) {}
|
||||
|
||||
ConflictBatch::~ConflictBatch()
|
||||
{
|
||||
}
|
||||
ConflictBatch::~ConflictBatch() {}
|
||||
|
||||
struct TransactionInfo {
|
||||
VectorRef<std::pair<int, int>> readRanges;
|
||||
@ -1011,18 +956,15 @@ void ConflictBatch::addTransaction( const CommitTransactionRef& tr ) {
|
||||
|
||||
class MiniConflictSet2 : NonCopyable {
|
||||
std::vector<bool> values;
|
||||
|
||||
public:
|
||||
explicit MiniConflictSet2( int size ) {
|
||||
values.assign( size, false );
|
||||
}
|
||||
explicit MiniConflictSet2(int size) { values.assign(size, false); }
|
||||
void set(int begin, int end) {
|
||||
for(int i=begin; i<end; i++)
|
||||
values[i] = true;
|
||||
for (int i = begin; i < end; i++) values[i] = true;
|
||||
}
|
||||
bool any(int begin, int end) {
|
||||
for (int i = begin; i < end; i++)
|
||||
if (values[i])
|
||||
return true;
|
||||
if (values[i]) return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@ -1038,18 +980,12 @@ class MiniConflictSet : NonCopyable {
|
||||
wordType bitMask(unsigned int bit) { // computes results for bit%word
|
||||
return (((wordType)1) << (bit & bucketMask));
|
||||
}
|
||||
void setNthBit(std::vector<wordType>& v, const unsigned int bit){
|
||||
v[bit>>bucketShift] |= bitMask(bit);
|
||||
}
|
||||
void clearNthBit(std::vector<wordType>& v, const unsigned int bit){
|
||||
v[bit>>bucketShift] &= ~(bitMask(bit));
|
||||
}
|
||||
void setNthBit(std::vector<wordType>& v, const unsigned int bit) { v[bit >> bucketShift] |= bitMask(bit); }
|
||||
void clearNthBit(std::vector<wordType>& v, const unsigned int bit) { v[bit >> bucketShift] &= ~(bitMask(bit)); }
|
||||
bool getNthBit(const std::vector<wordType>& v, const unsigned int bit) {
|
||||
return (v[bit >> bucketShift] & bitMask(bit)) != 0;
|
||||
}
|
||||
int wordsForNBits(unsigned int bits){
|
||||
return (bits+((1<<bucketShift)-1))>>bucketShift;
|
||||
}
|
||||
int wordsForNBits(unsigned int bits) { return (bits + ((1 << bucketShift) - 1)) >> bucketShift; }
|
||||
wordType highBits(int b) { // bits (b&bucketMask) and higher are 1
|
||||
#pragma warning(disable : 4146)
|
||||
return -bitMask(b);
|
||||
@ -1058,9 +994,7 @@ class MiniConflictSet : NonCopyable {
|
||||
wordType lowBits(int b) { // bits lower than (b&bucketMask) are 1
|
||||
return bitMask(b) - 1;
|
||||
}
|
||||
wordType lowBits2(int b) {
|
||||
return (b&bucketMask) ? lowBits(b) : -1;
|
||||
}
|
||||
wordType lowBits2(int b) { return (b & bucketMask) ? lowBits(b) : -1; }
|
||||
|
||||
void setBits(std::vector<wordType>& v, int bitBegin, int bitEnd, bool fillMiddle) {
|
||||
if (bitBegin >= bitEnd) return;
|
||||
@ -1071,8 +1005,7 @@ class MiniConflictSet : NonCopyable {
|
||||
} else {
|
||||
v[beginWord] |= highBits(bitBegin);
|
||||
if (fillMiddle)
|
||||
for(int w=beginWord+1;w<lastWord;w++)
|
||||
v[w] = wordType(-1);
|
||||
for (int w = beginWord + 1; w < lastWord; w++) v[w] = wordType(-1);
|
||||
v[lastWord] |= lowBits2(bitEnd);
|
||||
}
|
||||
}
|
||||
@ -1086,8 +1019,7 @@ class MiniConflictSet : NonCopyable {
|
||||
else {
|
||||
if (getMiddle)
|
||||
for (int w = beginWord + 1; w < lastWord; w++)
|
||||
if (v[w])
|
||||
return true;
|
||||
if (v[w]) return true;
|
||||
return ((v[beginWord] & highBits(bitBegin)) | (v[lastWord] & lowBits2(bitEnd))) != 0;
|
||||
}
|
||||
}
|
||||
@ -1130,11 +1062,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void ConflictBatch::checkIntraBatchConflicts() {
|
||||
int index = 0;
|
||||
for(int p=0; p<points.size(); p++)
|
||||
*points[p].pIndex = index++;
|
||||
for (int p = 0; p < points.size(); p++) *points[p].pIndex = index++;
|
||||
|
||||
MiniConflictSet mcs(index);
|
||||
for (int t = 0; t < transactionInfo.size(); t++) {
|
||||
@ -1148,8 +1078,7 @@ void ConflictBatch::checkIntraBatchConflicts() {
|
||||
}
|
||||
transactionConflictStatus[t] = conflict;
|
||||
if (!conflict)
|
||||
for(int i=0; i<tr.writeRanges.size(); i++)
|
||||
mcs.set( tr.writeRanges[i].first, tr.writeRanges[i].second );
|
||||
for (int i = 0; i < tr.writeRanges.size(); i++) mcs.set(tr.writeRanges[i].first, tr.writeRanges[i].second);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1161,7 +1090,8 @@ void ConflictBatch::GetTooOldTransactions(std::vector<int>& tooOldTransactions)
|
||||
}
|
||||
}
|
||||
|
||||
void ConflictBatch::detectConflicts(Version now, Version newOldestVersion, std::vector<int>& nonConflicting, std::vector<int>* tooOldTransactions) {
|
||||
void ConflictBatch::detectConflicts(Version now, Version newOldestVersion, std::vector<int>& nonConflicting,
|
||||
std::vector<int>* tooOldTransactions) {
|
||||
double t = timer();
|
||||
sortPoints(points);
|
||||
// std::sort( combinedReadConflictRanges.begin(), combinedReadConflictRanges.end() );
|
||||
@ -1186,12 +1116,9 @@ void ConflictBatch::detectConflicts(Version now, Version newOldestVersion, std::
|
||||
mergeWriteConflictRanges(now);
|
||||
g_merge += timer() - t;
|
||||
|
||||
for (int i = 0; i < transactionCount; i++)
|
||||
{
|
||||
if (!transactionConflictStatus[i])
|
||||
nonConflicting.push_back( i );
|
||||
if (tooOldTransactions && transactionInfo[i]->tooOld)
|
||||
tooOldTransactions->push_back(i);
|
||||
for (int i = 0; i < transactionCount; i++) {
|
||||
if (!transactionConflictStatus[i]) nonConflicting.push_back(i);
|
||||
if (tooOldTransactions && transactionInfo[i]->tooOld) tooOldTransactions->push_back(i);
|
||||
}
|
||||
|
||||
delete[] transactionConflictStatus;
|
||||
@ -1209,8 +1136,7 @@ void ConflictBatch::detectConflicts(Version now, Version newOldestVersion, std::
|
||||
}
|
||||
|
||||
void ConflictBatch::checkReadConflictRanges() {
|
||||
if (!combinedReadConflictRanges.size())
|
||||
return;
|
||||
if (!combinedReadConflictRanges.size()) return;
|
||||
|
||||
if (PARALLEL_THREAD_COUNT) {
|
||||
Event done[PARALLEL_THREAD_COUNT ? PARALLEL_THREAD_COUNT : 1];
|
||||
@ -1218,29 +1144,33 @@ void ConflictBatch::checkReadConflictRanges() {
|
||||
cs->worker_nextAction[t] = action([&, t] {
|
||||
#pragma GCC diagnostic push
|
||||
DISABLE_ZERO_DIVISION_FLAG
|
||||
auto begin = &combinedReadConflictRanges[0] + t*combinedReadConflictRanges.size()/PARALLEL_THREAD_COUNT;
|
||||
auto end = &combinedReadConflictRanges[0] + (t+1)*combinedReadConflictRanges.size()/PARALLEL_THREAD_COUNT;
|
||||
auto begin =
|
||||
&combinedReadConflictRanges[0] + t * combinedReadConflictRanges.size() / PARALLEL_THREAD_COUNT;
|
||||
auto end = &combinedReadConflictRanges[0] +
|
||||
(t + 1) * combinedReadConflictRanges.size() / PARALLEL_THREAD_COUNT;
|
||||
#pragma GCC diagnostic pop
|
||||
cs->versionHistory.detectConflicts(begin, end - begin, transactionConflictStatus);
|
||||
done[t].set();
|
||||
});
|
||||
cs->worker_ready[t]->set();
|
||||
}
|
||||
for(int i=0; i<PARALLEL_THREAD_COUNT; i++)
|
||||
done[i].block();
|
||||
for (int i = 0; i < PARALLEL_THREAD_COUNT; i++) done[i].block();
|
||||
} else {
|
||||
cs->versionHistory.detectConflicts( &combinedReadConflictRanges[0], combinedReadConflictRanges.size(), transactionConflictStatus );
|
||||
cs->versionHistory.detectConflicts(&combinedReadConflictRanges[0], combinedReadConflictRanges.size(),
|
||||
transactionConflictStatus);
|
||||
}
|
||||
}
|
||||
|
||||
void ConflictBatch::addConflictRanges(Version now, std::vector< std::pair<StringRef,StringRef> >::iterator begin, std::vector< std::pair<StringRef,StringRef> >::iterator end,SkipList* part) {
|
||||
void ConflictBatch::addConflictRanges(Version now, std::vector<std::pair<StringRef, StringRef>>::iterator begin,
|
||||
std::vector<std::pair<StringRef, StringRef>>::iterator end, SkipList* part) {
|
||||
int count = end - begin;
|
||||
#if 0
|
||||
//for(auto w = begin; w != end; ++w)
|
||||
for(auto w = end-1; w != begin-1; --w)
|
||||
part->addConflictRange( w->first, w->second, now );
|
||||
#else
|
||||
static_assert( sizeof( begin[0] ) == sizeof(StringRef)*2, "Write Conflict Range type not convertible to two StringPtrs" );
|
||||
static_assert(sizeof(begin[0]) == sizeof(StringRef) * 2,
|
||||
"Write Conflict Range type not convertible to two StringPtrs");
|
||||
const StringRef* strings = reinterpret_cast<const StringRef*>(&*begin);
|
||||
int stringCount = count * 2;
|
||||
|
||||
@ -1259,13 +1189,11 @@ void ConflictBatch::addConflictRanges(Version now, std::vector< std::pair<String
|
||||
}
|
||||
|
||||
void ConflictBatch::mergeWriteConflictRanges(Version now) {
|
||||
if (!combinedWriteConflictRanges.size())
|
||||
return;
|
||||
if (!combinedWriteConflictRanges.size()) return;
|
||||
|
||||
if (PARALLEL_THREAD_COUNT) {
|
||||
std::vector<SkipList> parts;
|
||||
for (int i = 0; i < PARALLEL_THREAD_COUNT; i++)
|
||||
parts.emplace_back();
|
||||
for (int i = 0; i < PARALLEL_THREAD_COUNT; i++) parts.emplace_back();
|
||||
|
||||
std::vector<StringRef> splits(parts.size() - 1);
|
||||
for (int s = 0; s < splits.size(); s++)
|
||||
@ -1278,8 +1206,10 @@ void ConflictBatch::mergeWriteConflictRanges(Version now) {
|
||||
for (int t = 0; t < parts.size(); t++) {
|
||||
cs->worker_nextAction[t] = action([&, t] {
|
||||
tstart[t] = timer();
|
||||
auto begin = combinedWriteConflictRanges.begin() + (t*combinedWriteConflictRanges.size()/parts.size());
|
||||
auto end = combinedWriteConflictRanges.begin() + ((t+1)*combinedWriteConflictRanges.size()/parts.size());
|
||||
auto begin =
|
||||
combinedWriteConflictRanges.begin() + (t * combinedWriteConflictRanges.size() / parts.size());
|
||||
auto end =
|
||||
combinedWriteConflictRanges.begin() + ((t + 1) * combinedWriteConflictRanges.size() / parts.size());
|
||||
|
||||
addConflictRanges(now, begin, end, &parts[t]);
|
||||
|
||||
@ -1289,14 +1219,14 @@ void ConflictBatch::mergeWriteConflictRanges(Version now) {
|
||||
cs->worker_ready[t]->set();
|
||||
}
|
||||
double launch = timer();
|
||||
for(int i=0; i<PARALLEL_THREAD_COUNT; i++)
|
||||
done[i].block();
|
||||
for (int i = 0; i < PARALLEL_THREAD_COUNT; i++) done[i].block();
|
||||
double after = timer();
|
||||
|
||||
g_merge_launch += launch - before;
|
||||
// g_merge_start_var += *std::max_element(tstart.begin(), tstart.end()) - before;
|
||||
g_merge_fork += *std::min_element(tstart.begin(), tstart.end()) - before;
|
||||
g_merge_start_var += *std::max_element(tstart.begin(), tstart.end()) - *std::min_element(tstart.begin(), tstart.end());
|
||||
g_merge_start_var +=
|
||||
*std::max_element(tstart.begin(), tstart.end()) - *std::min_element(tstart.begin(), tstart.end());
|
||||
g_merge_end_var += *std::max_element(tend.begin(), tend.end()) - *std::min_element(tend.begin(), tend.end());
|
||||
g_merge_join += after - *std::max_element(tend.begin(), tend.end());
|
||||
double run_max = 0, run_min = 1e9;
|
||||
@ -1307,31 +1237,30 @@ void ConflictBatch::mergeWriteConflictRanges(Version now) {
|
||||
g_merge_run_var += run_max - run_min;
|
||||
g_merge_run_shortest += run_min;
|
||||
g_merge_run_longest += run_max;
|
||||
g_merge_run_total += std::accumulate(tend.begin(),tend.end(),0.0)-std::accumulate(tstart.begin(),tstart.end(),0.0);
|
||||
g_merge_run_total +=
|
||||
std::accumulate(tend.begin(), tend.end(), 0.0) - std::accumulate(tstart.begin(), tstart.end(), 0.0);
|
||||
|
||||
cs->versionHistory.concatenate(&parts[0], parts.size());
|
||||
} else {
|
||||
addConflictRanges( now, combinedWriteConflictRanges.begin(), combinedWriteConflictRanges.end(), &cs->versionHistory );
|
||||
addConflictRanges(now, combinedWriteConflictRanges.begin(), combinedWriteConflictRanges.end(),
|
||||
&cs->versionHistory);
|
||||
}
|
||||
|
||||
// for(auto w = combinedWriteConflictRanges.begin(); w != combinedWriteConflictRanges.end(); ++w)
|
||||
// versionHistory.addConflictRange( w->first.begin(), w->first.size(), w->second.begin(), w->second.size(), now );
|
||||
}
|
||||
|
||||
void ConflictBatch::combineWriteConflictRanges()
|
||||
{
|
||||
void ConflictBatch::combineWriteConflictRanges() {
|
||||
int activeWriteCount = 0;
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
KeyInfo& point = points[i];
|
||||
if (point.write && !transactionConflictStatus[point.transaction]) {
|
||||
if (point.begin) {
|
||||
activeWriteCount++;
|
||||
if (activeWriteCount == 1)
|
||||
combinedWriteConflictRanges.emplace_back(point.key, KeyRef());
|
||||
if (activeWriteCount == 1) combinedWriteConflictRanges.emplace_back(point.key, KeyRef());
|
||||
} else /*if (point.end)*/ {
|
||||
activeWriteCount--;
|
||||
if (activeWriteCount == 0)
|
||||
combinedWriteConflictRanges.back().second = point.key;
|
||||
if (activeWriteCount == 0) combinedWriteConflictRanges.back().second = point.key;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1342,10 +1271,8 @@ void ConflictBatch::combineWriteConflictRanges()
|
||||
/*
|
||||
bool sse4Less( const uint8_t* a, int aLen, const uint8_t* b, int bLen ) {
|
||||
while (true) {
|
||||
int res = _mm_cmpestri(*(__m128i*)a, aLen, *(__m128i*)b, bLen, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_EACH | _SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT );
|
||||
printf("%d ", res);
|
||||
if (res == 16) {
|
||||
if (bLen < 16) return false;
|
||||
int res = _mm_cmpestri(*(__m128i*)a, aLen, *(__m128i*)b, bLen, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_EACH |
|
||||
_SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT ); printf("%d ", res); if (res == 16) { if (bLen < 16) return false;
|
||||
a += 16; b += 16; aLen -= 16; bLen -= 16;
|
||||
}
|
||||
if (res == bLen) return false;
|
||||
@ -1385,7 +1312,8 @@ void sse4Test(){
|
||||
__m128i aa = *(__m128i*)a;
|
||||
__m128i bb = *(__m128i*)a;
|
||||
|
||||
int res = _mm_cmpestri(aa, 2, bb, 2, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_EACH | _SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT );
|
||||
int res = _mm_cmpestri(aa, 2, bb, 2, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_EACH | _SIDD_NEGATIVE_POLARITY |
|
||||
_SIDD_LEAST_SIGNIFICANT );
|
||||
|
||||
cout << res << endl;
|
||||
|
||||
@ -1421,7 +1349,6 @@ void skipListTest() {
|
||||
|
||||
miniConflictSetTest();
|
||||
|
||||
|
||||
setAffinity(0);
|
||||
// showNumaStatus();
|
||||
|
||||
@ -1441,9 +1368,7 @@ void skipListTest() {
|
||||
for (int j = 0; j < testData[i].size(); j++) {
|
||||
int key = deterministicRandom()->randomInt(0, 20000000);
|
||||
int key2 = key + 1 + deterministicRandom()->randomInt(0, 10);
|
||||
testData[i][j] = KeyRangeRef(
|
||||
setK( testDataArena, key ),
|
||||
setK( testDataArena, key2 ) );
|
||||
testData[i][j] = KeyRangeRef(setK(testDataArena, key), setK(testDataArena, key2));
|
||||
}
|
||||
}
|
||||
printf("Test data generated (%d)\n", deterministicRandom()->randomInt(0, 100000));
|
||||
@ -1479,8 +1404,7 @@ void skipListTest() {
|
||||
|
||||
t = timer();
|
||||
ConflictBatch batch(cs);
|
||||
for(int j=0; j<trs.size(); j++)
|
||||
batch.addTransaction( trs[j] );
|
||||
for (int j = 0; j < trs.size(); j++) batch.addTransaction(trs[j]);
|
||||
g_add += timer() - t;
|
||||
|
||||
t = timer();
|
||||
@ -1548,5 +1472,6 @@ void skipListTest() {
|
||||
printf("ERROR: %d transactions incorrectly accepted!\n", aminusb);
|
||||
*/
|
||||
// for(int i=0; i<testData.size(); i++)
|
||||
// printf("%d %d %d %d\n", i, nonConflict[i].size(), nonConflict2[i].size()-nonConflict[i].size(), nonConflict[i] != nonConflict2[i]);
|
||||
// printf("%d %d %d %d\n", i, nonConflict[i].size(), nonConflict2[i].size()-nonConflict[i].size(), nonConflict[i]
|
||||
//!= nonConflict2[i]);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user