Skip to content
Open
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
obj
ext

deploy-run.conf

bin
src
106 changes: 106 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
{
"files.associations": {
"csignal": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"array": "cpp",
"atomic": "cpp",
"hash_map": "cpp",
"hash_set": "cpp",
"strstream": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"bitset": "cpp",
"chrono": "cpp",
"codecvt": "cpp",
"compare": "cpp",
"complex": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"cstdint": "cpp",
"deque": "cpp",
"list": "cpp",
"map": "cpp",
"set": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"future": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"semaphore": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"thread": "cpp",
"cfenv": "cpp",
"cinttypes": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"valarray": "cpp",
"variant": "cpp",
"cassert": "cpp",
"cerrno": "cpp",
"shared_mutex": "cpp",
"__nullptr": "cpp",
"__node_handle": "cpp",
"unordered_set": "cpp",
"span": "cpp",
"regex": "cpp",
"__bit_reference": "cpp",
"__hash_table": "cpp",
"__split_buffer": "cpp",
"__tree": "cpp",
"filesystem": "cpp",
"any": "cpp",
"ios": "cpp",
"charconv": "cpp",
"__bits": "cpp",
"__config": "cpp",
"__debug": "cpp",
"__threading_support": "cpp",
"__tuple": "cpp",
"__verbose_abort": "cpp",
"locale": "cpp",
"queue": "cpp",
"stack": "cpp",
"__functional_base": "cpp",
"__functional_base_03": "cpp",
"__mutex_base": "cpp",
"__string": "cpp"
}
}
2 changes: 1 addition & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Installation

And there are some import parameters you need to edit :
- src/deployment/main.cc, #define HOT ***: Set amount of Hot records for micorbenchmark, it is used to vary contention index (100 means contention index = 0.01);
- src/sequencer/sequencer.h: #define MAX_BATCH_SIZE *** : Set batch size per 10 ms epoch , set it a little bigger than the actually throughput(200 means every second the sequencer creates 20K transactions)
- src/sequencer/sequencer.h: #define MAX_LOCK_BATCH_SIZE *** : Set batch size per 10 ms epoch , set it a little bigger than the actually throughput(200 means every second the sequencer creates 20K transactions)

You should make sure that your LD_LIBRARY_PATH includes the object files noted in the dependencies above. And you need to edit deploy-run.conf to include the machines which Calvin run on(The port should be same with the port in the src/deployment/portfile).

Expand Down
Binary file added bin/deployment/cluster
Binary file not shown.
157 changes: 157 additions & 0 deletions calvin_comparison.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#!/bin/bash

# ==============================================================================
# Calvin 比較実験用スクリプト (96コアサーバー向け)
# ==============================================================================

# --- 比較対象を設定 ('original' または 'proposed') ---
TARGET="proposed" # ここを 'original' に変えて元カルバンを測定

# --- 引数処理 ---
if [ "$1" == "m" ]; then
ARGUMENT="m"
elif [ "$1" == "t" ]; then
ARGUMENT="t"
elif [ "$1" == "y" ]; then
ARGUMENT="y"
else
echo "エラー: 引数が無効です。'm', 't', 'y' のいずれかを使用してください。"
exit 1
fi
echo "🧪 使用するベンチマーク: $ARGUMENT"
echo "🎯 測定対象: $TARGET"

# ========================== 実験パラメータ ==========================
if [ "$TARGET" == "original" ]; then
NUM_BACKGROUND=4
DEFINITIONS_FILE="definitions_original.hh"
SOURCE_DIR="src_calvin" # 元カルバンのソースディレクトリ
OUTPUT_CSV="throughput_summary_${ARGUMENT}_original.csv"
else
# 提案手法 (Dispatcherは1つで実験する例)
NUM_DISPATCHERS=0
OTHER_BACKGROUND_THREADS=4
NUM_BACKGROUND=$((OTHER_BACKGROUND_THREADS + NUM_DISPATCHERS))
DEFINITIONS_FILE="definitions_original.hh"
SOURCE_DIR="src_calvin_ext" # 提案手法のソースディレクトリ
OUTPUT_CSV="throughput_summary_${ARGUMENT}_proposed_d${NUM_DISPATCHERS}.csv"
fi

# ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
# ★★★ ここを修正:96コアサーバー向けにテスト範囲を拡張 ★★★
# ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
THREAD_COUNTS=(1 4 8 16)

# <--- 変更点 No.1: 測定回数を60回に設定 ---
RUN_DURATION=10
NUM_RUNS=4
WARMUP_RUNS=0

# --- 基本設定 ---
SCRIPT_DIR=$(dirname "$0")
cd "$SCRIPT_DIR" || exit 1
CONFIG_FILE="cygnus-run.conf"
BACKUP_CONFIG_FILE="${CONFIG_FILE}.bak"
LOG_FILE="/tmp/calvin_output.log"

# --- 事前準備 ---
rm -f /tmp/failed_log_*.log
cp "$CONFIG_FILE" "$BACKUP_CONFIG_FILE"
echo "✅ 設定ファイルをバックアップ: $BACKUP_CONFIG_FILE"
echo "Threads,Average_Throughput(ops/sec)" > "$OUTPUT_CSV"

