Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion cc/ss2pl/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
if(CCBENCH_SS2PL_DLR STREQUAL "0")
set(SS2PL_DLR_MARKER DLR0)
elseif(CCBENCH_SS2PL_DLR STREQUAL "1")
set(SS2PL_DLR_MARKER DLR1)
else()
message(FATAL_ERROR "CCBENCH_SS2PL_DLR must be 0 or 1")
endif()

ccbench_add_protocol(ss2pl
SOURCES transaction.cc util.cc
WORKLOADS ycsb bomb tpcc
OPTIONS
DLR1
${SS2PL_DLR_MARKER}
KEY_SORT=${CCBENCH_KEY_SORT}
)
11 changes: 9 additions & 2 deletions cc/ss2pl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,15 @@ default : `0`
default : `1`
- `VAL_SIZE` : Value of key-value size. In other words, payload size.<br>
default : `4`
- `DLR0` : Dead lock resolution is timeout.
- `DLR1` : Dead lock resolution is no-wait.
- Dead lock resolution is selected at configure time with the
`CCBENCH_SS2PL_DLR` cache variable, which defines exactly one of the
markers below.<br>
default : `1`
- `DLR0` : Timeout. Every record lock acquisition retries until it
succeeds or `-ss2pl_dlr0_timeout_us` elapses; on expiry the transaction
aborts through the same path as a no-wait abort.
- `DLR1` : No-wait. A lock acquisition that cannot succeed immediately
aborts the transaction.

## Optimizations
- Backoff.
Expand Down
9 changes: 9 additions & 0 deletions cc/ss2pl/include/common.hh
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,13 @@ DECLARE_bool(ycsb);
DECLARE_double(zipf_skew);
#endif

#if defined(DLR0)
#ifdef GLOBAL_VALUE_DEFINE
DEFINE_uint64(ss2pl_dlr0_timeout_us, 1000,
"ss2pl DLR0 lock timeout in microseconds.");
#else
DECLARE_uint64(ss2pl_dlr0_timeout_us);
#endif
#endif

alignas(CACHE_LINE_SIZE) GLOBAL uint32_t TotalThreadNum;
49 changes: 49 additions & 0 deletions cc/ss2pl/include/dlr0_timeout.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#pragma once

#if defined(DLR0)

#include <atomic>
#include <cstdint>

#include "../../../include/tsc.hh"
#include "common.hh"

inline bool ss2pl_dlr0_try_read_once(ReaderWriteLock& lock) {
int expected = lock.counter.load(std::memory_order_acquire);
if (expected == -1) return false;

return lock.counter.compare_exchange_strong(expected, expected + 1,
std::memory_order_acq_rel,
std::memory_order_acquire);
}

inline bool ss2pl_dlr0_try_write_once(ReaderWriteLock& lock) {
int expected = lock.counter.load(std::memory_order_acquire);
if (expected != 0) return false;

return lock.counter.compare_exchange_strong(
expected, -1, std::memory_order_acq_rel, std::memory_order_acquire);
}

inline bool ss2pl_dlr0_try_upgrade_once(ReaderWriteLock& lock) {
int expected = lock.counter.load(std::memory_order_acquire);
if (expected != 1) return false;

return lock.counter.compare_exchange_strong(
expected, -1, std::memory_order_acq_rel, std::memory_order_acquire);
}

template <typename TryOnce>
inline bool ss2pl_dlr0_lock_until_timeout(TryOnce&& try_once) {
const std::uint64_t timeout_clocks =
FLAGS_ss2pl_dlr0_timeout_us * FLAGS_clocks_per_us;
const std::uint64_t start = rdtscp();

for (;;) {
if (try_once()) return true;
if (rdtscp() - start >= timeout_clocks) return false;
_mm_pause();
}
}

#endif
58 changes: 41 additions & 17 deletions cc/ss2pl/transaction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#include "../../include/procedure.hh"
#include "../../include/result.hh"
#include "include/common.hh"
#if defined(DLR0)
#include "include/dlr0_timeout.hh"
#endif
#include "include/transaction.hh"

