Compare commits
3 Commits
cdb5360b9a
...
a4d1f91670
Author | SHA1 | Date | |
---|---|---|---|
a4d1f91670 | |||
b7cdecaf71 | |||
cda28643a6 |
@@ -2607,16 +2607,25 @@ ConflictSet_check(void *cs, const ConflictSet_ReadRange *reads,
|
|||||||
__attribute__((__visibility__("default"))) void
|
__attribute__((__visibility__("default"))) void
|
||||||
ConflictSet_addWrites(void *cs, const ConflictSet_WriteRange *writes, int count,
|
ConflictSet_addWrites(void *cs, const ConflictSet_WriteRange *writes, int count,
|
||||||
int64_t writeVersion) {
|
int64_t writeVersion) {
|
||||||
((ConflictSet::Impl *)cs)->addWrites(writes, count, writeVersion);
|
auto *impl = ((ConflictSet::Impl *)cs);
|
||||||
|
mallocBytesDelta = 0;
|
||||||
|
impl->addWrites(writes, count, writeVersion);
|
||||||
|
impl->totalBytes += mallocBytesDelta;
|
||||||
}
|
}
|
||||||
__attribute__((__visibility__("default"))) void
|
__attribute__((__visibility__("default"))) void
|
||||||
ConflictSet_setOldestVersion(void *cs, int64_t oldestVersion) {
|
ConflictSet_setOldestVersion(void *cs, int64_t oldestVersion) {
|
||||||
((ConflictSet::Impl *)cs)->setOldestVersion(oldestVersion);
|
auto *impl = ((ConflictSet::Impl *)cs);
|
||||||
|
mallocBytesDelta = 0;
|
||||||
|
impl->setOldestVersion(oldestVersion);
|
||||||
|
impl->totalBytes += mallocBytesDelta;
|
||||||
}
|
}
|
||||||
__attribute__((__visibility__("default"))) void *
|
__attribute__((__visibility__("default"))) void *
|
||||||
ConflictSet_create(int64_t oldestVersion) {
|
ConflictSet_create(int64_t oldestVersion) {
|
||||||
return new (safe_malloc(sizeof(ConflictSet::Impl)))
|
mallocBytesDelta = 0;
|
||||||
|
auto *result = new (safe_malloc(sizeof(ConflictSet::Impl)))
|
||||||
ConflictSet::Impl{oldestVersion};
|
ConflictSet::Impl{oldestVersion};
|
||||||
|
result->totalBytes += mallocBytesDelta;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
__attribute__((__visibility__("default"))) void ConflictSet_destroy(void *cs) {
|
__attribute__((__visibility__("default"))) void ConflictSet_destroy(void *cs) {
|
||||||
using Impl = ConflictSet::Impl;
|
using Impl = ConflictSet::Impl;
|
||||||
@@ -2630,6 +2639,12 @@ ConflictSet_getBytes(void *cs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure abi is well-defined
|
||||||
|
static_assert(std::is_standard_layout_v<ConflictSet::Result>);
|
||||||
|
static_assert(std::is_standard_layout_v<ConflictSet::Key>);
|
||||||
|
static_assert(std::is_standard_layout_v<ConflictSet::ReadRange>);
|
||||||
|
static_assert(std::is_standard_layout_v<ConflictSet::WriteRange>);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
std::string getSearchPathPrintable(Node *n) {
|
std::string getSearchPathPrintable(Node *n) {
|
||||||
|
100
README.md
100
README.md
@@ -9,49 +9,49 @@ Hardware for all benchmarks is a mac m1 2020.
|
|||||||
## Skip list
|
## Skip list
|
||||||
|
|
||||||
```
|
```
|
||||||
New conflict set: 1.964 sec
|
New conflict set: 1.962 sec
|
||||||
0.637 Mtransactions/sec
|
0.637 Mtransactions/sec
|
||||||
2.546 Mkeys/sec
|
2.548 Mkeys/sec
|
||||||
Detect only: 1.859 sec
|
Detect only: 1.842 sec
|
||||||
0.672 Mtransactions/sec
|
0.679 Mtransactions/sec
|
||||||
2.690 Mkeys/sec
|
2.714 Mkeys/sec
|
||||||
Skiplist only: 1.275 sec
|
Skiplist only: 1.261 sec
|
||||||
0.980 Mtransactions/sec
|
0.991 Mtransactions/sec
|
||||||
3.921 Mkeys/sec
|
3.964 Mkeys/sec
|
||||||
Performance counters:
|
Performance counters:
|
||||||
Build: 0.0496
|
Build: 0.0597
|
||||||
Add: 0.0539
|
Add: 0.0587
|
||||||
Detect: 1.86
|
Detect: 1.84
|
||||||
D.Sort: 0.412
|
D.Sort: 0.411
|
||||||
D.Combine: 0.0139
|
D.Combine: 0.0136
|
||||||
D.CheckRead: 0.682
|
D.CheckRead: 0.67
|
||||||
D.CheckIntraBatch: 0.00673
|
D.CheckIntraBatch: 0.00671
|
||||||
D.MergeWrite: 0.593
|
D.MergeWrite: 0.592
|
||||||
D.RemoveBefore: 0.148
|
D.RemoveBefore: 0.146
|
||||||
```
|
```
|
||||||
|
|
||||||
## Radix tree (this implementation)
|
## Radix tree (this implementation)
|
||||||
|
|
||||||
```
|
```
|
||||||
New conflict set: 1.289 sec
|
New conflict set: 1.285 sec
|
||||||
0.970 Mtransactions/sec
|
0.973 Mtransactions/sec
|
||||||
3.879 Mkeys/sec
|
3.892 Mkeys/sec
|
||||||
Detect only: 1.199 sec
|
Detect only: 1.196 sec
|
||||||
1.043 Mtransactions/sec
|
1.045 Mtransactions/sec
|
||||||
4.170 Mkeys/sec
|
4.180 Mkeys/sec
|
||||||
Skiplist only: 0.542 sec
|
Skiplist only: 0.539 sec
|
||||||
2.305 Mtransactions/sec
|
2.320 Mtransactions/sec
|
||||||
9.220 Mkeys/sec
|
9.281 Mkeys/sec
|
||||||
Performance counters:
|
Performance counters:
|
||||||
Build: 0.0395
|
Build: 0.0377
|
||||||
Add: 0.0492
|
Add: 0.0493
|
||||||
Detect: 1.2
|
Detect: 1.2
|
||||||
D.Sort: 0.411
|
D.Sort: 0.41
|
||||||
D.Combine: 0.0135
|
D.Combine: 0.0135
|
||||||
D.CheckRead: 0.22
|
D.CheckRead: 0.219
|
||||||
D.CheckIntraBatch: 0.00652
|
D.CheckIntraBatch: 0.00654
|
||||||
D.MergeWrite: 0.322
|
D.MergeWrite: 0.319
|
||||||
D.RemoveBefore: 0.223
|
D.RemoveBefore: 0.224
|
||||||
```
|
```
|
||||||
|
|
||||||
# Our benchmark
|
# Our benchmark
|
||||||
@@ -60,25 +60,25 @@ Performance counters:
|
|||||||
|
|
||||||
| ns/op | op/s | err% | total | benchmark
|
| ns/op | op/s | err% | total | benchmark
|
||||||
|--------------------:|--------------------:|--------:|----------:|:----------
|
|--------------------:|--------------------:|--------:|----------:|:----------
|
||||||
| 249.47 | 4,008,533.72 | 0.5% | 0.01 | `point reads`
|
| 246.99 | 4,048,700.59 | 0.2% | 0.01 | `point reads`
|
||||||
| 236.78 | 4,223,252.12 | 0.4% | 0.01 | `prefix reads`
|
| 260.16 | 3,843,784.65 | 0.1% | 0.01 | `prefix reads`
|
||||||
| 432.76 | 2,310,737.74 | 0.1% | 0.01 | `range reads`
|
| 493.35 | 2,026,953.19 | 0.1% | 0.01 | `range reads`
|
||||||
| 449.42 | 2,225,105.96 | 0.5% | 0.01 | `point writes`
|
| 462.05 | 2,164,289.23 | 0.6% | 0.01 | `point writes`
|
||||||
| 438.47 | 2,280,674.39 | 0.3% | 0.01 | `prefix writes`
|
| 448.19 | 2,231,205.25 | 0.9% | 0.01 | `prefix writes`
|
||||||
| 242.92 | 4,116,581.59 | 3.7% | 0.02 | `range writes`
|
| 255.83 | 3,908,845.72 | 1.5% | 0.02 | `range writes`
|
||||||
| 553.31 | 1,807,319.60 | 0.7% | 0.01 | `monotonic increasing point writes`
|
| 582.63 | 1,716,349.02 | 1.3% | 0.01 | `monotonic increasing point writes`
|
||||||
|
|
||||||
## Radix tree (this implementation)
|
## Radix tree (this implementation)
|
||||||
|
|
||||||
| ns/op | op/s | err% | total | benchmark
|
| ns/op | op/s | err% | total | benchmark
|
||||||
|--------------------:|--------------------:|--------:|----------:|:----------
|
|--------------------:|--------------------:|--------:|----------:|:----------
|
||||||
| 19.35 | 51,669,510.11 | 0.2% | 0.01 | `point reads`
|
| 19.42 | 51,483,206.67 | 0.3% | 0.01 | `point reads`
|
||||||
| 56.64 | 17,655,057.00 | 0.2% | 0.01 | `prefix reads`
|
| 58.43 | 17,115,612.57 | 0.1% | 0.01 | `prefix reads`
|
||||||
| 217.04 | 4,607,450.05 | 0.2% | 0.01 | `range reads`
|
| 216.09 | 4,627,766.60 | 0.2% | 0.01 | `range reads`
|
||||||
| 26.31 | 38,012,015.29 | 0.0% | 0.01 | `point writes`
|
| 28.35 | 35,267,567.72 | 0.2% | 0.01 | `point writes`
|
||||||
| 41.45 | 24,124,003.19 | 0.2% | 0.01 | `prefix writes`
|
| 43.43 | 23,026,226.17 | 0.2% | 0.01 | `prefix writes`
|
||||||
| 48.33 | 20,691,082.14 | 0.0% | 0.01 | `range writes`
|
| 50.00 | 20,000,000.00 | 0.0% | 0.01 | `range writes`
|
||||||
| 84.92 | 11,775,856.81 | 4.0% | 0.01 | `monotonic increasing point writes`
|
| 92.38 | 10,824,863.69 | 4.1% | 0.01 | `monotonic increasing point writes`
|
||||||
|
|
||||||
# "Real data" test
|
# "Real data" test
|
||||||
|
|
||||||
@@ -87,13 +87,13 @@ Point queries only, best of three runs. Gc ratio is the ratio of time spent doin
|
|||||||
## skip list
|
## skip list
|
||||||
|
|
||||||
```
|
```
|
||||||
Check: 11.267 seconds, 331.812 MB/s, Add: 5.33323 seconds, 131.635 MB/s, Gc ratio: 45.4671%
|
Check: 11.3385 seconds, 329.718 MB/s, Add: 5.35612 seconds, 131.072 MB/s, Gc ratio: 45.7173%
|
||||||
```
|
```
|
||||||
|
|
||||||
## radix tree
|
## radix tree
|
||||||
|
|
||||||
```
|
```
|
||||||
Check: 2.48508 seconds, 1504.38 MB/s, Add: 2.07295 seconds, 338.666 MB/s, Gc ratio: 42.2825%
|
Check: 2.48583 seconds, 1503.93 MB/s, Add: 2.12768 seconds, 329.954 MB/s, Gc ratio: 41.7943%
|
||||||
```
|
```
|
||||||
|
|
||||||
## hash table
|
## hash table
|
||||||
@@ -101,5 +101,5 @@ Check: 2.48508 seconds, 1504.38 MB/s, Add: 2.07295 seconds, 338.666 MB/s, Gc rat
|
|||||||
(The hash table implementation doesn't work on range queries, and its purpose is to provide an idea of how fast point queries can be)
|
(The hash table implementation doesn't work on range queries, and its purpose is to provide an idea of how fast point queries can be)
|
||||||
|
|
||||||
```
|
```
|
||||||
Check: 1.83931 seconds, 2032.56 MB/s, Add: 0.607861 seconds, 1154.93 MB/s, Gc ratio: 48.7142%
|
Check: 1.83386 seconds, 2038.6 MB/s, Add: 0.601411 seconds, 1167.32 MB/s, Gc ratio: 48.9776%
|
||||||
```
|
```
|
||||||
|
@@ -7,6 +7,7 @@ int main(void) {
|
|||||||
ConflictSet_WriteRange w;
|
ConflictSet_WriteRange w;
|
||||||
ConflictSet_Result result;
|
ConflictSet_Result result;
|
||||||
ConflictSet_ReadRange r;
|
ConflictSet_ReadRange r;
|
||||||
|
int64_t bytes;
|
||||||
w.begin.p = (const uint8_t *)"0000";
|
w.begin.p = (const uint8_t *)"0000";
|
||||||
w.begin.len = 4;
|
w.begin.len = 4;
|
||||||
w.end.len = 0;
|
w.end.len = 0;
|
||||||
@@ -17,6 +18,8 @@ int main(void) {
|
|||||||
r.readVersion = 0;
|
r.readVersion = 0;
|
||||||
ConflictSet_check(cs, &r, &result, 1);
|
ConflictSet_check(cs, &r, &result, 1);
|
||||||
assert(result == ConflictSet_Conflict);
|
assert(result == ConflictSet_Conflict);
|
||||||
|
bytes = ConflictSet_getBytes(cs);
|
||||||
|
assert(bytes > 0);
|
||||||
ConflictSet_destroy(cs);
|
ConflictSet_destroy(cs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -17,4 +17,6 @@ int main(void) {
|
|||||||
r.readVersion = 0;
|
r.readVersion = 0;
|
||||||
cs.check(&r, &result, 1);
|
cs.check(&r, &result, 1);
|
||||||
assert(result == ConflictSet::Conflict);
|
assert(result == ConflictSet::Conflict);
|
||||||
|
int64_t bytes = cs.getBytes();
|
||||||
|
assert(bytes > 0);
|
||||||
}
|
}
|
||||||
|
@@ -26,7 +26,7 @@ limitations under the License.
|
|||||||
* - It's safe to operate on two different ConflictSets in two different
|
* - It's safe to operate on two different ConflictSets in two different
|
||||||
* threads concurrently
|
* threads concurrently
|
||||||
* - It's safe to have multiple threads operating on the same ConflictSet
|
* - It's safe to have multiple threads operating on the same ConflictSet
|
||||||
* concurrently if and only if all threads only call `check`.
|
* concurrently if and only if all threads only call const methods
|
||||||
*/
|
*/
|
||||||
struct __attribute__((__visibility__("default"))) ConflictSet {
|
struct __attribute__((__visibility__("default"))) ConflictSet {
|
||||||
enum Result {
|
enum Result {
|
||||||
@@ -110,7 +110,8 @@ private:
|
|||||||
* - It's safe to operate on two different ConflictSets in two different
|
* - It's safe to operate on two different ConflictSets in two different
|
||||||
* threads concurrently
|
* threads concurrently
|
||||||
* - It's safe to have multiple threads operating on the same ConflictSet
|
* - It's safe to have multiple threads operating on the same ConflictSet
|
||||||
* concurrently if and only if all threads only call `check`.
|
* concurrently if and only if all threads only call functions that accept a
|
||||||
|
* const ConflictSet pointer
|
||||||
*/
|
*/
|
||||||
typedef struct ConflictSet ConflictSet;
|
typedef struct ConflictSet ConflictSet;
|
||||||
|
|
||||||
@@ -150,7 +151,8 @@ typedef struct {
|
|||||||
} ConflictSet_WriteRange;
|
} ConflictSet_WriteRange;
|
||||||
|
|
||||||
/** The result of checking reads[i] is written in results[i] */
|
/** The result of checking reads[i] is written in results[i] */
|
||||||
void ConflictSet_check(ConflictSet *cs, const ConflictSet_ReadRange *reads,
|
void ConflictSet_check(const ConflictSet *cs,
|
||||||
|
const ConflictSet_ReadRange *reads,
|
||||||
ConflictSet_Result *results, int count);
|
ConflictSet_Result *results, int count);
|
||||||
|
|
||||||
/** `writes` must be sorted ascending, and must not have adjacent or
|
/** `writes` must be sorted ascending, and must not have adjacent or
|
||||||
@@ -173,6 +175,6 @@ ConflictSet *ConflictSet_create(int64_t oldestVersion);
|
|||||||
void ConflictSet_destroy(ConflictSet *cs);
|
void ConflictSet_destroy(ConflictSet *cs);
|
||||||
|
|
||||||
/** Returns the total bytes in use by this ConflictSet */
|
/** Returns the total bytes in use by this ConflictSet */
|
||||||
int64_t ConflictSet_getBytes(ConflictSet *cs);
|
int64_t ConflictSet_getBytes(const ConflictSet *cs);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user