# ========================== メインループ ==========================
for THREADS in "${THREAD_COUNTS[@]}"; do
echo -e "\n======== Total Cores for Workers+Dispatchers: $THREADS ========"

# -------- [ここから修正] --------
# THREADS を NUM_WORKERS に設定
NUM_WORKERS=$THREADS
# NUM_CORE を計算 (ワーカー + バックグラウンド)
NUM_CORE=$(($NUM_WORKERS + $NUM_BACKGROUND))
# -------- [ここまで修正] --------

echo " - Configuration: Workers=$NUM_WORKERS, Background=$NUM_BACKGROUND, TotalCores=$NUM_CORE"

# --- ソースコードと定義ファイルの更新 ---
echo " [1/4] ソースコードと定義ファイルを更新中..."
rm -rf src obj
cp -r "$SOURCE_DIR"/ src
cp "$DEFINITIONS_FILE" src/common/definitions.hh

# sedで各種マクロを置換
sed -i -E "s/^#define[[:space:]]+NUM_CORE[[:space:]]+.*$/#define NUM_CORE $NUM_CORE/" src/common/definitions.hh
sed -i -E "s/^#define[[:space:]]+NUM_BACKGROUND_THREADS[[:space:]]+.*$/#define NUM_BACKGROUND_THREADS $NUM_BACKGROUND/" src/common/definitions.hh
sed -i -E "s/^#define[[:space:]]+NUM_WORKERS[[:space:]]+.*$/#define NUM_WORKERS $NUM_WORKERS/" src/common/definitions.hh
if [ "$TARGET" != "original" ]; then
sed -i -E "s/^#define[[:space:]]+NUM_RO_DISPATCHERS[[:space:]]+.*$/#define NUM_RO_DISPATCHERS $NUM_DISPATCHERS/" src/common/definitions.hh
fi
# --- ビルド ---
echo " [2/4] ビルドを実行中..."
cd src
make clean > /dev/null 2>&1
if make -j$(nproc); then
echo " - ビルド成功。"
else
echo " - ❌ ビルド失敗 (Workers=$NUM_WORKERS)。スキップします。"
cd ..
continue
fi
cd ..

# ========================== 測定実行 ==========================
echo " [3/4] 測定を実行中 ($NUM_RUNS 回)..."
THROUGHPUT_ARRAY=()

for i in $(seq 1 $NUM_RUNS); do
./bin/deployment/db 0 "$ARGUMENT" 0 > "$LOG_FILE" 2>&1 &
APP_PID=$!
sleep "$RUN_DURATION"
kill -SIGINT "$APP_PID" 2>/dev/null
wait "$APP_PID" 2>/dev/null
sleep 1
if ps -p $APP_PID > /dev/null; then
kill -SIGKILL "$APP_PID" 2>/dev/null
fi

THROUGHPUT=$(grep -oP 'Completed\s*\K[0-9.]+' "$LOG_FILE" | tail -n 5 | head -n 1 | awk '{print $1}')

# <--- 変更点 No.2: 最初の10回は結果を保存しない ---
if [ "$i" -le "$WARMUP_RUNS" ]; then
echo " - ウォームアップ実行 $i/$NUM_RUNS: 🚀 完了 (結果は破棄)"
elif [ -z "$THROUGHPUT" ]; then
echo " - 測定実行 $i/$NUM_RUNS: ⚠️ スループット抽出失敗"
FAILED_LOG_NAME="/tmp/failed_log_threads_${THREADS}_run_${i}.log"
mv "$LOG_FILE" "$FAILED_LOG_NAME"
echo " (ログを ${FAILED_LOG_NAME} に保存しました)"
else
echo " - 測定実行 $i/$NUM_RUNS: ✅ スループット: $THROUGHPUT ops/sec"
THROUGHPUT_ARRAY+=($THROUGHPUT)
fi
rm -f "$LOG_FILE"
done