using namespace std;
Expand Down Expand Up @@ -155,6 +158,11 @@ Status TxExecutor::read(Storage s, std::string_view key, TupleBody** body) {
if (tuple == nullptr) return Status::WARN_NOT_FOUND;

read_internal(s, key, tuple);
#if defined(DLR0)
if (this->status_ == TransactionStatus::aborted) {
return Status::ERROR_LOCK_FAILED;
}
#endif
*body = &(read_set_.back().body_);

FINISH_READ:
Expand All @@ -169,11 +177,12 @@ void TxExecutor::read_internal(Storage s, std::string_view key, Tuple* tuple) {

if (reconnoitering_) goto FINISH_READ_LOCK;

#ifdef DLR0
/**
* Acquire lock with wait.
*/
tuple->lock_.r_lock();
#if defined(DLR0)
if (!ss2pl_dlr0_lock_until_timeout(
[&]() { return ss2pl_dlr0_try_read_once(tuple->lock_); })) {
this->status_ = TransactionStatus::aborted;
goto FINISH_READ;
}
r_lock_list_.emplace_back(&tuple->lock_);
#elif defined(DLR1)
if (tuple->lock_.r_trylock()) {
Expand Down Expand Up @@ -260,9 +269,10 @@ Status TxExecutor::update(Storage s, std::string_view key, TupleBody&& body) {
for (auto rItr = read_set_.begin(); rItr != read_set_.end(); ++rItr) {
if ((*rItr).storage_ != s) continue;
if ((*rItr).key_ == key) { // hit
#if DLR0
// Workaround for handling static BoMB properly
if (!(*rItr).rcdptr_->lock_.tryupgrade()) {
#if defined(DLR0)
if (!ss2pl_dlr0_lock_until_timeout([&]() {
return ss2pl_dlr0_try_upgrade_once((*rItr).rcdptr_->lock_);
})) {
this->status_ = TransactionStatus::aborted;
goto FINISH_WRITE;
}
Expand Down Expand Up @@ -306,11 +316,12 @@ Status TxExecutor::update(Storage s, std::string_view key, TupleBody&& body) {
#endif
if (tuple == nullptr) return Status::WARN_NOT_FOUND;

#if DLR0
/**
* Lock with wait.
*/
tuple->lock_.w_lock();
#if defined(DLR0)
if (!ss2pl_dlr0_lock_until_timeout(
[&]() { return ss2pl_dlr0_try_write_once(tuple->lock_); })) {
this->status_ = TransactionStatus::aborted;
goto FINISH_WRITE;
}
#elif defined(DLR1)
if (!tuple->lock_.w_trylock()) {
/**
Expand All @@ -331,6 +342,11 @@ Status TxExecutor::update(Storage s, std::string_view key, TupleBody&& body) {
#if ADD_ANALYSIS
result_->local_write_latency_ += rdtscp() - start;
#endif // ADD_ANALYSIS
#if defined(DLR0)
if (this->status_ == TransactionStatus::aborted) {
return Status::ERROR_LOCK_FAILED;
}
#endif
return Status::OK;
}

Expand Down Expand Up @@ -408,8 +424,12 @@ Status TxExecutor::read_lock(Storage s, std::string_view key) {
if (w_lock == &tuple->lock_) { return Status::OK; }
}

#ifdef DLR0
tuple->lock_.r_lock();
#if defined(DLR0)
if (!ss2pl_dlr0_lock_until_timeout(
[&]() { return ss2pl_dlr0_try_read_once(tuple->lock_); })) {
this->status_ = TransactionStatus::aborted;
return Status::ERROR_LOCK_FAILED;
}
#elif defined(DLR1)
if (!tuple->lock_.r_trylock()) {
this->status_ = TransactionStatus::aborted;
Expand All @@ -433,8 +453,12 @@ Status TxExecutor::write_lock(Storage s, std::string_view key) {
if (w_lock == &tuple->lock_) { return Status::OK; }
}

#if DLR0
tuple->lock_.w_lock();
#if defined(DLR0)
if (!ss2pl_dlr0_lock_until_timeout(
[&]() { return ss2pl_dlr0_try_write_once(tuple->lock_); })) {
this->status_ = TransactionStatus::aborted;
return Status::ERROR_LOCK_FAILED;
}
#elif defined(DLR1)
if (!tuple->lock_.w_trylock()) {
this->status_ = TransactionStatus::aborted;
Expand Down
12 changes: 12 additions & 0 deletions cc/ss2pl/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ void chkArg() {

if (FLAGS_rratio > 100) { ERR; }

#if defined(DLR0)
if (FLAGS_clocks_per_us == 0 ||
FLAGS_ss2pl_dlr0_timeout_us >
std::numeric_limits<std::uint64_t>::max() / FLAGS_clocks_per_us) {
ERR;
}
#endif

TotalThreadNum = FLAGS_thread_num;

if (FLAGS_clocks_per_us < 100) {
Expand All @@ -50,6 +58,10 @@ void displayParameter() {
cout << "#FLAGS_tuple_num:\t" << FLAGS_tuple_num << endl;
cout << "#FLAGS_ycsb:\t\t" << FLAGS_ycsb << endl;
cout << "#FLAGS_zipf_skew:\t" << FLAGS_zipf_skew << endl;
#if defined(DLR0)
cout << "#FLAGS_ss2pl_dlr0_timeout_us:\t" << FLAGS_ss2pl_dlr0_timeout_us
<< endl;
#endif
}

void partTableInit([[maybe_unused]] size_t thid,
Expand Down
1 change: 1 addition & 0 deletions cmake/Options.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ set(CCBENCH_PROCEDURE_SORT 0 CACHE STRING "silo")
set(CCBENCH_WAL 0 CACHE STRING "silo")
set(CCBENCH_TEMPERATURE_RESET_OPT 1 CACHE STRING "mocc")
set(CCBENCH_WORKER1_INSERT_DELAY_RPHASE 0 CACHE STRING "cicada")
set(CCBENCH_SS2PL_DLR 1 CACHE STRING "ss2pl: 0=timeout, 1=no-wait")

# Cicada and Oze share many flags but disagree on this one's default.
# Keep two separate cache entries; protocols pick the one they want.
Expand Down
11 changes: 11 additions & 0 deletions docs/runtime-args_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ BoMB has many knobs; the ones below are the most common. See
| `-bomb_use_cache` | `false` | Use cached BoM tree (static setting). |
| `-bomb_rate_control` | `false` | Enable rate-limited request injection. |

## SS2PL-specific flags (`*_ss2pl.exe`, only when built with `CCBENCH_SS2PL_DLR=0`)

The deadlock resolution strategy is chosen at configure time with
`-DCCBENCH_SS2PL_DLR=<0|1>`. The default is `1` (no-wait), which is the
historical behaviour. Only a binary built with `0` (timeout) accepts the flag
below.

| Flag | Default | Meaning |
|---|---|---|
| `-ss2pl_dlr0_timeout_us` | `1000` | Upper bound, in microseconds, on how long a single record lock acquisition waits. The transaction aborts when it expires. The bound is converted to TSC ticks with `-clocks_per_us`, so that value has to be correct. |

## Examples

TPC-C on Silo with 8 warehouses:
Expand Down
10 changes: 10 additions & 0 deletions docs/runtime-args_ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ BoMB には多くの knob がある。下記はよく使うものだけ。ワー
| `-bomb_use_cache` | `false` | キャッシュ済みの BoM tree を使う (静的設定)。 |
| `-bomb_rate_control` | `false` | レート制限付きの request injection を有効化。 |

## SS2PL 固有のフラグ (`*_ss2pl.exe`、`CCBENCH_SS2PL_DLR=0` でビルドしたときだけ)

デッドロック解決方式は configure 時に `-DCCBENCH_SS2PL_DLR=<0|1>` で選ぶ。既定は `1`
(no-wait) で、これは従来の挙動である。`0` (timeout) でビルドしたバイナリだけが下記の
フラグを受け付ける。

| Flag | デフォルト | 意味 |
|---|---|---|
| `-ss2pl_dlr0_timeout_us` | `1000` | 1 回のレコードロック取得を待つ上限 (マイクロ秒)。到達するとトランザクションを abort する。`-clocks_per_us` を使って TSC tick へ換算するので、その値が正しいことが前提。 |

## 例

8 warehouse で Silo の TPC-C:
Expand Down