# ========================== 結果集計 ==========================
echo " [4/4] 結果を集計中..."
# <--- 変更点 No.3: 集計ロジックを修正 ---
NUM_VALID_RUNS=${#THROUGHPUT_ARRAY[@]}
if [ "$NUM_VALID_RUNS" -gt 0 ]; then
# 配列内のすべての有効なスループットを合計する
TOTAL_THROUGHPUT=0
for t in "${THROUGHPUT_ARRAY[@]}"; do
TOTAL_THROUGHPUT=$(awk "BEGIN {print $TOTAL_THROUGHPUT + $t}")
done

AVERAGE_THROUGHPUT=$(awk "BEGIN {printf \"%.2f\", $TOTAL_THROUGHPUT / $NUM_VALID_RUNS}")
echo "✅ 平均スループット ($THREADS threads): $AVERAGE_THROUGHPUT ops/sec ($NUM_VALID_RUNS 回の有効実行から算出)"
else
AVERAGE_THROUGHPUT="N/A"
echo "⚠️ $THREADS threads の有効な実行がなかったため、平均を計算できませんでした。"
fi
echo "$THREADS,$AVERAGE_THROUGHPUT" >> "$OUTPUT_CSV"
done

# ========================== 後始末 ==========================
mv "$BACKUP_CONFIG_FILE" "$CONFIG_FILE"
echo -e "\n🛠️ 設定ファイルを元に戻しました。"
echo "🎉 全実験完了。結果は $OUTPUT_CSV に保存されました。"
3 changes: 2 additions & 1 deletion ...x/common/configuration_test_one_node.conf → cygnus-run.conf
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# Node<id>=<replica>:<partition>:<cores>:<host>:<port>
node0=0:0:16:128.36.232.50:60001
node0=0:0:8:133.27.19.50:54564

3 changes: 2 additions & 1 deletion ...s/common/configuration_test_one_node.conf → cygnus-run.conf.bak
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# Node<id>=<replica>:<partition>:<cores>:<host>:<port>
node0=0:0:16:128.36.232.50:60001
node0=0:0:8:133.27.19.50:54564

101 changes: 101 additions & 0 deletions definitions_original.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#pragma once

// ============== please don't change ==============
#define COLD_CUTOFF 1000000
#define MAX_LOCK_BATCH_SIZE 2000
#define EPOCH_DURATION 0.01 // 0.01 is 10ms
// =================================================

// ============== 元のCalvin用設定 (NUMA完全分離版) ==============
// ★ バックグラウンドをNode 1 (奇数)、ワーカーをNode 0 (偶数) に分離 ★
// =============================================================

// ============== server setting ==============
#define NUM_CORE 0 // スクリプトで上書き

// --- バックグラウンドスレッドの定義 (4つ) ---
#define NUM_BACKGROUND_THREADS 4
// バックグラウンドをNode 1 (奇数コア) にハードコードで割り当て
#define MULTIPLEXER_CORE 1
#define SEQUENCER_WRITER_CORE 3
#define SEQUENCER_READER_CORE 5
#define LOCK_MANAGER_CORE 7

// --- ワーカーの定義 ---
#define NUM_WORKERS_CORE (NUM_CORE - NUM_BACKGROUND_THREADS)
#define NUM_WORKERS (NUM_WORKERS_CORE)

// -------- [ここから変更] --------

/**
* @brief ワーカーコアを割り当てる関数
* 1. まず、偶数コアを昇順 (0, 2, 4, ...) に割り当てる。
* 2. 偶数コアを使い切ったら (NUM_COREを超えたら)、
* 利用可能な奇数コアを降順 (NUM_CORE-1, NUM_CORE-3, ...) に割り当てる。
* 3. その際、バックグラウンドスレッドが使用するコア (1, 3, 5, 7) は除外する。
*/
inline int GetWorkerCore(int thread_id) {
// 1. 偶数コアを昇順に割り当て
int even_core = thread_id * 2;
if (even_core < NUM_CORE) {
return even_core;
}

// 2. 偶数コアを使い切った場合 (スピルオーバー)
// 利用可能な偶数コアの数を計算
int num_even_cores = (NUM_CORE + 1) / 2;
// 自分は何番目のスピルオーバースレッドか (0-indexed)
int spill_thread_index = thread_id - num_even_cores;

// 3. 利用可能な奇数コアを降順に探す
// NUM_CORE-1 が偶数なら、(NUM_CORE-1)-1 = NUM_CORE-2 から開始
int current_odd_core = (NUM_CORE - 1);
if (current_odd_core % 2 == 0) {
current_odd_core--;
}

int assigned_spill_count = 0;
while (current_odd_core >= 0) {
// バックグラウンドスレッドのコアかチェック
bool is_background_core =
(current_odd_core == MULTIPLEXER_CORE) ||
(current_odd_core == SEQUENCER_WRITER_CORE) ||
(current_odd_core == SEQUENCER_READER_CORE) ||
(current_odd_core == LOCK_MANAGER_CORE);

if (!is_background_core) {
// 利用可能な奇数コアだった
if (assigned_spill_count == spill_thread_index) {
return current_odd_core; // 該当するコアを返す
}
assigned_spill_count++;
}
current_odd_core -= 2; // 次の奇数コアへ (降順)
}

// 割り当て失敗 (NUM_WORKERS の定義が正しければ、ここには来ない)
return -1;
}

// ワーカーをNode 0 (偶数コア) に割り当て
// (ただし、使い切ったら降順の奇数コアにスピルオーバー)
#define GET_WORKER_CORE(thread_id) (GetWorkerCore(thread_id))
// -------- [ここまで変更] --------
// ==============================================

// ============== database setting ==============
#define DB_SIZE 1000000
#define LOCK_TABLE_SIZE 1000000
// ==============================================

// ============== workload setting ==============
#define RW_SET_SIZE 100
#define SKEW 0.99
#define UNIFORM_KEY_SELECTION_RATIO 0
#define HOT 10
// ==============================================

// ============== used for only calvin ==============
#define MAX_ACTIVE_TXNS 2000
#define LOCK_BATCH_SIZE 100
// ==============================================
Loading