├── .gitignore ├── data ├── plots │ ├── .gitignore │ ├── exp_helpers.py │ ├── ethplot.mplstyle │ ├── locking-throughput-new.py │ ├── abortion-rate-warehouses.py │ ├── network-delay.py │ ├── transaction-throughput-warehouses.py │ ├── transaction-throughput-new.py │ └── tx-breakdown.py ├── .gitignore ├── requirements.txt ├── processing │ ├── exp_helpers.py │ ├── locking-throughput.py │ ├── tx-breakdown.py │ └── transaction-throughput.py ├── exp2json.py ├── collect_data.sh ├── collect_data_paper.sh ├── jsonl2hdf5.py ├── README.md └── _exp_helpers.py ├── HumongousLock ├── .gitignore ├── src │ └── hdb │ │ ├── messages │ │ ├── MessageSlot.cpp │ │ ├── Shutdown.cpp │ │ ├── AbortTransaction.cpp │ │ ├── VoteRequest.cpp │ │ ├── TransactionEnd.cpp │ │ ├── Shutdown.h │ │ ├── MessageSlot.h │ │ ├── LockRelease.cpp │ │ ├── AbortTransaction.h │ │ ├── VoteRequest.h │ │ ├── Message.cpp │ │ ├── TransactionEnd.h │ │ ├── LockRelease.h │ │ ├── LockGrant.cpp │ │ ├── Message.h │ │ ├── LockGrant.h │ │ ├── MessageUtils.h │ │ ├── LockRequest.h │ │ └── LockRequest.cpp │ │ ├── transactions │ │ ├── Transaction.cpp │ │ ├── SimpleClient.h │ │ ├── ReplayClient.h │ │ ├── TransactionAgent.h │ │ ├── Transaction.h │ │ ├── TransactionManager.h │ │ ├── SimpleClient.cpp │ │ ├── TransactionAgent.cpp │ │ ├── ReplayClient.cpp │ │ └── TransactionManager.cpp │ │ ├── utils │ │ └── Debug.h │ │ ├── locktable │ │ ├── LockTableAgent.h │ │ ├── LockMode.h │ │ ├── LockTableAgent.cpp │ │ ├── Lock.h │ │ └── Table.h │ │ ├── communication │ │ ├── SendReceiveCommunicator.h │ │ ├── VoteCommunicator.h │ │ ├── NotifiedCommunicator.h │ │ ├── HybridCommunicator.h │ │ ├── Communicator.h │ │ ├── DataLayer.h │ │ ├── Communicator.cpp │ │ ├── SendReceiveCommunicator.cpp │ │ ├── VoteCommunicator.cpp │ │ ├── NotifiedCommunicator.cpp │ │ └── HybridCommunicator.cpp │ │ ├── configuration │ │ └── SystemConfig.h │ │ └── stats │ │ ├── ClientStats.h │ │ └── ClientStats.cpp └── Makefile ├── workload-traces ├── mysql │ ├── tpcc │ │ ├── make_trace │ │ │ ├── .gitignore │ │ │ ├── .clang-format │ │ │ └── src │ │ │ │ ├── CMakeLists.txt │ │ │ │ └── main.cpp │ │ ├── analyse.py │ │ ├── generate_lock_ids.py │ │ ├── extract_lock_names.py │ │ ├── split_locks_by_warehouse.py │ │ ├── extract_events.py │ │ ├── segmentize.py │ │ ├── parse.py │ │ └── parse_segment.py │ ├── 3rdparty │ │ ├── .gitignore │ │ ├── download-tpcc-mysql.sh │ │ └── download-mysql-server.sh │ └── my.cnf └── README.md ├── foMPI-NA-0.2.4.tar.gz ├── .gitmodules ├── preprocess.template ├── README.md ├── LICENSE ├── reproducability_daint.sh ├── compile_daint.sh ├── job.template ├── test_general_mpi.sh ├── run_general_mpi.sh ├── test_cray_mpi.sh ├── run_cray_mpi.sh └── generate_batch_job.sh /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | -------------------------------------------------------------------------------- /data/plots/.gitignore: -------------------------------------------------------------------------------- 1 | *.csv 2 | *.pdf 3 | -------------------------------------------------------------------------------- /data/.gitignore: -------------------------------------------------------------------------------- 1 | /data.hdf5 2 | /data.json 3 | -------------------------------------------------------------------------------- /HumongousLock/.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /release/ 3 | -------------------------------------------------------------------------------- /workload-traces/mysql/tpcc/make_trace/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /workload-traces/mysql/3rdparty/.gitignore: -------------------------------------------------------------------------------- 1 | /mysql-server 2 | /tpcc-mysql 3 | -------------------------------------------------------------------------------- /data/requirements.txt: -------------------------------------------------------------------------------- 1 | matplotlib 2 | palettable 3 | pandas 4 | scipy 5 | seaborn 6 | tables 7 | -------------------------------------------------------------------------------- /foMPI-NA-0.2.4.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spcl/vldb19-distributed-locking/HEAD/foMPI-NA-0.2.4.tar.gz -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "3rdparty/rapidjson"] 2 | path = 3rdparty/rapidjson 3 | url = https://github.com/miloyip/rapidjson 4 | -------------------------------------------------------------------------------- /data/plots/exp_helpers.py: -------------------------------------------------------------------------------- 1 | import os, sys 2 | 3 | sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) 4 | 5 | from _exp_helpers import * 6 | -------------------------------------------------------------------------------- /data/processing/exp_helpers.py: -------------------------------------------------------------------------------- 1 | import os, sys 2 | 3 | sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) 4 | 5 | from _exp_helpers import * 6 | -------------------------------------------------------------------------------- /workload-traces/mysql/tpcc/analyse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from sys import stdin 4 | import pandas as pd 5 | 6 | df = pd.read_json(stdin, lines=True) 7 | 8 | trx_df = df.groupby('trx_id').agg({ 'partition_no': ['count', 'nunique'] }).reset_index() 9 | 10 | print(trx_df) 11 | -------------------------------------------------------------------------------- /workload-traces/mysql/tpcc/make_trace/.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: Google 4 | AccessModifierOffset: -2 5 | BreakBeforeBraces: Allman 6 | IndentWidth: 4 7 | TabWidth: 8 8 | UseTab: Never 9 | ContinuationIndentWidth: 8 10 | ... 11 | 12 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/MessageSlot.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MessageSlot.cpp 3 | * 4 | * Created on: Apr 16, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace hdb { 13 | namespace messages { 14 | 15 | 16 | 17 | } /* namespace messages */ 18 | } /* namespace hdb */ 19 | -------------------------------------------------------------------------------- /workload-traces/mysql/3rdparty/download-tpcc-mysql.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | SCRIPTDIR="$(dirname "$(readlink -f "$0")")" 7 | 8 | ( 9 | mkdir "$SCRIPTDIR/tpcc-mysql" 10 | cd "$SCRIPTDIR/tpcc-mysql" 11 | wget https://github.com/Percona-Lab/tpcc-mysql/archive/1ec1c5.tar.gz -O - | \ 12 | tar -xz --strip-components=1 13 | patch -p1 < ../tpcc-mysql.patch 14 | ) 15 | -------------------------------------------------------------------------------- /workload-traces/mysql/3rdparty/download-mysql-server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | SCRIPTDIR="$(dirname "$(readlink -f "$0")")" 7 | 8 | ( 9 | mkdir "$SCRIPTDIR/mysql-server" 10 | cd "$SCRIPTDIR/mysql-server" 11 | wget https://github.com/mysql/mysql-server/archive/mysql-5.6.27.tar.gz -O - | \ 12 | tar -xz --strip-components=1 13 | patch -p1 < ../mysql-server.patch 14 | ) 15 | -------------------------------------------------------------------------------- /workload-traces/mysql/tpcc/generate_lock_ids.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import json 5 | import argparse 6 | 7 | # Setup parser for command line arguments 8 | parser = argparse.ArgumentParser() 9 | parser.add_argument('offset', type=int) 10 | args = parser.parse_args() 11 | 12 | i = 0 13 | 14 | for line in sys.stdin: 15 | data = json.loads(line) 16 | data['lock_id'] = i + args.offset 17 | i += 1 18 | print(json.dumps(data)) 19 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/transactions/Transaction.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Transaction.cpp 3 | * 4 | * Created on: Apr 18, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include "Transaction.h" 9 | 10 | namespace hdb { 11 | namespace transactions { 12 | 13 | Transaction::Transaction(hdb::transactions::DataMode transactionTypeId) { 14 | this->transactionTypeId = transactionTypeId; 15 | } 16 | 17 | 18 | } /* namespace transactions */ 19 | } /* namespace hdb */ 20 | 21 | 22 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/Shutdown.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Shutdown.cpp 3 | * 4 | * Created on: Apr 17, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include 9 | 10 | namespace hdb { 11 | namespace messages { 12 | 13 | Shutdown::Shutdown(uint32_t clientGlobalRank) : Message(SHUTDOWN_MESSAGE, sizeof(Shutdown), clientGlobalRank, 0) { 14 | 15 | } 16 | 17 | Shutdown::~Shutdown() { 18 | 19 | } 20 | 21 | } /* namespace messages */ 22 | } /* namespace hdb */ 23 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/AbortTransaction.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * AbortTransaction.cpp 3 | * 4 | */ 5 | 6 | #include 7 | 8 | namespace hdb { 9 | namespace messages { 10 | 11 | AbortTransaction::AbortTransaction(uint32_t clientGlobalRank, uint64_t transactionNumber) : Message(TX_ABORT_MESSAGE, sizeof(AbortTransaction), clientGlobalRank, transactionNumber) { 12 | 13 | } 14 | 15 | AbortTransaction::~AbortTransaction() { 16 | 17 | } 18 | 19 | } /* namespace messages */ 20 | } /* namespace hdb */ 21 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/VoteRequest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * VoteRequest.cpp 3 | * 4 | * Created on: Apr 17, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include "VoteRequest.h" 9 | 10 | namespace hdb { 11 | namespace messages { 12 | 13 | VoteRequest::VoteRequest(uint32_t clientGlobalRank, uint64_t transactionNumber) : Message(VOTE_REQUEST_MESSAGE, sizeof(VoteRequest), clientGlobalRank, transactionNumber) { 14 | 15 | } 16 | 17 | VoteRequest::~VoteRequest() { 18 | 19 | } 20 | 21 | } /* namespace messages */ 22 | } /* namespace hdb */ 23 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/TransactionEnd.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TransactionEnd.cpp 3 | * 4 | * Created on: Apr 17, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include 9 | 10 | namespace hdb { 11 | namespace messages { 12 | 13 | TransactionEnd::TransactionEnd(uint32_t clientGlobalRank, uint64_t transactionNumber) : Message(TX_END_MESSAGE, sizeof(TransactionEnd), clientGlobalRank, transactionNumber) { 14 | 15 | } 16 | 17 | TransactionEnd::~TransactionEnd() { 18 | 19 | } 20 | 21 | } /* namespace messages */ 22 | } /* namespace hdb */ 23 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/Shutdown.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Shutdown.h 3 | * 4 | * Created on: Apr 17, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_MESSAGES_SHUTDOWN_H_ 9 | #define SRC_HDB_MESSAGES_SHUTDOWN_H_ 10 | 11 | #include 12 | 13 | #include 14 | 15 | namespace hdb { 16 | namespace messages { 17 | 18 | class Shutdown : public Message { 19 | 20 | public: 21 | 22 | Shutdown(uint32_t clientGlobalRank); 23 | virtual ~Shutdown(); 24 | }; 25 | 26 | } /* namespace messages */ 27 | } /* namespace hdb */ 28 | 29 | #endif /* SRC_HDB_MESSAGES_SHUTDOWN_H_ */ 30 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/MessageSlot.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MessageSlot.h 3 | * 4 | * Created on: Apr 16, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_MESSAGES_MESSAGESLOT_H_ 9 | #define SRC_HDB_MESSAGES_MESSAGESLOT_H_ 10 | 11 | #include 12 | 13 | #include 14 | 15 | namespace hdb { 16 | namespace messages { 17 | 18 | struct MessageSlot { 19 | uint64_t valid; 20 | char data[MAX_MESSAGE_SIZE]; 21 | 22 | } __attribute__((aligned(64))); 23 | 24 | } /* namespace messages */ 25 | } /* namespace hdb */ 26 | 27 | #endif /* SRC_HDB_MESSAGES_MESSAGESLOT_H_ */ 28 | -------------------------------------------------------------------------------- /preprocess.template: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | agents=16 3 | nodenum=$NODES 4 | codelocation=$EXECUTABLE 5 | 6 | declare -a workloads=($WORKLOADS) 7 | 8 | 9 | for workload in "${workloads[@]}"; do 10 | 11 | wlloc="$DATADIR/${workload}/" 12 | locksperwh=$(cat ${wlloc}/max-locks-per-wh.meta | grep -oP '^[^0-9]*\K[0-9]+') 13 | numwhs=$(ls ${wlloc}/*.csv | sed 's!.*/!!' | grep -o -E '[0-9]+' | sort -nr | head -1 | sed 's/^0*//') 14 | 15 | $codelocation --warehouses=${numwhs} --processespernode=${agents} --locksperwh=${locksperwh} --localworkloadsize=1000000 --workloadlocation=${wlloc} --numberofnodes=${nodenum} 16 | 17 | done 18 | 19 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/LockRelease.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * LockRelease.cpp 3 | * 4 | * Created on: Apr 17, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include "LockRelease.h" 9 | 10 | namespace hdb { 11 | namespace messages { 12 | 13 | LockRelease::LockRelease(uint32_t clientGlobalRank, uint64_t transactionNumber, uint64_t lockId) : Message(LOCK_RELEASE_MESSAGE, sizeof(LockRelease), clientGlobalRank, transactionNumber) { 14 | 15 | this->lockId = lockId; 16 | 17 | } 18 | 19 | LockRelease::~LockRelease() { 20 | // TODO Auto-generated destructor stub 21 | } 22 | 23 | } /* namespace messages */ 24 | } /* namespace hdb */ 25 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/AbortTransaction.h: -------------------------------------------------------------------------------- 1 | /* 2 | * AbortTransaction.h 3 | * 4 | */ 5 | 6 | #ifndef SRC_HDB_MESSAGES_ABORTTRANSACTION_H_ 7 | #define SRC_HDB_MESSAGES_ABORTTRANSACTION_H_ 8 | 9 | #include 10 | 11 | #include 12 | 13 | namespace hdb { 14 | namespace messages { 15 | 16 | class AbortTransaction : public Message { 17 | 18 | public: 19 | 20 | AbortTransaction(uint32_t clientGlobalRank = 0, uint64_t transactionNumber = 0); 21 | virtual ~AbortTransaction(); 22 | 23 | }; 24 | 25 | } /* namespace messages */ 26 | } /* namespace hdb */ 27 | 28 | #endif /* SRC_HDB_MESSAGES_ABORTTRANSACTION_H_ */ 29 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/VoteRequest.h: -------------------------------------------------------------------------------- 1 | /* 2 | * VoteRequest.h 3 | * 4 | * Created on: Apr 17, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_MESSAGES_VOTEREQUEST_H_ 9 | #define SRC_HDB_MESSAGES_VOTEREQUEST_H_ 10 | 11 | #include 12 | 13 | #include 14 | 15 | namespace hdb { 16 | namespace messages { 17 | 18 | class VoteRequest : public Message { 19 | 20 | public: 21 | 22 | VoteRequest(uint32_t clientGlobalRank = 0, uint64_t transactionNumber = 0); 23 | virtual ~VoteRequest(); 24 | 25 | }; 26 | 27 | } /* namespace messages */ 28 | } /* namespace hdb */ 29 | 30 | #endif /* SRC_HDB_MESSAGES_VOTEREQUEST_H_ */ 31 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/Message.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Message.cpp 3 | * 4 | * Created on: Mar 26, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include "Message.h" 9 | 10 | namespace hdb { 11 | namespace messages { 12 | 13 | Message::Message(MessageType messageType, uint32_t messageSize, uint32_t clientGlobalRank, uint64_t transactionNumber) { 14 | 15 | this->messageType = messageType; 16 | this->messageSize = messageSize; 17 | this->clientGlobalRank = clientGlobalRank; 18 | this->transactionNumber = transactionNumber; 19 | 20 | } 21 | 22 | Message::~Message() { 23 | // TODO Auto-generated destructor stub 24 | } 25 | 26 | } /* namespace messages */ 27 | } /* namespace hdb */ 28 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/TransactionEnd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TransactionEnd.h 3 | * 4 | * Created on: Apr 17, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_MESSAGES_TRANSACTIONEND_H_ 9 | #define SRC_HDB_MESSAGES_TRANSACTIONEND_H_ 10 | 11 | #include 12 | 13 | #include 14 | 15 | namespace hdb { 16 | namespace messages { 17 | 18 | class TransactionEnd : public Message { 19 | 20 | public: 21 | 22 | TransactionEnd(uint32_t clientGlobalRank = 0, uint64_t transactionNumber = 0); 23 | virtual ~TransactionEnd(); 24 | 25 | }; 26 | 27 | } /* namespace messages */ 28 | } /* namespace hdb */ 29 | 30 | #endif /* SRC_HDB_MESSAGES_TRANSACTIONEND_H_ */ 31 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/LockRelease.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LockRelease.h 3 | * 4 | * Created on: Apr 17, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_MESSAGES_LOCKRELEASE_H_ 9 | #define SRC_HDB_MESSAGES_LOCKRELEASE_H_ 10 | 11 | #include 12 | 13 | #include 14 | 15 | namespace hdb { 16 | namespace messages { 17 | 18 | class LockRelease : public Message { 19 | 20 | public: 21 | 22 | LockRelease(uint32_t clientGlobalRank, uint64_t transactionNumber, uint64_t lockId); 23 | virtual ~LockRelease(); 24 | 25 | public: 26 | 27 | uint64_t lockId; 28 | }; 29 | 30 | } /* namespace messages */ 31 | } /* namespace hdb */ 32 | 33 | #endif /* SRC_HDB_MESSAGES_LOCKRELEASE_H_ */ 34 | -------------------------------------------------------------------------------- /workload-traces/mysql/tpcc/extract_lock_names.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import fileinput 4 | import json 5 | from collections import OrderedDict 6 | 7 | locks = set() 8 | 9 | for line in fileinput.input(): 10 | data = json.loads(line) 11 | 12 | # Get only lock events 13 | if data.get('action') not in ['lock', 'unlock']: 14 | continue 15 | 16 | # Insert ware house where missing (home ware house by default) 17 | ware_house = data['ware_house'] if 'ware_house' in data else data['home_ware_house'] 18 | ware_house = int(ware_house) 19 | 20 | locks.add((ware_house, data['object_name'])) 21 | 22 | for l in locks: 23 | data = OrderedDict([('ware_house', l[0]), ('object_name', l[1])]) 24 | print(json.dumps(data)) 25 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/utils/Debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Debug.h 3 | * 4 | * Created on: Apr 19, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_UTILS_DEBUG_H_ 9 | #define SRC_HDB_UTILS_DEBUG_H_ 10 | 11 | #include 12 | 13 | #ifdef DEBUG 14 | #define DLOG(A, B, ...) { \ 15 | fprintf(stdout, "["); \ 16 | fprintf(stdout, A); \ 17 | fprintf(stdout, "] "); \ 18 | fprintf(stdout, B, ##__VA_ARGS__); \ 19 | fprintf(stdout, "\n"); \ 20 | fflush(stdout); \ 21 | } 22 | #else 23 | #define DLOG(A, B, ...) {} 24 | #endif 25 | 26 | #define DLOG_ALWAYS(A, B, ...) { \ 27 | fprintf(stdout, "["); \ 28 | fprintf(stdout, A); \ 29 | fprintf(stdout, "] "); \ 30 | fprintf(stdout, B, ##__VA_ARGS__); \ 31 | fprintf(stdout, "\n"); \ 32 | fflush(stdout); \ 33 | } 34 | 35 | #endif /* SRC_HDB_UTILS_DEBUG_H_ */ 36 | -------------------------------------------------------------------------------- /data/exp2json.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import json 5 | 6 | parser = argparse.ArgumentParser(description='Convert experiment output (.exp) to json format.') 7 | parser.add_argument('-i', '--input', help='Input .exp file') 8 | parser.add_argument('-c', '--common', type=str, default='{}', 9 | help='JSON object with common keys for the whole file.') 10 | args = parser.parse_args() 11 | 12 | d = None 13 | with open(args.input, 'r') as f: 14 | for line in f: 15 | if line.strip() == '####': 16 | if d is not None: 17 | print(json.dumps(d)) 18 | d = json.loads(args.common) 19 | d['__filename'] = args.input 20 | else: 21 | k, v = line.strip().split() 22 | d[k] = v 23 | if d is not None: 24 | print(json.dumps(d)) 25 | -------------------------------------------------------------------------------- /workload-traces/mysql/tpcc/split_locks_by_warehouse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import json 5 | import gzip 6 | import sys 7 | 8 | # Setup parser for command line arguments 9 | parser = argparse.ArgumentParser() 10 | parser.add_argument('prefix') 11 | args = parser.parse_args() 12 | 13 | outputfile = gzip.open('/dev/null') 14 | current_warehouse = None 15 | 16 | with open('{0}.split-locks'.format(args.prefix), 'w') as f: 17 | f.write('') 18 | 19 | for line in sys.stdin: 20 | data = json.loads(line) 21 | warehouse = data['ware_house'] 22 | if warehouse != current_warehouse: 23 | outputfile.close() 24 | outputname = '{0}-wh{1:06}.json.gz'.format(args.prefix, warehouse) 25 | outputfile = gzip.open(outputname, mode='wt') 26 | current_warehouse = warehouse 27 | outputfile.write(line) 28 | 29 | outputfile.close() 30 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/LockGrant.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * LockGrant.cpp 3 | * 4 | * Created on: Apr 17, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include "LockGrant.h" 9 | 10 | namespace hdb { 11 | namespace messages { 12 | 13 | LockGrant::LockGrant(uint32_t clientGlobalRank, uint64_t transactionNumber, uint64_t lockId, hdb::locktable::LockMode mode, bool granted) : Message(LOCK_GRANT_MESSAGE, sizeof(LockGrant), clientGlobalRank, transactionNumber) { 14 | 15 | this->lockId = lockId; 16 | this->mode = mode; 17 | this->granted = granted; 18 | 19 | #ifdef USE_LOGGING 20 | this->clientSendTime = 0; 21 | this->serverReceiveTime = 0; 22 | this->serverEnqueueTime = 0; 23 | this->serverDequeueTime = 0; 24 | this->serverSendTime = 0; 25 | this->clientReceiveTime = 0; 26 | #endif 27 | 28 | } 29 | 30 | LockGrant::~LockGrant() { 31 | 32 | } 33 | 34 | } /* namespace messages */ 35 | } /* namespace hdb */ 36 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/Message.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Message.h 3 | * 4 | * Created on: Mar 26, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_MESSAGES_MESSAGE_H_ 9 | #define SRC_HDB_MESSAGES_MESSAGE_H_ 10 | 11 | #include 12 | 13 | namespace hdb { 14 | namespace messages { 15 | 16 | enum MessageType { 17 | 18 | LOCK_REQUEST_MESSAGE = 1, 19 | LOCK_GRANT_MESSAGE = 2, 20 | LOCK_RELEASE_MESSAGE = 3, 21 | VOTE_REQUEST_MESSAGE = 4, 22 | TX_END_MESSAGE = 5, 23 | SHUTDOWN_MESSAGE = 6, 24 | TX_ABORT_MESSAGE = 7 25 | 26 | }; 27 | 28 | class Message { 29 | public: 30 | 31 | Message(MessageType messageType, uint32_t messageSize, uint32_t clientGlobalRank, uint64_t transactionNumber); 32 | virtual ~Message(); 33 | 34 | public: 35 | // bool valid; 36 | MessageType messageType; 37 | 38 | public: 39 | 40 | uint32_t clientGlobalRank; 41 | uint32_t messageSize; 42 | uint64_t transactionNumber; 43 | 44 | }; 45 | 46 | } /* namespace messages */ 47 | } /* namespace hdb */ 48 | 49 | #endif /* SRC_HDB_MESSAGES_MESSAGE_H_ */ 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Humongous Lock 2 | 3 | Implementation of concurrency control mechanisms on a large-scale compute infrastructure on several thousand processor cores. 4 | 5 | This repository hosts the code used for the following paper: 6 | Claude Barthels, Ingo Müller, Konstantin Taranov, Torsten Hoefler, Gustavo Alonso. "Strong consistency is not hard to get: Two-Phase Locking and Two-Phase Commit on Thousands of Cores." In: PVLDB, 2020. [[DOI](https://doi.org/10.14778/3358701.3358702)] 7 | 8 | It consists of three parts: 9 | 1. Instrumentialized MySQL, TPC-C driver to produce workload traces: [`workload-traces/`](workload-traces/README.md) 10 | 1. MPI-based prototype implementations of distributed concurrency control mechanisms: [INSTALL.md](INSTALL.md) 11 | 1. Analysis and plotting scripts for the experiment results: [`data/`](data/README.md) 12 | 13 | ## Git submodules 14 | 15 | Clone this repository using `git clone --recursive ` or run the following commands after cloning: 16 | 17 | ```bash 18 | git submodule init 19 | git submodule update 20 | ``` 21 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/transactions/SimpleClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SimpleClient.h 3 | * 4 | * Created on: Apr 19, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_TRANSACTIONS_SIMPLECLIENT_H_ 9 | #define SRC_HDB_TRANSACTIONS_SIMPLECLIENT_H_ 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | namespace hdb { 17 | namespace transactions { 18 | 19 | class SimpleClient : public TransactionAgent { 20 | 21 | public: 22 | 23 | SimpleClient(hdb::configuration::SystemConfig *config, uint64_t numberOfTransactions, uint64_t numberOfLocksPerTransaction, uint32_t remoteprob); 24 | virtual ~SimpleClient(); 25 | 26 | public: 27 | 28 | void generate(); 29 | void execute(); 30 | 31 | protected: 32 | uint32_t remoteprob; 33 | uint32_t tableRangeStart; 34 | uint32_t NumberOfLocksOnThisMachine; 35 | uint64_t numberOfTransactions; 36 | uint64_t numberOfLocksPerTransaction; 37 | 38 | }; 39 | 40 | } /* namespace transactions */ 41 | } /* namespace hdb */ 42 | 43 | #endif /* SRC_HDB_TRANSACTIONS_SIMPLECLIENT_H_ */ 44 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/LockGrant.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LockGrant.h 3 | * 4 | * Created on: Apr 17, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_MESSAGES_LOCKGRANT_H_ 9 | #define SRC_HDB_MESSAGES_LOCKGRANT_H_ 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | namespace hdb { 17 | namespace messages { 18 | 19 | class LockGrant : public Message { 20 | public: 21 | 22 | LockGrant(uint32_t clientGlobalRank, uint64_t transactionNumber, uint64_t lockId, hdb::locktable::LockMode mode, bool granted = true); 23 | virtual ~LockGrant(); 24 | 25 | public: 26 | 27 | uint64_t lockId; 28 | hdb::locktable::LockMode mode; 29 | bool granted; 30 | 31 | #ifdef USE_LOGGING 32 | public: 33 | 34 | uint64_t clientSendTime; 35 | uint64_t serverReceiveTime; 36 | uint64_t serverEnqueueTime; 37 | uint64_t serverDequeueTime; 38 | uint64_t serverSendTime; 39 | uint64_t clientReceiveTime; 40 | 41 | #endif 42 | 43 | }; 44 | 45 | } /* namespace messages */ 46 | } /* namespace hdb */ 47 | 48 | #endif /* SRC_HDB_MESSAGES_LOCKGRANT_H_ */ 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 SPCL 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /reproducability_daint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | echo "Script for generating scripts for reproducability experiments" 5 | 6 | PROJECTDIR="" 7 | WORKLOADSDIR="" 8 | DELAYWORKLOADDIR="" 9 | 10 | if [ -z "${PROJECTDIR}" ] 11 | then 12 | echo "The PROJECTDIR must be specified. For example: ${HOME}/HumongousLock/" 13 | exit 1 14 | fi 15 | 16 | 17 | if [ -z "${WORKLOADSDIR}" ] 18 | then 19 | echo "The WORKLOADSDIR must be specified. For example: ${SCRATCH}/tpcc/" 20 | exit 1 21 | fi 22 | 23 | 24 | if [ -z "${DELAYWORKLOADDIR}" ] 25 | then 26 | echo "The DELAYWORKLOADDIR must be specified for delay experiment. For example: ${SCRATCH}/tpcc/serializable_1024/" 27 | exit 1 28 | fi 29 | 30 | 31 | for i in {0..7}; 32 | do 33 | 34 | NODES=$((2**i)); 35 | ./generate_batch_job.sh --dir=${PROJECTDIR} --workloadsDir=${WORKLOADSDIR} --nodes=${NODES} --simple2pl --waitdie --nowait --timestamp --jobname=job${NODES}.sh 36 | 37 | done 38 | 39 | 40 | 41 | ./generate_batch_job.sh --dir=${PROJECTDIR} --workloadDir=${DELAYWORKLOADDIR} --nodes=8 --delays=0,250,1000,4000,16000,64000,256000,1024000 --simple2pl --waitdie --nowait --timestamp --jobname=delay_job8.sh 42 | -------------------------------------------------------------------------------- /compile_daint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | usage () { 4 | echo "Script for compiling the project on daint cluster" 5 | echo "options:" 6 | echo " --dir=PATH (default=PWD) #absolute path to the project" 7 | } 8 | 9 | 10 | WORKDIR=${PWD} 11 | 12 | for arg in "$@" 13 | do 14 | case ${arg} in 15 | --help|-help|-h) 16 | usage 17 | exit 1 18 | ;; 19 | --dir=*) 20 | WORKDIR=`echo $arg | sed -e 's/--dir=//'` 21 | WORKDIR=`eval echo ${WORKDIR}` # tilde and variable expansion 22 | ;; 23 | esac 24 | done 25 | 26 | echo "Start Compiling fompi-NA" 27 | 28 | cd ${WORKDIR} 29 | tar -xf foMPI-NA-0.2.4.tar.gz 30 | cd fompi-na/ 31 | make libfompi.a 32 | rm -f fompi_fortran.o module_fompi.o FOMPI.mod 33 | module load daint-mc 34 | make libfompi.a 35 | 36 | echo "fompi-NA has been compiled" 37 | 38 | echo "Start Compiling HumongousLock" 39 | 40 | module load Boost 41 | cd ${WORKDIR} 42 | cd HumongousLock 43 | 44 | echo "USE_CRAY=1" > Makefile.local 45 | echo "FOMPI_LOCATION=${WORKDIR}/fompi-na/" >> Makefile.local 46 | 47 | make 48 | cd ${WORKDIR} 49 | 50 | echo "HumongousLock has been compiled" 51 | 52 | 53 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/locktable/LockTableAgent.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LockTableAgent.h 3 | * 4 | * Created on: Mar 27, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_LOCKTABLE_LOCKTABLEAGENT_H_ 9 | #define SRC_HDB_LOCKTABLE_LOCKTABLEAGENT_H_ 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace hdb { 20 | namespace locktable { 21 | 22 | class LockTableAgent { 23 | 24 | public: 25 | 26 | LockTableAgent(hdb::configuration::SystemConfig *config); 27 | virtual ~LockTableAgent(); 28 | 29 | public: 30 | 31 | void execute(); 32 | 33 | protected: 34 | 35 | hdb::configuration::SystemConfig *config; 36 | hdb::communication::Communicator *communicator; 37 | 38 | protected: 39 | 40 | hdb::locktable::Table *table; 41 | 42 | protected: 43 | 44 | void processMessage(hdb::messages::Message *message); 45 | 46 | uint32_t remainingClients; 47 | 48 | }; 49 | 50 | } /* namespace locktable */ 51 | } /* namespace hdb */ 52 | 53 | #endif /* SRC_HDB_LOCKTABLE_LOCKTABLEAGENT_H_ */ 54 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/communication/SendReceiveCommunicator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SendReceiveCommunicator.h 3 | * 4 | * Created on: Apr 30, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_COMMUNICATION_SENDRECEIVECOMMUNICATOR_H_ 9 | #define SRC_HDB_COMMUNICATION_SENDRECEIVECOMMUNICATOR_H_ 10 | 11 | #include 12 | #include 13 | 14 | namespace hdb { 15 | namespace communication { 16 | 17 | class SendReceiveCommunicator { 18 | 19 | public: 20 | 21 | SendReceiveCommunicator(hdb::configuration::SystemConfig *config); 22 | virtual ~SendReceiveCommunicator(); 23 | 24 | public: 25 | const uint32_t comdelay; 26 | bool sendMessage(hdb::messages::Message *message, uint32_t targetGlobalRank); 27 | hdb::messages::Message * getMessage(); 28 | hdb::messages::Message * getMessageBlocking(); 29 | 30 | protected: 31 | 32 | void** receiveBuffer; 33 | 34 | uint32_t globalMachineId; 35 | uint32_t localMachineId; 36 | uint32_t numberOfProcessesPerMachine; 37 | 38 | uint32_t Slots; 39 | MPI_Request *requests; 40 | 41 | }; 42 | 43 | } /* namespace communication */ 44 | } /* namespace hdb */ 45 | 46 | #endif /* SRC_HDB_COMMUNICATION_SENDRECEIVECOMMUNICATOR_H_ */ 47 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/transactions/ReplayClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ReplayClient.h 3 | * 4 | * Created on: Apr 22, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_TRANSACTIONS_REPLAYCLIENT_H_ 9 | #define SRC_HDB_TRANSACTIONS_REPLAYCLIENT_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | namespace hdb { 21 | namespace transactions { 22 | 23 | class ReplayClient: public TransactionAgent { 24 | 25 | public: 26 | 27 | ReplayClient(hdb::configuration::SystemConfig *config, std::string fileLocation, uint64_t numberOfTransactions); 28 | virtual ~ReplayClient(); 29 | 30 | public: 31 | 32 | void generate(); 33 | void execute(); 34 | 35 | protected: 36 | 37 | uint32_t warehouseId; 38 | uint32_t clientId; 39 | 40 | uint64_t localclientid; 41 | uint64_t clientsPerWarehouse; 42 | 43 | 44 | 45 | std::string fileLocation; 46 | uint64_t numberOfTransactions; 47 | uint64_t globalTableSize; 48 | 49 | }; 50 | 51 | } /* namespace transactions */ 52 | } /* namespace hdb */ 53 | 54 | #endif /* SRC_HDB_TRANSACTIONS_REPLAYCLIENT_H_ */ 55 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/communication/VoteCommunicator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * VoteCommunicator.h 3 | * 4 | * Created on: Apr 17, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_COMMUNICATION_VOTECOMMUNICATOR_H_ 9 | #define SRC_HDB_COMMUNICATION_VOTECOMMUNICATOR_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #ifdef USE_FOMPI 16 | #include 17 | #endif 18 | 19 | 20 | namespace hdb { 21 | namespace communication { 22 | 23 | class VoteCommunicator { 24 | 25 | public: 26 | 27 | VoteCommunicator(hdb::configuration::SystemConfig* config); 28 | virtual ~VoteCommunicator(); 29 | 30 | protected: 31 | 32 | volatile uint64_t voteCounter; 33 | #ifdef USE_FOMPI 34 | foMPI_Win windowObject; 35 | #else 36 | MPI_Win windowObject; 37 | #endif 38 | 39 | protected: 40 | 41 | uint32_t globalRank; 42 | uint32_t numberOfProcessesPerMachine; 43 | uint32_t localMachineId; 44 | 45 | public: 46 | const uint32_t comdelay; 47 | void vote(uint32_t targetRank, bool outcome); 48 | bool checkVoteReady(bool *outcome, uint32_t targetCount); 49 | void reset(); 50 | 51 | }; 52 | 53 | } /* namespace communication */ 54 | } /* namespace hdb */ 55 | 56 | #endif /* SRC_HDB_COMMUNICATION_VOTECOMMUNICATOR_H_ */ 57 | -------------------------------------------------------------------------------- /job.template: -------------------------------------------------------------------------------- 1 | #!/bin/bash -l 2 | #SBATCH --job-name=$JOBNAME 3 | #SBATCH --time=$TOTALTIME 4 | #SBATCH --nodes=$NODES 5 | #SBATCH --ntasks-per-node=32 6 | #SBATCH --ntasks-per-core=1 7 | #SBATCH --partition=normal 8 | #SBATCH --constraint=mc 9 | #SBATCH --hint=nomultithread 10 | 11 | agents=16 12 | nodenum=$NODES 13 | codelocation=$EXECUTABLE 14 | 15 | #declare -a transactionalgs=("simple2pl" "waitdie" "nowait" "timestamp") 16 | declare -a transactionalgs=($ALGORITHMS) 17 | declare -a delays=($DELAYS) 18 | declare -a workloads=($WORKLOADS) 19 | 20 | 21 | for workload in "${workloads[@]}"; do 22 | for trtype in "${transactionalgs[@]}"; do 23 | for delay in "${delays[@]}"; do 24 | 25 | wlloc="$DATADIR/${workload}/" 26 | locksperwh=$(cat ${wlloc}/max-locks-per-wh.meta | grep -oP '^[^0-9]*\K[0-9]+') 27 | numwhs=$(ls ${wlloc}/*.csv | sed 's!.*/!!' | grep -o -E '[0-9]+' | sort -nr | head -1 | sed 's/^0*//') 28 | 29 | outname="out-${workload}-${numwhs}-${nodenum}-${agents}-${agents}-${delay}-${trtype}" 30 | 31 | srun $codelocation --timelimit=120 --comdelay=${delay} --warehouses=${numwhs} --processespernode=${agents} --locksperwh=${locksperwh} --socketspernode=2 --localworkloadsize=1000000 --workloadlocation=${wlloc} --logname=${outname} --${trtype} 32 | 33 | done 34 | done 35 | done 36 | 37 | -------------------------------------------------------------------------------- /data/processing/locking-throughput.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import pandas as pd 5 | 6 | from exp_helpers import MEASURES, summarize 7 | 8 | parser = argparse.ArgumentParser() 9 | parser.add_argument('-i', '--input', help='Input .hdf5 file') 10 | parser.add_argument('-o', '--output', help='Output .csv file') 11 | parser.add_argument('-s', '--summarize', action='store_true', 12 | help='Summarize runs of the same configuration?') 13 | args = parser.parse_args() 14 | 15 | # Open data 16 | df = pd.read_hdf(args.input) 17 | dimensions = [c for c in df.columns.values if c not in MEASURES] 18 | 19 | # Project to interesting attributes 20 | df = df[dimensions + ['ClientTotalLocks', 'ClientLockingTimeAccumulated']] 21 | 22 | # Average per run and derive other measures 23 | df = df.groupby(by=dimensions) \ 24 | .agg({'ClientTotalLocks': 'sum', 'ClientLockingTimeAccumulated': 'mean'}) \ 25 | .reset_index() 26 | df['SystemLockingThroughput'] = df['ClientTotalLocks'] / df['ClientLockingTimeAccumulated'] 27 | 28 | # Average per configuration 29 | if args.summarize: 30 | df = summarize(df) 31 | 32 | # Write result 33 | df.sort_values(ascending=False, by=['num_server_agents_per_node', 'workload', 'isolation_mode', 'num_nodes']) \ 34 | .to_csv(args.output, index=False) 35 | -------------------------------------------------------------------------------- /workload-traces/mysql/tpcc/extract_events.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import json 4 | import fileinput 5 | 6 | #current_trx_num = None 7 | #locks_of_current_trx = set() 8 | 9 | # Read trace events one by one 10 | for line in fileinput.input(): 11 | data = json.loads(line) 12 | 13 | # Get only lock events 14 | if data.get('action') != 'lock': 15 | continue 16 | 17 | # Extract interesting properties 18 | object_name = data['object_name'] 19 | lock_mode = data['lock_mode'] 20 | trx_name = data['trx_name'] 21 | trx_num = data['trx_num'] 22 | 23 | # Insert ware house where missing (home ware house by default) 24 | ware_house = data['ware_house'] if 'ware_house' in data else data['home_ware_house'] 25 | ware_house = int(ware_house) 26 | 27 | # # Skip over duplicate locks of the same TRX 28 | # if trx_num != current_trx_num: 29 | # locks_of_current_trx.clear() 30 | # current_trx_num = trx_num 31 | # 32 | # if lock_id in locks_of_current_trx: 33 | # continue 34 | # locks_of_current_trx.add(lock_id) 35 | 36 | # Output result 37 | print(json.dumps({ 'ware_house': ware_house, 38 | 'object_name': object_name, 39 | 'lock_mode': lock_mode, 40 | 'trx_name': trx_name, 41 | 'trx_num': trx_num })) 42 | -------------------------------------------------------------------------------- /workload-traces/mysql/tpcc/segmentize.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import fileinput 4 | import lzma 5 | import re 6 | 7 | with open('dummy.out', 'w') as f: 8 | f.write('') 9 | 10 | class Segment: 11 | def __init__(self): 12 | self.num = 0; 13 | self.content = [] 14 | self.name = "unknown" 15 | self.files = {} 16 | 17 | def Flush(self): 18 | filename = '{0}.out.xz'.format(self.name) 19 | if filename not in self.files: 20 | self.files[filename] = lzma.open(filename, mode='wt') 21 | f = self.files[filename] 22 | for l in self.content: 23 | f.write(l) 24 | self.content = [] 25 | self.num += 1 26 | self.name = "unknown" 27 | 28 | def Append(self, line): 29 | self.content.append(line) 30 | 31 | def SetName(self, name): 32 | self.name = name 33 | 34 | trx_start_re = re.compile('start: trx ([a-z]*) on home w_id ([0-9]*)') 35 | 36 | current_segment = Segment() 37 | for line in fileinput.input(): 38 | result = trx_start_re.match(line) 39 | if result: 40 | current_segment.Flush() 41 | current_segment.SetName("wh{0:06}".format(int(result.group(2)))) 42 | line = line.strip() + " trx_num {0}\n".format(current_segment.num) 43 | 44 | current_segment.Append(line) 45 | 46 | current_segment.Flush() 47 | -------------------------------------------------------------------------------- /workload-traces/mysql/tpcc/make_trace/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.7) 2 | 3 | project(make_trace) 4 | 5 | # Set build type to Release if not set 6 | if(NOT DEFINED CMAKE_BUILD_TYPE) 7 | set(CMAKE_BUILD_TYPE "Release") 8 | message(STATUS "No build type set, defaulting to Release") 9 | endif() 10 | 11 | # Add variable to cache 12 | set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" 13 | CACHE STRING 14 | "Choose the type of build. Options are: , Debug, Release, RelWithDebInfo, MinSizeRel.") 15 | message(STATUS "Using build type: ${CMAKE_BUILD_TYPE}") 16 | 17 | include_directories("${PROJECT_SOURCE_DIR}") 18 | 19 | # Setup compilation options 20 | set (CMAKE_CXX_STANDARD 11) 21 | set (CMAKE_C_STANDARD 11) 22 | 23 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") 24 | 25 | # Find external dependencies 26 | include_directories("${CMAKE_CURRENT_LIST_DIR}/../../../../../3rdparty/rapidjson/include") 27 | 28 | find_package(Boost REQUIRED 29 | COMPONENTS program_options) 30 | 31 | find_package(OpenMP) 32 | if(OPENMP_FOUND) 33 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 34 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 35 | endif() 36 | 37 | # Add main compilation target 38 | add_executable(make_trace 39 | main.cpp 40 | ) 41 | target_link_libraries(make_trace 42 | ${Boost_LIBRARIES} 43 | ) 44 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/MessageUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MessageUtils.h 3 | * 4 | * Created on: Mar 27, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_MESSAGES_MESSAGEUTILS_H_ 9 | #define SRC_HDB_MESSAGES_MESSAGEUTILS_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace hdb { 19 | namespace messages { 20 | 21 | #define MAX(a,b) ((a) > (b) ? (a) : (b)) 22 | 23 | #define MAX_MESSAGE_SIZE (MAX( \ 24 | sizeof(hdb::messages::LockRequest), \ 25 | MAX ( \ 26 | sizeof(hdb::messages::LockGrant), \ 27 | MAX ( \ 28 | sizeof(hdb::messages::LockRelease), \ 29 | MAX ( \ 30 | sizeof(hdb::messages::VoteRequest), \ 31 | MAX ( \ 32 | sizeof(hdb::messages::TransactionEnd), \ 33 | sizeof(hdb::messages::Shutdown) \ 34 | ) \ 35 | ) \ 36 | ) \ 37 | ) \ 38 | ) \ 39 | ) 40 | 41 | } /* namespace messages */ 42 | } /* namespace hdb */ 43 | 44 | #endif /* SRC_HDB_MESSAGES_MESSAGEUTILS_H_ */ 45 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/communication/NotifiedCommunicator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * NotifiedCommunicator.h 3 | * 4 | * Created on: Apr 28, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_COMMUNICATION_NOTIFIEDCOMMUNICATOR_H_ 9 | #define SRC_HDB_COMMUNICATION_NOTIFIEDCOMMUNICATOR_H_ 10 | 11 | #ifdef USE_FOMPI 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | namespace hdb { 20 | namespace communication { 21 | 22 | class NotifiedCommunicator { 23 | 24 | public: 25 | 26 | NotifiedCommunicator(hdb::configuration::SystemConfig *config); 27 | virtual ~NotifiedCommunicator(); 28 | 29 | protected: 30 | 31 | uint32_t windowSizeInSlots; 32 | void *buffer; 33 | foMPI_Win window; 34 | 35 | protected: 36 | 37 | foMPI_Request request; 38 | MPI_Status status; 39 | 40 | public: 41 | const uint32_t comdelay; 42 | bool sendMessage(hdb::messages::Message *message, uint32_t targetGlobalRank); 43 | hdb::messages::Message * getMessage(); 44 | hdb::messages::Message * getMessageBlocking(); 45 | 46 | protected: 47 | 48 | uint32_t globalRank; 49 | uint32_t internalRank; 50 | uint32_t localMachineId; 51 | uint32_t numberOfProcessesPerMachine; 52 | bool isLockServerEndPoint; 53 | 54 | 55 | }; 56 | 57 | } /* namespace communication */ 58 | } /* namespace hdb */ 59 | 60 | #endif 61 | 62 | #endif /* SRC_HDB_COMMUNICATION_NOTIFIEDCOMMUNICATOR_H_ */ 63 | -------------------------------------------------------------------------------- /workload-traces/mysql/my.cnf: -------------------------------------------------------------------------------- 1 | [mysqld] 2 | ssl=0 3 | symbolic-links=0 4 | sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES 5 | 6 | # general 7 | thread_cache_size=2000 8 | table_open_cache = 200000 9 | table_open_cache_instances=64 10 | back_log=1500 11 | query_cache_type=0 12 | max_connections=4000 13 | 14 | # files 15 | innodb_file_per_table 16 | innodb_log_file_size=15G 17 | innodb_log_files_in_group=2 18 | innodb_open_files=4000 19 | 20 | innodb_io_capacity=10000 21 | loose-innodb_io_capacity_max=12000 22 | innodb_lru_scan_depth=1024 23 | #innodb_page_cleaners=32 24 | 25 | # buffers 26 | innodb_buffer_pool_size=200G 27 | innodb_buffer_pool_instances=8 28 | innodb_log_buffer_size=64M 29 | 30 | # tune 31 | innodb_doublewrite= 1 32 | innodb_support_xa=0 33 | innodb_thread_concurrency=0 34 | innodb_flush_log_at_trx_commit= 1 35 | innodb_flush_method=O_DIRECT_NO_FSYNC 36 | innodb_max_dirty_pages_pct=90 37 | join_buffer_size=32K 38 | sort_buffer_size=32K 39 | innodb_use_native_aio=0 40 | innodb_stats_persistent = 1 41 | 42 | # perf special 43 | innodb_adaptive_flushing = 1 44 | innodb_flush_neighbors = 0 45 | innodb_read_io_threads = 16 46 | innodb_write_io_threads = 8 47 | innodb_purge_threads=4 48 | 49 | innodb_adaptive_hash_index=0 50 | innodb_change_buffering=none 51 | 52 | loose-innodb-log_checksum-algorithm=crc32 53 | loose-innodb-checksum-algorithm=strict_crc32 54 | loose-innodb_sched_priority_cleaner=39 55 | loose-metadata_locks_hash_instances=256 56 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/LockRequest.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LockRequest.h 3 | * 4 | * Created on: Apr 16, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_MESSAGES_LOCKREQUEST_H_ 9 | #define SRC_HDB_MESSAGES_LOCKREQUEST_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | namespace hdb { 18 | namespace messages { 19 | 20 | class LockRequest : public Message { 21 | 22 | public: 23 | 24 | LockRequest(uint32_t clientGlobalRank = 0, uint64_t transactionNumber = 0, uint64_t lockId = 0, hdb::locktable::LockMode mode = hdb::locktable::LockMode::NL); 25 | 26 | virtual ~LockRequest(); 27 | 28 | public: 29 | 30 | uint64_t lockId; 31 | hdb::locktable::LockMode mode; 32 | 33 | public: 34 | 35 | uint64_t GetGlobalTransactionId() const; 36 | 37 | 38 | friend bool operator < (const LockRequest& lhs, const LockRequest& rhs); 39 | friend bool operator > (const LockRequest& lhs, const LockRequest& rhs); 40 | 41 | 42 | 43 | 44 | bool requestExpired(); 45 | void setExpiryTime(); 46 | std::chrono::high_resolution_clock::time_point expiryTime; 47 | 48 | 49 | 50 | #ifdef USE_LOGGING 51 | public: 52 | 53 | uint64_t clientSendTime; 54 | uint64_t serverReceiveTime; 55 | uint64_t serverEnqueueTime; 56 | uint64_t serverDequeueTime; 57 | #endif 58 | 59 | }; 60 | 61 | } /* namespace messages */ 62 | } /* namespace hdb */ 63 | 64 | #endif /* SRC_HDB_MESSAGES_LOCKREQUEST_H_ */ 65 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/transactions/TransactionAgent.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TransactionAgent.h 3 | * 4 | * Created on: Mar 27, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_TRANSACTIONS_TRANSACTIONAGENT_H_ 9 | #define SRC_HDB_TRANSACTIONS_TRANSACTIONAGENT_H_ 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace hdb { 21 | namespace transactions { 22 | 23 | class TransactionAgent { 24 | 25 | public: 26 | 27 | TransactionAgent(hdb::configuration::SystemConfig *config); 28 | virtual ~TransactionAgent(); 29 | 30 | public: 31 | 32 | virtual void generate() = 0; 33 | virtual void execute() = 0; 34 | 35 | void shutdown(); 36 | 37 | void tpccExecute(uint32_t warehouse, uint32_t workloadSize); 38 | 39 | public: 40 | 41 | void debugPrintTransactions(); 42 | 43 | public: 44 | 45 | hdb::stats::ClientStats stats; 46 | 47 | protected: 48 | 49 | hdb::configuration::SystemConfig *config; 50 | hdb::communication::Communicator *communicator; 51 | hdb::transactions::TransactionManager *manager; 52 | 53 | protected: 54 | 55 | std::vector transactions; 56 | 57 | }; 58 | 59 | } /* namespace transactions */ 60 | } /* namespace hdb */ 61 | 62 | #endif /* SRC_HDB_TRANSACTIONS_TRANSACTIONAGENT_H_ */ 63 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/communication/HybridCommunicator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HybridCommunicator.h 3 | * 4 | * Created on: Apr 28, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_COMMUNICATION_HYBRIDCOMMUNICATOR_H_ 9 | #define SRC_HDB_COMMUNICATION_HYBRIDCOMMUNICATOR_H_ 10 | 11 | #ifdef USE_FOMPI 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | namespace hdb { 20 | namespace communication { 21 | 22 | class HybridCommunicator { 23 | 24 | public: 25 | 26 | HybridCommunicator(hdb::configuration::SystemConfig *config); 27 | virtual ~HybridCommunicator(); 28 | 29 | protected: 30 | 31 | uint32_t windowSizeInSlots; 32 | void *buffer; 33 | foMPI_Win window; 34 | 35 | protected: 36 | 37 | foMPI_Request request; 38 | MPI_Status status; 39 | 40 | protected: 41 | 42 | void** receiveBuffer; 43 | uint32_t Slots; 44 | MPI_Request *requests; 45 | 46 | public: 47 | const uint32_t comdelay; 48 | bool sendMessage(hdb::messages::Message *message, uint32_t targetGlobalRank); 49 | hdb::messages::Message * getMessage(); 50 | hdb::messages::Message * getMessageBlocking(); 51 | 52 | protected: 53 | 54 | uint32_t globalRank; 55 | uint32_t internalRank; 56 | uint32_t localMachineId; 57 | uint32_t numberOfProcessesPerMachine; 58 | bool isLockServerEndPoint; 59 | 60 | 61 | }; 62 | 63 | } /* namespace communication */ 64 | } /* namespace hdb */ 65 | 66 | #endif 67 | 68 | #endif /* SRC_HDB_COMMUNICATION_HYBRIDCOMMUNICATOR_H_ */ 69 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/configuration/SystemConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SystemConfig.h 3 | * 4 | * Created on: Mar 27, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_CONFIGURATION_SYSTEMCONFIG_H_ 9 | #define SRC_HDB_CONFIGURATION_SYSTEMCONFIG_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define REQUEST_TIME_OUT_MS (100) 18 | 19 | namespace hdb { 20 | namespace configuration { 21 | 22 | class SystemConfig { 23 | 24 | public: 25 | 26 | MPI_Comm localCommunicator; 27 | 28 | std::vector transaction_constraints; 29 | uint32_t comdelay; 30 | bool waitdie; 31 | bool nowait; 32 | bool timestamp; 33 | bool hashlock; 34 | 35 | bool isLockTableAgent; 36 | bool syntheticmode; 37 | 38 | uint32_t timelimit; 39 | uint32_t numberOfNodes; 40 | 41 | int32_t globalRank; 42 | int32_t globalNumberOfProcesses; 43 | 44 | int32_t localRank; 45 | int32_t localNumberOfProcesses; 46 | 47 | uint32_t locksPerWarehouse; 48 | uint32_t locksOnThisAgent; 49 | uint32_t globalNumberOfLocks; 50 | uint32_t globalNumberOfWarehouses; 51 | uint32_t globalNumberOfTransactionAgents; 52 | 53 | uint32_t internalRank; 54 | uint32_t globalNumberOfLockTableAgents; 55 | uint32_t *lockServerGlobalRanks; 56 | 57 | std::vector warehouseToLockServer; 58 | std::vector AllLocksPerAgent; 59 | 60 | }; 61 | 62 | } /* namespace configuration */ 63 | } /* namespace hdb */ 64 | 65 | #endif /* SRC_HDB_CONFIGURATION_SYSTEMCONFIG_H_ */ 66 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/messages/LockRequest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * LockRequest.cpp 3 | * 4 | * Created on: Apr 16, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include "LockRequest.h" 9 | 10 | #include 11 | 12 | namespace hdb { 13 | namespace messages { 14 | 15 | LockRequest::LockRequest(uint32_t clientGlobalRank, uint64_t transactionNumber, uint64_t lockId, hdb::locktable::LockMode mode) : Message(LOCK_REQUEST_MESSAGE, sizeof(LockRequest), clientGlobalRank, transactionNumber) { 16 | 17 | this->lockId = lockId; 18 | this->mode = mode; 19 | 20 | #ifdef USE_LOGGING 21 | this->clientSendTime = 0; 22 | this->serverReceiveTime = 0; 23 | this->serverEnqueueTime = 0; 24 | this->serverDequeueTime = 0; 25 | #endif 26 | 27 | } 28 | 29 | uint64_t LockRequest::GetGlobalTransactionId() const{ 30 | return transactionNumber; 31 | } 32 | 33 | bool operator < (const LockRequest& lhs, const LockRequest& rhs) 34 | { 35 | return lhs.GetGlobalTransactionId() < rhs.GetGlobalTransactionId(); 36 | } 37 | 38 | bool operator > (const LockRequest& lhs, const LockRequest& rhs) 39 | { 40 | return lhs.GetGlobalTransactionId() > rhs.GetGlobalTransactionId(); 41 | } 42 | 43 | 44 | LockRequest::~LockRequest() { 45 | 46 | } 47 | 48 | bool LockRequest::requestExpired() { 49 | return (expiryTime < std::chrono::high_resolution_clock::now()); 50 | } 51 | 52 | void LockRequest::setExpiryTime() { 53 | expiryTime = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds(REQUEST_TIME_OUT_MS); 54 | } 55 | 56 | } /* namespace messages */ 57 | } /* namespace hdb */ 58 | -------------------------------------------------------------------------------- /data/plots/ethplot.mplstyle: -------------------------------------------------------------------------------- 1 | font.size: 14.0 2 | font.family: sans-serif 3 | font.sans-serif: Supria Sans 4 | font.style: normal 5 | font.variant: normal 6 | 7 | lines.linewidth: 3.0 8 | lines.solid_capstyle: butt 9 | lines.markeredgecolor: black 10 | 11 | # Don't really want a frame but in case we do we want the fancy one: 12 | legend.frameon: false 13 | legend.fancybox: true 14 | 15 | axes.prop_cycle: cycler('color', ['30a2da', 'fc4f30', 'e5ae38', '6d904f', '8b8b8b']) 16 | axes.facecolor: ffffff 17 | axes.edgecolor: 000000 18 | axes.labelsize: large 19 | axes.axisbelow: true 20 | axes.grid: true 21 | axes.linewidth: 2.0 22 | axes.titlesize: x-large 23 | axes.labelweight: light 24 | 25 | # Remove small ticks at the labels, not necessary with grid: 26 | xtick.major.size: 0 27 | ytick.major.size: 0 28 | xtick.minor.size: 0 29 | ytick.minor.size: 0 30 | 31 | # Adds more space between x[0] and y[0] tick labels: 32 | xtick.major.pad: 7 33 | ytick.major.pad: 7 34 | 35 | patch.edgecolor: f0f0f0 36 | patch.linewidth: 0.5 37 | 38 | svg.fonttype: path 39 | 40 | grid.linestyle: - 41 | grid.linewidth: 1.0 42 | grid.color: cbcbcb 43 | 44 | savefig.edgecolor: f0f0f0 45 | savefig.facecolor: ffffff 46 | savefig.dpi: 300 47 | savefig.bbox: tight 48 | savefig.pad_inches: 0.0 49 | 50 | figure.figsize: 8, 6 51 | figure.subplot.left: 0.00 52 | figure.subplot.right: 1.0 53 | figure.subplot.bottom: 0.00 54 | figure.subplot.top: 0.9 55 | #figure.subplot.wspace : 0.2 # the amount of width reserved for blank space between subplots 56 | #figure.subplot.hspace : 0.2 # the amount of height reserved for white space between subplots 57 | -------------------------------------------------------------------------------- /data/collect_data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPTDIR=$(dirname "$(readlink -f "$0")") 4 | 5 | ( 6 | cd "$SCRIPTDIR"/traces && \ 7 | find . -name "*.exp" | \ 8 | while read line 9 | do 10 | filename="$(basename $line)" 11 | partsstr="$(echo "$filename" | sed -n 's/^out-\(.*\)-\([0-9]*\)-\([0-9]*\)-\([0-9]*\)-\([0-9]*\)-\([0-9]*\)-\(.*\)\.exp$/\2-\3-\4-\5-\6-\7/p')" 12 | dirname="$( echo "$filename" | sed -n 's/^out-\(.*\)-\([0-9]*\)-\([0-9]*\)-\([0-9]*\)-\([0-9]*\)-\([0-9]*\)-\(.*\)\.exp$/\1/p')" 13 | if [[ -z "$dirname" || -z "$partsstr" ]] 14 | then 15 | echo "File $filename does not match pattern. Ignoring..." >&2 16 | continue 17 | fi 18 | parts=(${partsstr//-/ }) 19 | wh=${parts[0]} 20 | nn=${parts[1]} 21 | sa=${parts[2]} 22 | ta=${parts[3]} 23 | nd=${parts[4]} 24 | m=${parts[5]} 25 | im="$(echo "$dirname" | sed -rn 's/^.*(read_com|rep_read|serializable).*$/\1/p')" 26 | wl="tpcc" 27 | if [[ -z "$im" ]] 28 | then 29 | wl="$dirname" 30 | fi 31 | "$SCRIPTDIR"/exp2json.py -i $line -c \ 32 | '{"workload": "'$wl'", 33 | "isolation_mode": "'$im'", 34 | "num_cores_per_node": '$(($sa + $ta))', 35 | "num_server_agents_per_node": '$sa', 36 | "num_nodes": '$nn', 37 | "num_warehouses": '$wh', 38 | "network_delay": '$nd', 39 | "mechanism": "'$m'" 40 | }' 41 | done 42 | ) > "$SCRIPTDIR"/data.json 43 | -------------------------------------------------------------------------------- /data/collect_data_paper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPTDIR=$(dirname "$(readlink -f "$0")") 4 | 5 | rm -f "$SCRIPTDIR"/data.json 6 | 7 | ( 8 | cd "$SCRIPTDIR"/traces_paper && \ 9 | find . -name "*.exp" | \ 10 | while read line 11 | do 12 | b=$(basename $line | cut -f1 -d. | sed -E "s/--*(hashlock|neworder|nowait|waitdie|timestamp|uni|high|med)/-\\1/g") 13 | parts=(${b//-/ }) 14 | IFS=$'-'; parts=($b); unset IFS 15 | has_nd=0; nd='null' 16 | if [[ ${#parts[@]} -eq 8 ]]; then 17 | nd=${parts[6]} 18 | has_nd=1 19 | fi 20 | im=${parts[1]} 21 | wh=${parts[2]} 22 | if [[ "$wh" == "2520" ]]; then wh=2048; fi 23 | nn=${parts[3]} 24 | sa=${parts[4]} 25 | ta=${parts[4]} 26 | o1=${parts[$((6+$has_nd))]} 27 | o2=${parts[$((7+$has_nd))]} 28 | wl="tpcc" 29 | if [[ "$o1" == "uni" || "$o1" == "med" || "$o1" == "high" || 30 | "$o2" == "uni" || "$o2" == "med" || "$o2" == "high" ]] 31 | then 32 | wl="ycsb" 33 | fi 34 | "$SCRIPTDIR"/exp2json.py -i $line -c \ 35 | '{"workload": "'$wl'", 36 | "isolation_mode": "'$im'", 37 | "num_cores_per_node": '$(($sa + $ta))', 38 | "num_server_agents_per_node": '$sa', 39 | "num_nodes": '$nn', 40 | "num_warehouses": '$wh', 41 | "network_delay": '$nd', 42 | "option1": "'$o1'", 43 | "option2": "'$o2'" 44 | }' 45 | done 46 | ) >> "$SCRIPTDIR"/data.json 47 | 48 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/communication/Communicator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Communicator.h 3 | * 4 | * Created on: Apr 17, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_COMMUNICATION_COMMUNICATOR_H_ 9 | #define SRC_HDB_COMMUNICATION_COMMUNICATOR_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace hdb { 19 | namespace communication { 20 | 21 | class Communicator { 22 | 23 | public: 24 | 25 | Communicator(hdb::configuration::SystemConfig *config); 26 | virtual ~Communicator(); 27 | 28 | public: 29 | 30 | hdb::communication::DataLayer *dataLayer; 31 | 32 | protected: 33 | #ifdef USE_FOMPI 34 | hdb::communication::NotifiedCommunicator *notifiedCommunicator; 35 | //hdb::communication::HybridCommunicator *notifiedCommunicator; 36 | #else 37 | hdb::communication::SendReceiveCommunicator *notifiedCommunicator; 38 | #endif 39 | hdb::communication::VoteCommunicator *voteCommunictor; 40 | 41 | public: 42 | 43 | bool sendMessage(hdb::messages::Message *message, uint32_t targetRank); 44 | hdb::messages::Message * getMessage(); 45 | hdb::messages::Message * getMessageBlocking(); 46 | 47 | public: 48 | 49 | void vote(uint32_t targetRank, bool outcome); 50 | bool checkVoteReady(bool *outcome, uint32_t targetCount); 51 | 52 | public: 53 | 54 | void signalTransactionEnd(uint32_t targetRank); 55 | void waitForTransactionEndSignals(uint32_t targetCount); 56 | 57 | }; 58 | 59 | } /* namespace communication */ 60 | } /* namespace hdb */ 61 | 62 | #endif /* SRC_HDB_COMMUNICATION_COMMUNICATOR_H_ */ 63 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/communication/DataLayer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * DataLayer.h 3 | * 4 | * Created on: Apr 29, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_COMMUNICATION_DATALAYER_H_ 9 | #define SRC_HDB_COMMUNICATION_DATALAYER_H_ 10 | 11 | #include 12 | #ifdef USE_FOMPI 13 | #include 14 | #endif 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | namespace hdb { 22 | namespace communication { 23 | 24 | 25 | class DataLayer { 26 | public: 27 | 28 | DataLayer(hdb::configuration::SystemConfig *config); 29 | virtual ~DataLayer(); 30 | 31 | public: 32 | 33 | void newOrder(uint32_t warehouse, bool remoteItemPresent, std::set *involvedLockServers); 34 | void payment(uint32_t warehouse); 35 | void orderStat(uint32_t warehouse); 36 | void delivery(uint32_t warehouse); 37 | void slev(uint32_t warehouse); 38 | void ycsb(uint32_t warehouse); 39 | 40 | protected: 41 | 42 | void *buffer; 43 | 44 | #ifdef USE_FOMPI 45 | foMPI_Win window; 46 | #else 47 | MPI_Win window; 48 | #endif 49 | 50 | void *writeBuffer; 51 | void *readBuffer; 52 | 53 | protected: 54 | 55 | const uint32_t comdelay; 56 | 57 | void readFromProcess(uint32_t targetProcess, uint32_t numberOfBytes); 58 | void writeToProcess(uint32_t targetProcess, uint32_t numberOfBytes); 59 | 60 | protected: 61 | 62 | uint32_t localMachineId; 63 | uint32_t numberOfProcessesPerMachine; 64 | uint32_t numberOfLockServers; 65 | 66 | std::vector& warehouseToLockServer; 67 | 68 | // one of them is not zero. 69 | // uint32_t wareHousesPerLockServer; 70 | // uint32_t LockServersPerwareHouse; 71 | 72 | 73 | uint32_t *lockServerGlobalRanks; 74 | 75 | }; 76 | 77 | } /* namespace communication */ 78 | } /* namespace hdb */ 79 | 80 | #endif /* SRC_HDB_COMMUNICATION_DATALAYER_H_ */ 81 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/locktable/LockMode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LockMode.h 3 | * 4 | * Created on: Mar 16, 2017 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef HDB_LOCKTABLE_LOCKMODE_H_ 9 | #define HDB_LOCKTABLE_LOCKMODE_H_ 10 | 11 | #include 12 | 13 | namespace hdb { 14 | namespace locktable { 15 | 16 | enum LockMode { 17 | NL = 0, IS = 1, IX = 2, S = 3, SIX = 4 , X = 5, MODE_COUNT = 6 18 | }; 19 | 20 | static const bool COMPATIBILITY_MATRIX [LockMode::MODE_COUNT][LockMode::MODE_COUNT] = 21 | { 22 | {true, true, true, true, true, true}, 23 | {true, true, true, true, true, false}, 24 | {true, true, true, false, false, false}, 25 | {true, true, false, true, false, false}, 26 | {true, true, false, false, false, false}, 27 | {true, false, false, false, false, false} 28 | }; 29 | 30 | static const bool LOCK_MODE_COMPATIBLE(LockMode a, LockMode b) { 31 | return COMPATIBILITY_MATRIX[a][b]; 32 | } 33 | 34 | static const bool LOCK_READ_OR_WRITE(LockMode a) { 35 | return a == LockMode::S || a == LockMode::X; 36 | } 37 | 38 | static const bool WRITE_MATRIX [LockMode::MODE_COUNT] = 39 | {false, false, false, false, false, true}; 40 | 41 | 42 | static const bool WRITE_LOCK_MODE(LockMode a) { 43 | return WRITE_MATRIX[a]; 44 | } 45 | 46 | 47 | static LockMode LOCK_MODE_FROM_STRING(char *lockMode) { 48 | 49 | if(strcmp(lockMode, "IS") == 0) { 50 | return LockMode::IS; 51 | } else if(strcmp(lockMode, "IX") == 0) { 52 | return LockMode::IX; 53 | } else if(strcmp(lockMode, "S") == 0) { 54 | return LockMode::S; 55 | } else if(strcmp(lockMode, "SIX") == 0) { 56 | return LockMode::SIX; 57 | } else if(strcmp(lockMode, "X") == 0) { 58 | return LockMode::X; 59 | } else { 60 | return LockMode::NL; 61 | } 62 | 63 | } 64 | 65 | } /* namespace locktable */ 66 | } /* namespace hdb */ 67 | 68 | #endif /* HDB_LOCKTABLE_LOCKMODE_H_ */ 69 | -------------------------------------------------------------------------------- /data/jsonl2hdf5.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import pandas as pd 5 | from _exp_helpers import DIMENSIONS 6 | 7 | parser = argparse.ArgumentParser(description='Convert data frame in JSON lines format to HDF5.') 8 | parser.add_argument('-i', '--input', help='Input .jsonl file') 9 | parser.add_argument('-o', '--output', help='Output .hdf5 file') 10 | args = parser.parse_args() 11 | 12 | # Load data in JSON lines format 13 | df = pd.read_json(args.input, lines=True).fillna('') 14 | 15 | # Compute derived dimensions 16 | df['num_tx_agents_per_node'] = df['num_cores_per_node'] - df['num_server_agents_per_node'] 17 | df['num_cores'] = df['num_nodes'] * df['num_cores_per_node'] 18 | df['num_tx_agents'] = df['num_nodes'] * df['num_tx_agents_per_node'] 19 | df['num_server_agents'] = df['num_nodes'] * df['num_server_agents_per_node'] 20 | 21 | # Make naming consistent 22 | df['isolation_mode'] = df['isolation_mode'].replace({'read_com': 'readcommitted', 'rep_read': 'repeatableread'}) 23 | 24 | # Add empty values for missing dimensions 25 | for d in DIMENSIONS: 26 | if d not in df.columns.values: 27 | df[d] = '' 28 | 29 | # Derive mechanism name 30 | df['mechanism'] = '2pl-bw' 31 | df.loc[(df['option1'] == 'timestamp') | (df['option2'] == 'timestamp'), 'mechanism'] = 'to' 32 | df.loc[(df['option1'] == 'waitdie') | (df['option2'] == 'waitdie'), 'mechanism'] = '2pl-wd' 33 | df.loc[(df['option1'] == 'nowait') | (df['option2'] == 'nowait'), 'mechanism'] = '2pl-nw' 34 | 35 | # Derive workload name and YCSB config 36 | df['distribution'] = '' 37 | df.loc[(df['option1'] == 'uni') | (df['option2'] == 'uni'), 'distribution'] = 'uni' 38 | df.loc[(df['option1'] == 'med') | (df['option2'] == 'med'), 'distribution'] = 'med' 39 | df.loc[(df['option1'] == 'high') | (df['option2'] == 'high'), 'distribution'] = 'high' 40 | 41 | # Write into HDF5 format 42 | df.reset_index().to_hdf(args.output,'data') 43 | -------------------------------------------------------------------------------- /data/processing/tx-breakdown.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import pandas as pd 5 | 6 | from exp_helpers import MEASURES, summarize 7 | 8 | parser = argparse.ArgumentParser() 9 | parser.add_argument('-i', '--input', help='Input .hdf5 file') 10 | parser.add_argument('-o', '--output', help='Output .csv file') 11 | parser.add_argument('-s', '--summarize', action='store_true', 12 | help='Summarize runs of the same configuration?') 13 | args = parser.parse_args() 14 | 15 | # Open data 16 | df = pd.read_hdf(args.input) 17 | dimensions = [c for c in df.columns.values if c not in MEASURES] 18 | 19 | # Project to interesting attributes 20 | df = df[dimensions + 21 | ['ClientLockingTimeAccumulated', 22 | 'ClientDataAccessTimeAccumulated', 23 | 'ClientVotingTimeAccumulated', 24 | 'ClientEndingTimeAccumulated', 25 | 'ClientExecutionTime', 26 | 'ClientTotalTransactions']] 27 | 28 | # Average per configuration and derive other measures 29 | df = df.groupby(by=dimensions).sum().reset_index() 30 | df['ClientLockingTimePerTx'] = df['ClientLockingTimeAccumulated'] / df['ClientTotalTransactions'] 31 | df['ClientDataAccessTimePerTx'] = df['ClientDataAccessTimeAccumulated'] / df['ClientTotalTransactions'] 32 | df['ClientVotingTimePerTx'] = df['ClientVotingTimeAccumulated'] / df['ClientTotalTransactions'] 33 | df['ClientEndingTimePerTx'] = df['ClientEndingTimeAccumulated'] / df['ClientTotalTransactions'] 34 | df['ClientExecutionTimePerTx'] = df['ClientExecutionTime'] / df['ClientTotalTransactions'] 35 | df['ClientOtherTimePerTx'] = df['ClientExecutionTimePerTx'] \ 36 | - df['ClientLockingTimePerTx'] \ 37 | - df['ClientDataAccessTimePerTx'] \ 38 | - df['ClientVotingTimePerTx'] \ 39 | - df['ClientEndingTimePerTx'] 40 | 41 | # Average per configuration 42 | if args.summarize: 43 | df = summarize(df) 44 | 45 | # Write result 46 | df.sort_values(ascending=False, by=['num_server_agents_per_node', 'workload', 'num_nodes']) \ 47 | .to_csv(args.output, index=False) 48 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/communication/Communicator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Communicator.cpp 3 | * 4 | * Created on: Apr 17, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include 9 | 10 | namespace hdb { 11 | namespace communication { 12 | 13 | Communicator::Communicator(hdb::configuration::SystemConfig* config) { 14 | if (config->syntheticmode){ 15 | dataLayer = nullptr; 16 | } else { 17 | dataLayer = new hdb::communication::DataLayer(config); 18 | } 19 | voteCommunictor = new hdb::communication::VoteCommunicator(config); 20 | #ifdef USE_FOMPI 21 | notifiedCommunicator = new hdb::communication::NotifiedCommunicator(config); 22 | #else 23 | notifiedCommunicator = new hdb::communication::SendReceiveCommunicator(config); 24 | #endif 25 | 26 | } 27 | 28 | Communicator::~Communicator() { 29 | 30 | delete notifiedCommunicator; 31 | delete voteCommunictor; 32 | 33 | } 34 | 35 | bool Communicator::sendMessage(hdb::messages::Message* message, uint32_t targetRank) { 36 | 37 | return notifiedCommunicator->sendMessage(message, targetRank); 38 | 39 | } 40 | 41 | hdb::messages::Message* Communicator::getMessage() { 42 | 43 | return notifiedCommunicator->getMessage(); 44 | } 45 | 46 | hdb::messages::Message* Communicator::getMessageBlocking() { 47 | return notifiedCommunicator->getMessageBlocking(); 48 | } 49 | 50 | void Communicator::vote(uint32_t targetRank, bool outcome) { 51 | voteCommunictor->vote(targetRank, outcome); 52 | } 53 | 54 | bool Communicator::checkVoteReady(bool* outcome, uint32_t targetCount) { 55 | bool ready = voteCommunictor->checkVoteReady(outcome, targetCount); 56 | if(ready) { 57 | voteCommunictor->reset(); 58 | } 59 | return ready; 60 | } 61 | 62 | void Communicator::signalTransactionEnd(uint32_t targetRank) { 63 | vote(targetRank, true); 64 | } 65 | 66 | 67 | 68 | void Communicator::waitForTransactionEndSignals(uint32_t targetCount) { 69 | bool outcome = false; 70 | while(!voteCommunictor->checkVoteReady(&outcome, targetCount)); 71 | voteCommunictor->reset(); 72 | } 73 | 74 | } /* namespace communication */ 75 | } /* namespace hdb */ 76 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/transactions/Transaction.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Transaction.h 3 | * 4 | * Created on: Apr 18, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_TRANSACTIONS_TRANSACTION_H_ 9 | #define SRC_HDB_TRANSACTIONS_TRANSACTION_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | 25 | typedef std::pair lockid_mode_pair_t; 26 | 27 | namespace hdb { 28 | namespace transactions { 29 | 30 | 31 | enum DataMode: uint8_t { 32 | NONE = 0, NEWORD = 1, PAYMENT = 2, ORDSTAT = 3, DELIVERY = 4 , SLEV = 5, YCSB = 6 33 | }; 34 | 35 | static DataMode DATA_MODE_FROM_STRING(char *dataMode) { 36 | 37 | if(strcmp(dataMode,"neword") == 0) { 38 | return DataMode::NEWORD; 39 | } else if (strcmp(dataMode,"payment") == 0) { 40 | return DataMode::PAYMENT; 41 | } else if (strcmp(dataMode,"ordstat") == 0) { 42 | return DataMode::ORDSTAT; 43 | } else if (strcmp(dataMode,"delivery") == 0) { 44 | return DataMode::DELIVERY; 45 | } else if (strcmp(dataMode,"slev") == 0) { 46 | return DataMode::SLEV; 47 | } else { 48 | return DataMode::YCSB; 49 | } 50 | } 51 | 52 | 53 | class Transaction { 54 | 55 | public: 56 | 57 | Transaction(hdb::transactions::DataMode transactionTypeId = hdb::transactions::DataMode::NONE); 58 | 59 | public: 60 | 61 | hdb::transactions::DataMode transactionTypeId; 62 | std::vector requests; 63 | private: 64 | friend class boost::serialization::access; 65 | 66 | template 67 | void serialize(Archive & ar, const unsigned int version) 68 | { 69 | ar & transactionTypeId; 70 | ar & requests; 71 | } 72 | 73 | 74 | }; 75 | 76 | } /* namespace transactions */ 77 | } /* namespace hdb */ 78 | 79 | #endif /* SRC_HDB_TRANSACTIONS_TRANSACTION_H_ */ 80 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/transactions/TransactionManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TransactionManager.h 3 | * 4 | * Created on: Apr 19, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_TRANSACTIONS_TRANSACTIONMANAGER_H_ 9 | #define SRC_HDB_TRANSACTIONS_TRANSACTIONMANAGER_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | namespace hdb { 25 | namespace transactions { 26 | 27 | class TransactionManager { 28 | 29 | public: 30 | 31 | TransactionManager(hdb::configuration::SystemConfig *config, hdb::communication::Communicator *communicator, hdb::stats::ClientStats *stats); 32 | virtual ~TransactionManager(); 33 | 34 | public: 35 | 36 | void startTransaction(); 37 | void abortTransaction(hdb::transactions::DataMode txId); 38 | void commitTransaction(hdb::transactions::DataMode txId); 39 | 40 | public: 41 | 42 | bool requestLock(uint64_t lockId, hdb::locktable::LockMode mode); 43 | 44 | public: 45 | 46 | uint64_t transactionId; 47 | std::set involvedLockServers; 48 | std::set involvedVoteServers; 49 | 50 | uint64_t transaction_time; 51 | std::chrono::time_point start_time; 52 | 53 | 54 | bool voteNeeded; 55 | 56 | protected: 57 | const bool timestampordering; 58 | hdb::communication::Communicator *communicator; 59 | hdb::stats::ClientStats *stats; 60 | 61 | uint32_t globalRank; 62 | uint32_t *lockServerGlobalRanks; 63 | uint32_t locksPerWarehouse; 64 | const bool randomLockAssign; 65 | const uint32_t globalNumberOfWarehouses; 66 | 67 | std::vector& warehouseToLockServer; 68 | protected: 69 | 70 | hdb::messages::AbortTransaction abortRequest; 71 | hdb::messages::TransactionEnd endTransaction; 72 | hdb::messages::VoteRequest voteRequest; 73 | hdb::messages::LockRequest lockRequest; 74 | 75 | }; 76 | 77 | } /* namespace transactions */ 78 | } /* namespace hdb */ 79 | 80 | #endif /* SRC_HDB_TRANSACTIONS_TRANSACTIONMANAGER_H_ */ 81 | -------------------------------------------------------------------------------- /data/processing/transaction-throughput.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import pandas as pd 5 | 6 | from exp_helpers import MEASURES, summarize 7 | 8 | parser = argparse.ArgumentParser() 9 | parser.add_argument('-i', '--input', help='Input .hdf5 file') 10 | parser.add_argument('-o', '--output', help='Output .csv file') 11 | parser.add_argument('-s', '--summarize', action='store_true', 12 | help='Summarize runs of the same configuration?') 13 | args = parser.parse_args() 14 | 15 | # Open data 16 | df = pd.read_hdf(args.input) 17 | dimensions = [c for c in df.columns.values if c not in MEASURES] 18 | 19 | # Project to interesting attributes 20 | df = df[dimensions + ['ClientTotalTransactions', 'ClientNewOrderTransactions', 'ClientExecutionTime', 21 | 'ClientTransactionsCommitted']] 22 | 23 | # Average per run 24 | df = df.groupby(by=dimensions) \ 25 | .agg({'ClientTotalTransactions': 'sum', 26 | 'ClientNewOrderTransactions': 'sum', 27 | 'ClientTransactionsCommitted': 'sum', 28 | 'ClientExecutionTime': 'mean', 29 | }) \ 30 | .reset_index() 31 | 32 | # Compute successful NO transactions as estimate from commit ratio and total NO transactions 33 | if 'ClientNewOrderTransactionsCommitted' not in df.columns.values: 34 | df['ClientNewOrderTransactionsCommitted'] = float('NaN') 35 | df['SystemCommitRate'] = df['ClientTransactionsCommitted'] / df['ClientTotalTransactions'] 36 | missing_successful_no = df['ClientNewOrderTransactionsCommitted'].isna() 37 | df.loc[missing_successful_no, 'ClientNewOrderTransactionsCommitted'] = \ 38 | (df['ClientNewOrderTransactions'] * df['SystemCommitRate'])[missing_successful_no] 39 | 40 | # Derive other measures 41 | df['SystemTransactionThroughput'] = df['ClientTotalTransactions'] / df['ClientExecutionTime'] 42 | df['SystemNewOrderTransactionThroughput'] = df['ClientNewOrderTransactions'] / df['ClientExecutionTime'] 43 | df['SystemSuccessfulTransactionThroughput'] = df['ClientTransactionsCommitted'] / df['ClientExecutionTime'] 44 | df['SystemSuccessfulNewOrderTransactionThroughput'] = df['ClientNewOrderTransactionsCommitted'] / df['ClientExecutionTime'] 45 | 46 | # Average per configuration 47 | if args.summarize: 48 | df = summarize(df) 49 | 50 | # Write result 51 | df.sort_values(ascending=[True, True, False], by=['num_server_agents_per_node', 'percent_remote', 'num_nodes']) \ 52 | .to_csv(args.output, index=False) 53 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/stats/ClientStats.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ClientStats.h 3 | * 4 | * Created on: Apr 22, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_STATS_CLIENTSTATS_H_ 9 | #define SRC_HDB_STATS_CLIENTSTATS_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #define CLIENT_STAT_TAG (1<<2) 21 | 22 | namespace hdb { 23 | namespace stats { 24 | 25 | class ClientStats { 26 | 27 | public: 28 | 29 | ClientStats(); 30 | virtual ~ClientStats(); 31 | 32 | public: 33 | 34 | void sendDataToRoot(); 35 | void dumpToFile(FILE *output); 36 | 37 | public: 38 | 39 | uint32_t globalRank; 40 | 41 | public: 42 | 43 | void startDataAccess(); 44 | void stopDataAccess(); 45 | uint64_t accumulatedDataAccessTime; 46 | 47 | public: 48 | 49 | void startLocking(); 50 | void stopLocking(); 51 | void issuedLockRequest(hdb::messages::LockRequest *request, bool remoteServer); 52 | void receivedLockAnswer(hdb::messages::LockGrant *grant); 53 | 54 | uint64_t accumulatedLockingTime; 55 | uint64_t totalRequestedLocksByType[hdb::locktable::LockMode::MODE_COUNT]; 56 | uint64_t totalLocksRequests; 57 | uint64_t totalRemoteLocks; 58 | uint64_t totalLocalLocks; 59 | uint64_t totalDeniedLocks; 60 | uint64_t totalGrantedLocks; 61 | 62 | #ifdef USE_LOGGING 63 | uint64_t lockRequestTotalTimeAccumulated; 64 | uint64_t lockRequestNetworkTimeAccumulated; 65 | uint64_t lockRequestQueueingTimeAccumulated; 66 | uint64_t lockRequestServerProcessingTimeAccumulated; 67 | #endif 68 | 69 | public: 70 | 71 | void startVote(); 72 | void stopVote(bool outcome); 73 | 74 | uint64_t accumulatedVotingTime; 75 | uint64_t totalVotes; 76 | uint64_t totalVotesYes; 77 | uint64_t totalVotesNo; 78 | 79 | public: 80 | 81 | void startTransactionEnd(bool isNewOrder, uint64_t numberOfInvolvedServers); 82 | void stopTransactionEnd(bool outcome, bool isNewOrder); 83 | 84 | uint64_t accumulatedEndingTime; 85 | uint64_t totalTransactions; 86 | uint64_t totalTransactionsCommitted; 87 | uint64_t totalTransactionsAborted; 88 | uint64_t totalNewOrderTransactions; 89 | uint64_t totalNewOrderTransactionsCommitted; 90 | uint64_t totalServersInvolved; 91 | 92 | 93 | public: 94 | 95 | void startExecution(); 96 | void stopExecution(); 97 | 98 | uint64_t executionTime; 99 | 100 | protected: 101 | 102 | struct timeval executionStart; // 103 | struct timeval start; // 104 | 105 | }; 106 | 107 | } /* namespace stats */ 108 | } /* namespace hdb */ 109 | 110 | #endif /* SRC_HDB_STATS_CLIENTSTATS_H_ */ 111 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/communication/SendReceiveCommunicator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SendReceiveCommunicator.cpp 3 | * 4 | * Created on: Apr 30, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include "SendReceiveCommunicator.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace hdb { 18 | namespace communication { 19 | 20 | SendReceiveCommunicator::SendReceiveCommunicator(hdb::configuration::SystemConfig *config): comdelay(config->comdelay) { 21 | 22 | numberOfProcessesPerMachine = config->localNumberOfProcesses; 23 | localMachineId = config->globalRank / numberOfProcessesPerMachine; 24 | globalMachineId = config->globalRank; 25 | 26 | 27 | this->Slots = (config->isLockTableAgent) ? (config->globalNumberOfProcesses - config->globalNumberOfLockTableAgents) : (1); 28 | 29 | receiveBuffer = (void**)malloc(sizeof(void*)*Slots); 30 | for(uint32_t i=0; i < Slots; i++){ 31 | receiveBuffer[i] = malloc(MAX_MESSAGE_SIZE); 32 | } 33 | 34 | requests = (MPI_Request*)malloc(sizeof(MPI_Request)*Slots); 35 | for(uint32_t i=0; i < Slots; i++){ 36 | MPI_Irecv(receiveBuffer[i],MAX_MESSAGE_SIZE, MPI_BYTE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &requests[i]); 37 | } 38 | 39 | } 40 | 41 | SendReceiveCommunicator::~SendReceiveCommunicator() { 42 | for(uint32_t i = 0; i< Slots; i++){ 43 | MPI_Cancel(&requests[i]); 44 | free(receiveBuffer[i]); 45 | } 46 | free(receiveBuffer); 47 | free(requests); 48 | 49 | } 50 | 51 | bool SendReceiveCommunicator::sendMessage(hdb::messages::Message* message, uint32_t targetGlobalRank) { 52 | 53 | 54 | bool islocal = targetGlobalRank/numberOfProcessesPerMachine == localMachineId; 55 | if(!islocal && this->comdelay != 0){ 56 | auto const sleep_end_time = std::chrono::high_resolution_clock::now() + 57 | std::chrono::nanoseconds(this->comdelay); 58 | while (std::chrono::high_resolution_clock::now() < sleep_end_time); 59 | } 60 | MPI_Send(message, message->messageSize, MPI_BYTE, targetGlobalRank, 0, MPI_COMM_WORLD); 61 | 62 | return islocal; 63 | } 64 | 65 | hdb::messages::Message* SendReceiveCommunicator::getMessage() { 66 | 67 | int flag; 68 | int indx; 69 | MPI_Testany(Slots, requests, &indx, &flag, MPI_STATUS_IGNORE); 70 | if(flag){ 71 | MPI_Irecv(receiveBuffer[indx],MAX_MESSAGE_SIZE, MPI_BYTE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &requests[indx]); 72 | return (hdb::messages::Message*) receiveBuffer[indx]; 73 | } 74 | return NULL; 75 | } 76 | 77 | hdb::messages::Message* SendReceiveCommunicator::getMessageBlocking() { 78 | int indx; 79 | MPI_Waitany(Slots, requests, &indx, MPI_STATUS_IGNORE); 80 | MPI_Irecv(receiveBuffer[indx],MAX_MESSAGE_SIZE, MPI_BYTE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &requests[indx]); 81 | return (hdb::messages::Message*) receiveBuffer[indx]; 82 | } 83 | 84 | } /* namespace communication */ 85 | } /* namespace hdb */ 86 | -------------------------------------------------------------------------------- /workload-traces/mysql/tpcc/parse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import fileinput 4 | import re 5 | import json 6 | 7 | bootup_stripped = False 8 | 9 | for line in fileinput.input(): 10 | if line.strip().endswith('ready for connections.'): 11 | bootup_stripped = True 12 | continue 13 | 14 | if not bootup_stripped: 15 | continue 16 | 17 | if line.startswith('UNLOCK RECORD ') or line.startswith('RECORD '): 18 | result = re.match('(UNLOCK )?RECORD LOCK space ([0-9]*) page_no ([0-9]*) heap_no ([0-9]*) (.*?(/\\* Partition `p([0-9]*)` \\*/)?) trx id ([0-9]*) lock_mode ([A-Z]*)( ORDINARY)?( GAP)?( REC_NOT_GAP)?( INSERT_INTENTION)?', line) 19 | 20 | if not result: 21 | print("Warning: line not in expected format: " + line) 22 | continue 23 | 24 | action = 'unlock' if result.group(1) else 'lock' 25 | space_no = int(result.group(2)) 26 | page_no = int(result.group(3)) 27 | heap_no = int(result.group(4)) 28 | object_name = result.group(5) 29 | partition_no = int(result.group(7)) 30 | trx_id = int(result.group(8)) 31 | lock_mode = result.group(9) 32 | ordinary = True if result.group(10) else False 33 | gap = True if result.group(11) else False 34 | recnotgap = True if result.group(12) else False 35 | insertint = True if result.group(13) else False 36 | 37 | print(json.dumps({ 'action' : action, 38 | 'type': 'record', 39 | 'space_no' : space_no, 40 | 'page_no' : page_no, 41 | 'heap_no' : heap_no, 42 | 'object_name' : object_name, 43 | 'partition_no' : partition_no, 44 | 'trx_id' : trx_id, 45 | 'lock_mode' : lock_mode, 46 | 'ordinary' : ordinary, 47 | 'gap' : gap, 48 | 'recnotgap' : recnotgap, 49 | 'insertint' : insertint })) 50 | 51 | if line.startswith('UNLOCK TABLE ') or line.startswith('TABLE '): 52 | # TABLE LOCK table `tpcc10`.`warehouse` /* Partition `p5` */ trx id 4072790 lock_mode IX 53 | result = re.match('(UNLOCK )?TABLE LOCK (.*?(/\\* Partition `p([0-9]*)` \\*/)?) trx id ([0-9]*) lock_mode ([-A-Z]*)', line) 54 | 55 | if not result: 56 | print("Warning: line not in expected format: " + line) 57 | continue 58 | 59 | action = 'unlock' if result.group(1) else 'lock' 60 | object_name = result.group(2) 61 | partition_no = int(result.group(4)) 62 | trx_id = int(result.group(5)) 63 | lock_mode = result.group(6) 64 | 65 | print(json.dumps({ 'action' : action, 66 | 'type': 'table', 67 | 'object_name' : object_name, 68 | 'partition_no' : partition_no, 69 | 'trx_id' : trx_id, 70 | 'lock_mode' : lock_mode })) 71 | -------------------------------------------------------------------------------- /data/plots/locking-throughput-new.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import itertools 5 | import pandas as pd 6 | from matplotlib import pyplot as plt, font_manager 7 | 8 | from exp_helpers import MEASURES 9 | 10 | parser = argparse.ArgumentParser() 11 | parser.add_argument('-p', '--paper', action='store_true', 12 | help='Produce only configurations used in paper.') 13 | args = parser.parse_args() 14 | 15 | # Read data and group by configs (=everything that is neither a series nor on an axis) 16 | df = pd.read_csv('./locking-throughput.csv').fillna('') 17 | dimensions = [c for c in sorted(df.columns.values) if c not in MEASURES] 18 | 19 | if args.paper: 20 | df = df[(df['network_delay'] == '') & (df['num_warehouses'] == 2048)] 21 | 22 | plot_dims = ['num_tx_agents', 'num_cores', 'num_nodes', 'num_server_agents', 'isolation_mode', 23 | 'mechanism', 'option1', 'option2'] 24 | config_dims = [d for d in dimensions if d not in plot_dims] 25 | nonunique_config_dims = [d for d in config_dims if len(df[d].unique()) > 1] 26 | 27 | groups = df.groupby(by=config_dims) 28 | 29 | # Produce a plot for each config 30 | for g in groups: 31 | config_name = "".join(["-{}={}".format(k, v) for k, v in zip(config_dims, list(g[0])) 32 | if k in nonunique_config_dims]) 33 | 34 | plt.style.use(['./ethplot.mplstyle']) 35 | markers = ['o', 'x', '*', '^'] 36 | linestyles = ['-', '--', '-.'] 37 | labels = {'readcommitted': ' (RC)', 38 | 'serializable': ' (Ser)', 39 | 'repeatableread': ' (RR)'} 40 | prop_cycle = plt.rcParams['axes.prop_cycle'] 41 | colors = prop_cycle.by_key()['color'] 42 | 43 | fig = plt.figure() 44 | ax = fig.add_subplot(1, 1, 1) 45 | 46 | ax.set_xlabel('Transaction Processing Agents') 47 | ax.set_ylabel('Throughput [million requests/sec]') 48 | 49 | ax.get_xaxis().tick_bottom() 50 | ax.get_yaxis().tick_left() 51 | 52 | df_g = g[1] 53 | 54 | lines = [] 55 | for i, mode in enumerate(sorted(df['isolation_mode'].unique())): 56 | if mode == '': continue 57 | linestyle = linestyles[i] 58 | 59 | for j, mechanism in enumerate(sorted(df['mechanism'].unique())): 60 | df_m = df_g[(df_g['isolation_mode'] == mode) & (df_g['mechanism'] == mechanism)] 61 | 62 | if len(df_m.index) == 0: continue 63 | 64 | yAxisPoints = df_m['SystemLockingThroughput mean'] 65 | yAxisError = df_m['SystemLockingThroughput ci950'] 66 | xAxisPoints = df_m['num_tx_agents'] 67 | 68 | marker = markers[j] 69 | color = colors[j] 70 | label = mechanism.upper() + labels[mode] 71 | line = ax.errorbar(xAxisPoints, yAxisPoints, yAxisError, 72 | linestyle=linestyle, marker=marker, 73 | linewidth=2, markersize=6, label=label) 74 | lines.append(line) 75 | 76 | ax.legend(handles=lines, loc='upper left') 77 | 78 | ax.set_xlim(left=0) 79 | ax.set_ylim(bottom=0) 80 | 81 | X = df_g['num_tx_agents'].unique() 82 | X = [x for x in X if x in [16, 128, 256, 512, 1024, 2048]] 83 | ax.set_xticks(X) 84 | 85 | plt.savefig("./locking-throughput-new{}.pdf".format(config_name), format='pdf') 86 | plt.close() 87 | -------------------------------------------------------------------------------- /data/plots/abortion-rate-warehouses.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import itertools 5 | import pandas as pd 6 | import matplotlib; matplotlib.use('Agg') 7 | from matplotlib import pyplot as plt, font_manager 8 | from exp_helpers import MEASURES 9 | 10 | parser = argparse.ArgumentParser() 11 | parser.add_argument('-p', '--paper', action='store_true', 12 | help='Produce only configurations used in paper.') 13 | args = parser.parse_args() 14 | 15 | ############## DATA ################ 16 | 17 | # Read data and group by configs (=everything that is neither a series nor on an axis) 18 | df = pd.read_csv('./transaction-throughput.csv').fillna('') 19 | dimensions = [c for c in sorted(df.columns.values) if c not in MEASURES] 20 | 21 | df = df[df['workload'] == 'tpcc'] 22 | 23 | if args.paper: 24 | df = df[(df['network_delay'] == '') & (df['num_warehouses'] == 64)] 25 | 26 | plot_dims = ['num_tx_agents', 'num_cores', 'num_nodes', 'num_server_agents', 27 | 'mechanism', 'option1', 'option2', 'isolation_mode'] 28 | config_dims = [d for d in dimensions if d not in plot_dims] 29 | nonunique_config_dims = [d for d in config_dims if len(df[d].unique()) > 1] 30 | 31 | groups = df.groupby(by=config_dims) 32 | 33 | # Produce a plot for each config 34 | for g in groups: 35 | config_name = "".join(["-{}={}".format(k, v) for k, v in zip(config_dims, list(g[0])) 36 | if k in nonunique_config_dims]) 37 | 38 | plt.style.use(['./ethplot.mplstyle']) 39 | markers = ['o', 'x', '*', '^'] 40 | linestyles = ['-', '--', ':'] 41 | labels = {'readcommitted': ' (RC)', 42 | 'serializable': ' (Ser)', 43 | 'repeatableread': ' (RR)'} 44 | prop_cycle = plt.rcParams['axes.prop_cycle'] 45 | colors = prop_cycle.by_key()['color'] 46 | 47 | fig = plt.figure() 48 | ax = fig.add_subplot(1, 1, 1) 49 | 50 | ax.set_xlabel('Transaction Processing Agents') 51 | ax.set_ylabel('Abort Rate [%]') 52 | 53 | ax.get_xaxis().tick_bottom() 54 | ax.get_yaxis().tick_left() 55 | ax.set_xscale('log') 56 | 57 | df_g = g[1] 58 | 59 | # Plot total transaction throughput 60 | lines = [] 61 | for i, mode in enumerate(df['isolation_mode'].unique()): 62 | if mode == '': continue 63 | linestyle = linestyles[i] 64 | 65 | for j, mechanism in enumerate(sorted(df['mechanism'].unique())): 66 | df_m = df_g[(df_g['isolation_mode'] == mode) & (df_g['mechanism'] == mechanism)] 67 | 68 | if len(df_m.index) == 0: continue 69 | 70 | yAxisPoints1 = (1 - df_m['SystemCommitRate mean']) * 100 71 | xAxisPoints1 = df_m['num_tx_agents'] 72 | 73 | label = mechanism.upper() + labels[mode] 74 | marker = markers[j] 75 | color = colors[j] 76 | line = ax.errorbar(xAxisPoints1, yAxisPoints1, 77 | linewidth=2, markersize=6, label=label, 78 | color=color, linestyle=linestyle, marker=marker) 79 | lines.append(line) 80 | 81 | ax.legend(handles=lines) 82 | 83 | X = df_g['num_tx_agents'].unique() 84 | ax.set_xticks(X) 85 | ax.set_xticklabels(X) 86 | ax.set_ylim([0, 100]) 87 | 88 | plt.savefig("./abortion-rate-warehouses{}.pdf".format(config_name), format='pdf') 89 | plt.close() 90 | -------------------------------------------------------------------------------- /data/plots/network-delay.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import itertools 4 | import pandas as pd 5 | from cycler import cycler 6 | from matplotlib import pyplot as plt, font_manager, transforms 7 | from exp_helpers import MEASURES 8 | 9 | # Read data and group by configs (=everything that is neither a series nor on an axis) 10 | df = pd.read_csv('./transaction-throughput.csv').fillna('') 11 | dimensions = [c for c in sorted(df.columns.values) if c not in MEASURES] 12 | 13 | df = df[df['network_delay'] != ''] 14 | df['network_delay'] = df['network_delay'] / 1000 15 | 16 | plot_dims = ['network_delay', 'mechanism', 'isolation_mode', 'option1', 'option2'] 17 | config_dims = [d for d in dimensions if d not in plot_dims] 18 | nonunique_config_dims = [d for d in config_dims if len(df[d].unique()) > 1] 19 | 20 | groups = df.groupby(by=config_dims) 21 | 22 | # Produce a plot for each config 23 | for g in groups: 24 | config_name = "".join(["-{}={}".format(k, v) for k, v in zip(config_dims, list(g[0])) 25 | if k in nonunique_config_dims]) 26 | 27 | df_g = g[1] 28 | 29 | if len(df_g.index) < 2: continue 30 | 31 | plt.style.use(['./ethplot.mplstyle']) 32 | markers = ['o', 'x', '*', '^'] 33 | linestyles = ['-', '--', ':'] 34 | labels = {'readcommitted': ' (RC)', 35 | 'serializable': ' (Ser)', 36 | 'repeatableread': ' (RR)'} 37 | prop_cycle = plt.rcParams['axes.prop_cycle'] 38 | colors = prop_cycle.by_key()['color'] 39 | 40 | fig = plt.figure() 41 | ax = fig.add_subplot(1, 1, 1) 42 | ax.set_xscale("log") 43 | 44 | ax.set_xlabel('Network delay [microsec]') 45 | ax.set_ylabel('Throughput [million transactions/sec]') 46 | 47 | trans = transforms.blended_transform_factory(ax.transData, ax.transAxes) 48 | for x, label in [(1, 'IB EDR'), (16, 'AWS EFA')]: 49 | ax.axvline(x, color='red') 50 | plt.text(x, 1.01, label, transform=trans, va='bottom', ha='center') 51 | 52 | ax.get_xaxis().tick_bottom() 53 | ax.get_yaxis().tick_left() 54 | 55 | lines = [] 56 | for i, mode in enumerate(sorted(df['isolation_mode'].unique())): 57 | if mode == '': continue 58 | linestyle = linestyles[i] 59 | 60 | for j, mechanism in enumerate(sorted(df['mechanism'].unique())): 61 | df_m = df_g[(df_g['isolation_mode'] == mode) & (df_g['mechanism'] == mechanism)] 62 | 63 | if len(df_m.index) == 0: continue 64 | 65 | xAxisPoints = df_m['network_delay'] 66 | yAxisPoints = df_m['SystemTransactionThroughput mean'] 67 | yAxisError = df_m['SystemTransactionThroughput ci950'] 68 | 69 | marker = markers[j] 70 | color = colors[j] 71 | label = mechanism.upper() + labels[mode] 72 | 73 | line = ax.errorbar(xAxisPoints, yAxisPoints, yAxisError, 74 | color=color, linestyle=linestyle, marker=marker, 75 | linewidth=2, markersize=6, label=label) 76 | lines.append(line) 77 | 78 | ax.legend(handles=lines) 79 | 80 | X = [x for x in df_g['network_delay'].unique() if x != 0] 81 | ax.set_xticks(X) 82 | ax.set_xticklabels(['{:.4g}'.format(x) for x in X]) 83 | ax.set_ylim(bottom=0) 84 | 85 | plt.savefig("./network-delay{}.pdf".format(config_name), format='pdf') 86 | plt.close() 87 | -------------------------------------------------------------------------------- /data/README.md: -------------------------------------------------------------------------------- 1 | ## Overview 2 | 3 | The plots are produced in a pipeline consisting of the following steps: 4 | 5 | 1. Extract the numbers from the experiment traces as JSON and combine them into a single JSON lines file. 6 | 1. Convert that file into an HDF5 file for faster processing. 7 | 1. For each plot, extract the numbers to plot into a CSV file. 8 | 1. Produce the plots from the CSV files. 9 | 10 | ## Prerequesites 11 | 12 | Install the Python packages from the `requirements.txt` file: 13 | 14 | ```bash 15 | pip3 install -r requirements.txt 16 | ``` 17 | 18 | ## Collect data from experiment traces into JSON lines 19 | 20 | The format of the traces has slightly changed between the version of the paper and the version in this repository. 21 | Hence, there are two different scripts that extract the data from the traces. 22 | All subsequent steps are the same. 23 | 24 | To use the traces that were used in the paper (which are stored the `traces_paper` directory), run the following command: 25 | 26 | ```bash 27 | ./collect_data_paper.sh 28 | ``` 29 | 30 | To use traces that you produced yourself, extract the trace files into the `traces` directory (without further subdirectories), 31 | then furn the following command: 32 | 33 | ```bash 34 | ./collect_data.sh 35 | ``` 36 | 37 | ## Convert JSON lines to HDF5 38 | 39 | Run the following command: 40 | 41 | ```bash 42 | ./jsonl2hdf5.py -i data.json -o data.hdf5 43 | ``` 44 | 45 | ## Extract CSV data for plotting 46 | 47 | There is roughly one script per plot that extracts the data required for the plot and stores it as a CSV file. 48 | Each script mainly consists of cleansing the data, selecting the interesting subset, deriving new measures, and a first summarization step. 49 | To run all scripts, use the following command 50 | (to extract the data for a single plot, just run the corresponding script manually): 51 | 52 | ```bash 53 | for script in ./processing/*.py 54 | do 55 | echo $script 56 | $script -i data.hdf5 -o ./plots/$(basename ${script%.py}).csv -s 57 | done 58 | ``` 59 | 60 | ## Produce plots 61 | 62 | There is one script per plot. 63 | To produce all plots, run the following command 64 | (to produce a single plot, just run the corresponding script manually **in the `plots` folder**): 65 | 66 | ```bash 67 | ( 68 | cd plots 69 | for script in ./*.py 70 | do 71 | echo $script 72 | $script --paper 73 | done 74 | ) 75 | ``` 76 | 77 | This produces a large number of plots. 78 | Below are the filenames of the files used for the paper 79 | given as ` -- `. 80 | The original name refers to the name given by the plot scripts 81 | when run on the data derived from the original traces. 82 | 83 | XXX: Update these 84 | 85 | * Figure 3a: `transaction-throughput-new-num_warehouses=2048.pdf` 86 | * Figure 3b: `locking-throughput-new.pdf` 87 | * Figure 4: `tx-breakdown-num_warehouses=2048.pdf` 88 | * Figure 5a: `transaction-throughput-new-num_warehouses=64.pdf` 89 | * Figure 5b: `transaction-throughput-new-num_warehouses=1024.pdf` 90 | * Figure 6a: `transaction-throughput-warehouses-mechanism=2pl-bw-option1=.pdf` 91 | * Figure 6b: `transaction-throughput-warehouses-mechanism=2pl-nw-option1=nowait.pdf` 92 | * Figure 6c: `transaction-throughput-warehouses-mechanism=to-option1=timestamp.pdf` 93 | * Figure 7a: `tx-breakdown-num_warehouses=64.pdf` 94 | * Figure 7b: `abortion-rate-warehouses.pdf` 95 | * Figure 8: `network-delay.pdf` 96 | -------------------------------------------------------------------------------- /data/plots/transaction-throughput-warehouses.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import itertools 5 | import pandas as pd 6 | from matplotlib import pyplot as plt, font_manager 7 | from exp_helpers import MEASURES 8 | 9 | parser = argparse.ArgumentParser() 10 | parser.add_argument('-p', '--paper', action='store_true', 11 | help='Produce only configurations used in paper.') 12 | args = parser.parse_args() 13 | 14 | ############## DATA ################ 15 | 16 | # Read data and group by configs (=everything that is neither a series nor on an axis) 17 | df = pd.read_csv('./transaction-throughput.csv').fillna('') 18 | dimensions = [c for c in sorted(df.columns.values) if c not in MEASURES] 19 | 20 | df = df[df['workload'] == 'tpcc'] 21 | 22 | if args.paper: 23 | df = df[(df['network_delay'] == '') & 24 | (df['isolation_mode'] == 'serializable') & 25 | (df['mechanism'] != '2pl-wd')] 26 | 27 | plot_dims = ['num_tx_agents', 'num_cores', 'num_nodes', 'num_server_agents', 'num_warehouses'] 28 | config_dims = [d for d in dimensions if d not in plot_dims] 29 | nonunique_config_dims = [d for d in config_dims if len(df[d].unique()) > 1] 30 | 31 | groups = df.groupby(by=config_dims) 32 | 33 | # Produce a plot for each config 34 | for g in groups: 35 | config_name = "".join(["-{}={}".format(k, v) for k, v in zip(config_dims, list(g[0])) 36 | if k in nonunique_config_dims]) 37 | 38 | plt.style.use(['./ethplot.mplstyle']) 39 | markers = ['o', 'x', '*', '^'] 40 | linestyles = ['-', '--', ':', '-.'] 41 | prop_cycle = plt.rcParams['axes.prop_cycle'] 42 | colors = prop_cycle.by_key()['color'] 43 | 44 | fig = plt.figure(figsize=(5, 4.5)) 45 | ax = fig.add_subplot(1, 1, 1) 46 | 47 | ax.set_xlabel('Transaction Processing Agents') 48 | ax.set_ylabel('Throughput\n[million successful transactions/sec]') 49 | 50 | ax.get_xaxis().tick_bottom() 51 | ax.get_yaxis().tick_left() 52 | ax.set_xscale("log") 53 | ax.set_yscale("log") 54 | 55 | df_g = g[1] 56 | 57 | # Plot total transaction throughput 58 | lines = [] 59 | X = set() 60 | num_warehouses = [int(n) for n in df['num_warehouses'].unique() if n != ''] 61 | for i, nwh in enumerate(sorted(num_warehouses)): 62 | linestyle = linestyles[i] 63 | 64 | df_m = df_g[df_g['num_warehouses'] == nwh] 65 | 66 | if len(df_m.index) == 0: continue 67 | 68 | yAxisPoints1 = df_m['SystemSuccessfulTransactionThroughput mean'] 69 | yAxisError1 = df_m['SystemSuccessfulTransactionThroughput ci950'] 70 | xAxisPoints1 = df_m['num_tx_agents'] 71 | 72 | X |= set(xAxisPoints1) 73 | 74 | label = "{} warehouses".format(nwh) 75 | marker = markers[i] 76 | color = colors[i] 77 | line = ax.errorbar(xAxisPoints1, yAxisPoints1, yAxisError1, 78 | linewidth=2, markersize=6, label=label, 79 | color=color, linestyle=linestyle, marker=marker) 80 | lines.append(line) 81 | 82 | ax.legend(handles=lines, loc='upper left') 83 | 84 | X = list(sorted(list(X))) 85 | ax.set_xticks(X) 86 | ax.set_xticklabels(X) 87 | Y = [2**(i-2) for i in range(8)] 88 | ax.set_yticks(Y) 89 | ax.set_yticklabels(Y) 90 | ax.set_ylim(bottom=0.15) 91 | 92 | plt.savefig("./transaction-throughput-warehouses{}.pdf".format(config_name), format='pdf') 93 | plt.close() 94 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/transactions/SimpleClient.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SimpleClient.cpp 3 | * 4 | * Created on: Apr 19, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include "SimpleClient.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | namespace hdb { 16 | namespace transactions { 17 | 18 | SimpleClient::SimpleClient(hdb::configuration::SystemConfig *config, uint64_t numberOfTransactions, uint64_t numberOfLocksPerTransaction, uint32_t remoteprob) : TransactionAgent(config) { 19 | 20 | this->numberOfTransactions = numberOfTransactions; 21 | this->numberOfLocksPerTransaction = numberOfLocksPerTransaction; 22 | this->remoteprob = remoteprob; 23 | 24 | uint32_t machineId = config->globalRank / config->localNumberOfProcesses; 25 | 26 | // first lock agent on this nodes 27 | uint32_t firstLockAgent = machineId * (config->globalNumberOfLockTableAgents / config->numberOfNodes); 28 | // last lock agent on this nodes 29 | uint32_t lastLockAgent = (machineId + 1)* (config->globalNumberOfLockTableAgents / config->numberOfNodes); 30 | 31 | this->tableRangeStart = 0; 32 | 33 | 34 | 35 | for(uint32_t i = 0; i < firstLockAgent; i++){ 36 | uint32_t locksOnThisAgent = config->AllLocksPerAgent[i]; 37 | this->tableRangeStart += locksOnThisAgent; 38 | } 39 | 40 | this->NumberOfLocksOnThisMachine = 0; 41 | for(uint32_t i = firstLockAgent; i < lastLockAgent; i++){ 42 | uint32_t locksOnThisAgent = config->AllLocksPerAgent[i]; 43 | this->NumberOfLocksOnThisMachine += locksOnThisAgent; 44 | } 45 | 46 | } 47 | 48 | SimpleClient::~SimpleClient() { 49 | 50 | } 51 | 52 | void hdb::transactions::SimpleClient::generate() { 53 | 54 | //std::random_device device; 55 | //std::mt19937 gen(123); 56 | //std::uniform_int_distribution randomLock(0, config->globalNumberOfLocks-1); 57 | //std::uniform_int_distribution randomMode(1, hdb::locktable::LockMode::MODE_COUNT-1); 58 | srand(123 + config->globalRank); 59 | 60 | for (uint64_t txId = 0; txId < numberOfTransactions; ++txId) { 61 | hdb::transactions::Transaction *transaction = new hdb::transactions::Transaction(); 62 | while (transaction->requests.size() < numberOfLocksPerTransaction) { 63 | uint64_t lockId = 0; 64 | bool lockIsRemote = (rand() % 100) < remoteprob; 65 | 66 | if (!lockIsRemote) { 67 | uint32_t localLockOffset = rand() % (NumberOfLocksOnThisMachine); 68 | lockId = tableRangeStart + localLockOffset; 69 | 70 | } else { 71 | do{ 72 | lockId = rand() % config->globalNumberOfLocks; 73 | }while(lockId >= tableRangeStart && (lockId < (tableRangeStart + NumberOfLocksOnThisMachine)) ); 74 | } 75 | 76 | hdb::locktable::LockMode mode = (hdb::locktable::LockMode) ((rand() % 5) + 1); 77 | 78 | // De-dublicate 79 | bool isInSet = false; 80 | for(uint64_t a=0; arequests.size(); ++a) { 81 | if(transaction->requests[a].first == lockId) { 82 | isInSet = true; 83 | break; 84 | } 85 | } 86 | 87 | if(!isInSet) { 88 | transaction->requests.push_back(lockid_mode_pair_t(lockId, mode)); 89 | } 90 | } 91 | 92 | transactions.push_back(*transaction); 93 | } 94 | 95 | } 96 | 97 | void hdb::transactions::SimpleClient::execute() { 98 | tpccExecute(0, numberOfTransactions); 99 | } 100 | 101 | } /* namespace transactions */ 102 | } /* namespace hdb */ 103 | 104 | 105 | -------------------------------------------------------------------------------- /data/plots/transaction-throughput-new.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import itertools 5 | import pandas as pd 6 | from matplotlib import pyplot as plt, font_manager 7 | from exp_helpers import MEASURES 8 | 9 | parser = argparse.ArgumentParser() 10 | parser.add_argument('-p', '--paper', action='store_true', 11 | help='Produce only configurations used in paper.') 12 | args = parser.parse_args() 13 | 14 | ############## DATA ################ 15 | 16 | # Read data and group by configs (=everything that is neither a series nor on an axis) 17 | df = pd.read_csv('./transaction-throughput.csv').fillna('') 18 | dimensions = [c for c in sorted(df.columns.values) if c not in MEASURES] 19 | 20 | if args.paper: 21 | df = df[(df['network_delay'] == '') & 22 | ((df['num_warehouses'] == 64) | 23 | (df['num_warehouses'] == 1024) | 24 | (df['num_warehouses'] == 2048))] 25 | 26 | plot_dims = ['num_tx_agents', 'num_cores', 'num_nodes', 'num_server_agents', 'isolation_mode', 27 | 'mechanism', 'option1', 'option2'] 28 | config_dims = [d for d in dimensions if d not in plot_dims] 29 | nonunique_config_dims = [d for d in config_dims if len(df[d].unique()) > 1] 30 | 31 | groups = df.groupby(by=config_dims) 32 | 33 | # Produce a plot for each config 34 | for g in groups: 35 | config_name = "".join(["-{}={}".format(k, v) for k, v in zip(config_dims, list(g[0])) 36 | if k in nonunique_config_dims]) 37 | 38 | plt.style.use(['./ethplot.mplstyle']) 39 | markers = ['o', 'x', '*', '^'] 40 | linestyles = ['-', '--', ':'] 41 | labels = {'readcommitted': ' (RC)', 42 | 'serializable': ' (Ser)', 43 | 'repeatableread': ' (RR)'} 44 | prop_cycle = plt.rcParams['axes.prop_cycle'] 45 | colors = prop_cycle.by_key()['color'] 46 | 47 | fig = plt.figure() 48 | ax = fig.add_subplot(1, 1, 1) 49 | 50 | ax.set_xlabel('Transaction Processing Agents') 51 | ax.set_ylabel('Throughput [million successful transactions/sec]') 52 | 53 | ax.get_xaxis().tick_bottom() 54 | ax.get_yaxis().tick_left() 55 | 56 | df_g = g[1] 57 | 58 | # Plot total transaction throughput 59 | lines = [] 60 | for i, mode in enumerate(df['isolation_mode'].unique()): 61 | if mode == '': continue 62 | linestyle = linestyles[i] 63 | 64 | for j, mechanism in enumerate(sorted(df['mechanism'].unique())): 65 | df_m = df_g[(df_g['isolation_mode'] == mode) & (df_g['mechanism'] == mechanism)] 66 | 67 | if len(df_m.index) == 0: continue 68 | 69 | yAxisPoints1 = df_m['SystemSuccessfulTransactionThroughput mean'] 70 | yAxisError1 = df_m['SystemSuccessfulTransactionThroughput ci950'] 71 | xAxisPoints1 = df_m['num_tx_agents'] 72 | 73 | label = mechanism.upper() + labels[mode] 74 | marker = markers[j] 75 | color = colors[j] 76 | line = ax.errorbar(xAxisPoints1, yAxisPoints1, yAxisError1, 77 | color=color, linestyle=linestyle, marker=marker, 78 | linewidth=2, markersize=6, label=label) 79 | lines.append(line) 80 | 81 | X = df_g['num_tx_agents'].unique() 82 | X = [x for x in X if x in [16, 128, 256, 512, 1024, 2048]] 83 | ax.set_xticks(X) 84 | ax.set_xlim(left=0) 85 | ax.set_ylim(bottom=0) 86 | 87 | ncol = 1 88 | if df_m['SystemSuccessfulTransactionThroughput mean'].max() < 5: 89 | ax.set_ylim(top=3.2) 90 | ncol = 3 91 | 92 | ax.legend(handles=lines, loc='upper left', ncol=ncol) 93 | 94 | 95 | plt.savefig("./transaction-throughput-new{}.pdf".format(config_name), format='pdf') 96 | plt.close() 97 | -------------------------------------------------------------------------------- /data/_exp_helpers.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | import scipy 3 | import scipy.stats 4 | 5 | MEASURES = [ 6 | # Measures from trace files (.exp) 7 | 'ClientGlobalRank', 8 | 'ClientDataAccessTimeAccumulated', 9 | 'ClientLockingTimeAccumulated', 10 | 'ClientLocksNL', 11 | 'ClientLocksIS', 12 | 'ClientLocksIX', 13 | 'ClientLocksS', 14 | 'ClientLocksSIX', 15 | 'ClientLocksX', 16 | 'ClientTotalLocks', 17 | 'ClientRemoteLocks', 18 | 'ClientLocalLocks', 19 | 'ClientDeniedLocks', 20 | 'ClientGrantedLocks', 21 | 'ClientLockRequestTotalTime', 22 | 'ClientLockRequestNetworkTime', 23 | 'ClientLockRequestQueueingTime', 24 | 'ClientLockRequestServerTime', 25 | 'ClientVotingTimeAccumulated', 26 | 'ClientTotalVotes', 27 | 'ClientVotesYes', 28 | 'ClientVotesNo', 29 | 'ClientEndingTimeAccumulated', 30 | 'ClientTotalTransactions', 31 | 'ClientTransactionsCommitted', 32 | 'ClientTransactionsAborted', 33 | 'ClientNewOrderTransactions', 34 | 'ClientNewOrderTransactionsCommitted', 35 | 'ClientServersContacted', 36 | 'ClientExecutionTime', 37 | # Measures added by round-trip to feather 38 | 'index', 39 | # Measures added by scripts 40 | 'ClientDataAccessTimePerTx', 41 | 'ClientEndingTimePerTx', 42 | 'ClientExecutionTimePerTx', 43 | 'ClientLockRequestNetworkTimePerLock', 44 | 'ClientLockRequestQueueingTimePerLock', 45 | 'ClientLockRequestServerTimePerLock', 46 | 'ClientLockingTimePerTx', 47 | 'ClientOtherTimePerTx', 48 | 'ClientServersContactedPerTx', 49 | 'ClientVotingTimePerTx', 50 | 'ClientVotingTimePerVote', 51 | 'SystemCommitRate', 52 | 'SystemLockingThroughput', 53 | 'SystemNewOrderTransactionThroughput', 54 | 'SystemSuccessfulTransactionThroughput', 55 | 'SystemSuccessfulNewOrderTransactionThroughput', 56 | 'SystemTransactionThroughput', 57 | ] 58 | MEASURES = MEASURES +\ 59 | [m + " mean" for m in MEASURES] + \ 60 | [m + " count" for m in MEASURES] + \ 61 | [m + " ci950" for m in MEASURES] 62 | 63 | DIMENSIONS = [ 64 | 'distribution', 65 | 'isolation_mode', 66 | 'mechanism', 67 | 'network_delay', 68 | 'num_cores', 69 | 'num_cores_per_node', 70 | 'num_nodes', 71 | 'num_server_agents', 72 | 'num_server_agents_per_node', 73 | 'num_tx_agents', 74 | 'num_tx_agents_per_node', 75 | 'num_warehouses', 76 | 'option1', 77 | 'option2', 78 | 'percent_remote', 79 | 'workload', 80 | '__filename', 81 | ] 82 | 83 | 84 | def summarize(df): 85 | unkown_columns = [c for c in df.columns.values if c not in MEASURES + DIMENSIONS] 86 | if unkown_columns: 87 | raise RuntimeError('Unknown columns "{}"'.format(unkown_columns)) 88 | 89 | def error(confidence=0.95): 90 | def error_(data): 91 | a = 1.0 * numpy.array(data) 92 | n = len(a) 93 | if n == 1: 94 | return 0 95 | m, se = numpy.mean(a), scipy.stats.sem(a) 96 | return se * scipy.stats.t._ppf((1+confidence)/2., n-1) 97 | error_.__name__ = 'ci' + ''.join([c for c in str(100 * confidence) if c.isdigit()]) 98 | return error_ 99 | 100 | dimensions = [c for c in df.columns.values if c in DIMENSIONS] 101 | aggs = {c : ['mean', 'count', error()] for c in df.columns.values if c in MEASURES} 102 | 103 | df = df.groupby(by=[c for c in dimensions if c != '__filename']) \ 104 | .agg(aggs).reset_index() 105 | df.columns = [' '.join(col).strip() for col in df.columns.values] 106 | 107 | return df 108 | 109 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/locktable/LockTableAgent.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * LockTableAgent.cpp 3 | * 4 | * Created on: Mar 27, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include "LockTableAgent.h" 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | namespace hdb { 24 | namespace locktable { 25 | 26 | LockTableAgent::LockTableAgent(hdb::configuration::SystemConfig *config) { 27 | 28 | this->config = config; 29 | this->communicator = new hdb::communication::Communicator(config); 30 | 31 | uint32_t lockPerLockAgent = config->locksOnThisAgent; 32 | DLOG("LockTableAgent","Lockagent[%d] has %d locks" ,config->internalRank, lockPerLockAgent); 33 | if( config->waitdie ){ 34 | this->table = new hdb::locktable::TableWaitDie(lockPerLockAgent, communicator); 35 | } else if(config->nowait){ 36 | this->table = new hdb::locktable::TableNoWait(lockPerLockAgent, communicator); 37 | } else if(config->timestamp){ 38 | this->table = new hdb::locktable::TableTimestamp(lockPerLockAgent, communicator); 39 | } else { // simple 2pl 40 | this->table = new hdb::locktable::Table2PL(lockPerLockAgent, communicator); 41 | } 42 | 43 | 44 | this->remainingClients = config->globalNumberOfProcesses - config->globalNumberOfLockTableAgents; 45 | } 46 | 47 | LockTableAgent::~LockTableAgent() { 48 | 49 | delete table; 50 | delete communicator; 51 | 52 | } 53 | 54 | void LockTableAgent::execute() { 55 | 56 | DLOG("LockTableAgent", "Process %d running lock table %d", config->globalRank, config->internalRank); 57 | 58 | hdb::messages::Message *message = NULL; 59 | 60 | uint32_t handleCounter = 0; 61 | while (remainingClients > 0) { 62 | message = communicator->getMessage(); 63 | if (message != NULL) { 64 | processMessage(message); 65 | } 66 | ++handleCounter; 67 | if(handleCounter % 1024 == 0) { 68 | table->handleExpiredRequests(); 69 | } 70 | } 71 | 72 | } 73 | 74 | void LockTableAgent::processMessage(hdb::messages::Message* message) { 75 | 76 | DLOG("LockTableAgent", "Received message %d, %d, %d", message->messageType, message->clientGlobalRank, message->transactionNumber); 77 | 78 | switch (message->messageType) { 79 | 80 | case hdb::messages::MessageType::LOCK_REQUEST_MESSAGE: { 81 | #ifdef USE_LOGGING 82 | ((hdb::messages::LockRequest *) message)->serverReceiveTime = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); 83 | #endif 84 | table->insertNewRequest((hdb::messages::LockRequest *) message); 85 | break; 86 | } 87 | 88 | case hdb::messages::MessageType::LOCK_RELEASE_MESSAGE: { 89 | table->releaseLock((hdb::messages::LockRelease *) message); 90 | break; 91 | } 92 | 93 | case hdb::messages::MessageType::VOTE_REQUEST_MESSAGE: { 94 | communicator->vote(message->clientGlobalRank, true); 95 | break; 96 | } 97 | 98 | case hdb::messages::MessageType::TX_END_MESSAGE: { 99 | table->releaseTransaction((hdb::messages::TransactionEnd *) message); 100 | communicator->signalTransactionEnd(message->clientGlobalRank); 101 | break; 102 | } 103 | 104 | case hdb::messages::MessageType::TX_ABORT_MESSAGE: { 105 | table->abortTransaction((hdb::messages::AbortTransaction *) message); 106 | communicator->signalTransactionEnd(message->clientGlobalRank); 107 | break; 108 | } 109 | 110 | case hdb::messages::MessageType::SHUTDOWN_MESSAGE: { 111 | --remainingClients; 112 | break; 113 | } 114 | 115 | default: { 116 | exit(-1); 117 | break; 118 | } 119 | } 120 | } 121 | 122 | } /* namespace locktable */ 123 | } /* namespace hdb */ 124 | 125 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/communication/VoteCommunicator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * VoteCommunicator.cpp 3 | * 4 | * Created on: Apr 17, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace hdb { 17 | namespace communication { 18 | 19 | VoteCommunicator::VoteCommunicator(hdb::configuration::SystemConfig* config): comdelay(config->comdelay) { 20 | 21 | voteCounter = 0; 22 | globalRank = config->globalRank; 23 | numberOfProcessesPerMachine = config->localNumberOfProcesses; 24 | localMachineId = config->globalRank / numberOfProcessesPerMachine; 25 | 26 | //DLOG_ALWAYS("NotifiedCommunicator", "Process %d allocating space for voting", globalRank); 27 | 28 | #ifdef USE_FOMPI 29 | foMPI_Win_create((void *)&(voteCounter), sizeof(uint64_t), 1, MPI_INFO_NULL, MPI_COMM_WORLD, &(windowObject)); 30 | #else 31 | MPI_Win_create((void *) &(voteCounter), sizeof(uint64_t), 1, MPI_INFO_NULL, MPI_COMM_WORLD, &(windowObject)); 32 | #endif 33 | 34 | MPI_Barrier(MPI_COMM_WORLD); 35 | 36 | #ifdef USE_FOMPI 37 | foMPI_Win_lock_all(0, windowObject); 38 | #else 39 | MPI_Win_lock_all(0, windowObject); 40 | #endif 41 | 42 | //DLOG_ALWAYS("NotifiedCommunicator", "Process %d is ready for voting", globalRank); 43 | } 44 | 45 | VoteCommunicator::~VoteCommunicator() { 46 | 47 | #ifdef USE_FOMPI 48 | foMPI_Win_unlock_all(windowObject); 49 | #else 50 | MPI_Win_unlock_all(windowObject); 51 | #endif 52 | 53 | } 54 | 55 | void VoteCommunicator::vote(uint32_t targetRank, bool outcome) { 56 | 57 | uint64_t value = 1; 58 | uint64_t oldValue = 0; 59 | if (!outcome) { 60 | value = value << 32; 61 | } 62 | 63 | 64 | bool islocal = targetRank/numberOfProcessesPerMachine == localMachineId; 65 | if(!islocal && this->comdelay != 0){ 66 | auto const sleep_end_time = std::chrono::high_resolution_clock::now() + 67 | std::chrono::nanoseconds(this->comdelay); 68 | while (std::chrono::high_resolution_clock::now() < sleep_end_time); 69 | } 70 | #ifdef USE_FOMPI 71 | foMPI_Fetch_and_op(&(value), &(oldValue), MPI_UINT64_T, targetRank, 0, foMPI_SUM, windowObject); 72 | foMPI_Win_flush(targetRank, windowObject); 73 | #else 74 | MPI_Fetch_and_op(&(value), &(oldValue), MPI_UINT64_T, targetRank, 0, MPI_SUM, windowObject); 75 | MPI_Win_flush(targetRank, windowObject); 76 | #endif 77 | 78 | } 79 | 80 | bool VoteCommunicator::checkVoteReady(bool* outcome, uint32_t targetCount) { 81 | 82 | uint64_t currentValue = 0; 83 | 84 | 85 | #ifdef USE_FOMPI 86 | //foMPI_Fetch_and_op(NULL, &(currentValue), MPI_UINT64_T, globalRank, 0, foMPI_NO_OP, windowObject); 87 | foMPI_Get(¤tValue, 1, MPI_UINT64_T, globalRank, 0, 1, MPI_UINT64_T, windowObject); 88 | foMPI_Win_flush(globalRank, windowObject); 89 | #else 90 | //MPI_Fetch_and_op(NULL, &(currentValue), MPI_UINT64_T, globalRank, 0, MPI_NO_OP, windowObject); 91 | MPI_Get(¤tValue, 1, MPI_UINT64_T, globalRank, 0, 1, MPI_UINT64_T, windowObject); 92 | MPI_Win_flush(globalRank, windowObject); 93 | #endif 94 | 95 | uint64_t yesVotes = (currentValue << 32) >> 32; 96 | uint64_t noVotes = (currentValue >> 32); 97 | 98 | bool voteReady = (yesVotes + noVotes >= targetCount); 99 | *outcome = (yesVotes == targetCount); 100 | 101 | //printf("Yes: %lu | No: %lu | CurrentValue: %lu | Load: %lu\n", yesVotes, noVotes, currentValue, voteCounter); 102 | 103 | return voteReady; 104 | 105 | } 106 | 107 | void VoteCommunicator::reset() { 108 | 109 | 110 | uint64_t value = 0; 111 | uint64_t oldValue = 0; 112 | #ifdef USE_FOMPI 113 | foMPI_Fetch_and_op(&(value), &(oldValue), MPI_UINT64_T, globalRank, 0, foMPI_REPLACE, windowObject); 114 | foMPI_Win_flush(globalRank, windowObject); 115 | #else 116 | MPI_Fetch_and_op(&(value), &(oldValue), MPI_UINT64_T, globalRank, 0, MPI_REPLACE, windowObject); 117 | MPI_Win_flush(globalRank, windowObject); 118 | #endif 119 | } 120 | 121 | } /* namespace communication */ 122 | } /* namespace hdb */ 123 | 124 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/communication/NotifiedCommunicator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * NotifiedCommunicator.cpp 3 | * 4 | * Created on: Apr 28, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include "NotifiedCommunicator.h" 9 | 10 | #ifdef USE_FOMPI 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace hdb { 17 | namespace communication { 18 | 19 | NotifiedCommunicator::NotifiedCommunicator(hdb::configuration::SystemConfig* config): comdelay(config->comdelay) { 20 | 21 | globalRank = config->globalRank; 22 | internalRank = config->internalRank; 23 | numberOfProcessesPerMachine = config->localNumberOfProcesses; 24 | localMachineId = globalRank / numberOfProcessesPerMachine; 25 | isLockServerEndPoint = config->isLockTableAgent; 26 | windowSizeInSlots = (isLockServerEndPoint) ? (config->globalNumberOfProcesses - config->globalNumberOfLockTableAgents) : (1); 27 | 28 | //DLOG_ALWAYS("NotifiedCommunicator", "Process %d allocating space for %d messages (%lu bytes)", globalRank, windowSizeInSlots, windowSizeInSlots * MAX_MESSAGE_SIZE); 29 | 30 | foMPI_Win_allocate(windowSizeInSlots * MAX_MESSAGE_SIZE, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &(buffer), &(window)); 31 | 32 | memset(buffer, 0, windowSizeInSlots * MAX_MESSAGE_SIZE); 33 | 34 | //DLOG_ALWAYS("NotifiedCommunicator", "Process %d has memset'ed %d messages", globalRank, windowSizeInSlots); 35 | 36 | MPI_Barrier(MPI_COMM_WORLD); 37 | 38 | //DLOG_ALWAYS("NotifiedCommunicator", "Process %d passed initialization barrier", globalRank); 39 | 40 | foMPI_Win_lock_all(0, window); 41 | foMPI_Notify_init(window, foMPI_ANY_SOURCE, foMPI_ANY_TAG, 1, &(request)); 42 | 43 | foMPI_Start(&request); 44 | 45 | //DLOG_ALWAYS("NotifiedCommunicator", "Process %d is ready for communication", globalRank); 46 | 47 | } 48 | 49 | NotifiedCommunicator::~NotifiedCommunicator() { 50 | 51 | foMPI_Win_unlock_all(window); 52 | foMPI_Win_free(&(window)); 53 | 54 | } 55 | 56 | bool NotifiedCommunicator::sendMessage(hdb::messages::Message* message, uint32_t targetGlobalRank) { 57 | 58 | uint32_t targetOffset = (!isLockServerEndPoint) ? (internalRank) : (0); 59 | uint32_t messageSize = message->messageSize; 60 | 61 | //DLOG_ALWAYS("NotifiedCommunicator", "Process %d sending message to process %d. Placing %d bytes at offset %d", globalRank, targetGlobalRank, messageSize, targetOffset); 62 | 63 | bool islocal = targetGlobalRank/numberOfProcessesPerMachine == localMachineId; 64 | if(!islocal && this->comdelay != 0){ 65 | auto const sleep_end_time = std::chrono::high_resolution_clock::now() + 66 | std::chrono::nanoseconds(this->comdelay); 67 | while (std::chrono::high_resolution_clock::now() < sleep_end_time); 68 | } 69 | foMPI_Put_notify(message, messageSize, MPI_BYTE, targetGlobalRank, targetOffset * MAX_MESSAGE_SIZE, messageSize, MPI_BYTE, window, targetOffset); 70 | foMPI_Win_flush_local(targetGlobalRank, window); 71 | 72 | //DLOG_ALWAYS("NotifiedCommunicator", "Process %d sending message to process %d. Flush completed.", globalRank, targetGlobalRank, messageSize, targetOffset); 73 | 74 | return islocal; 75 | 76 | } 77 | 78 | hdb::messages::Message* NotifiedCommunicator::getMessage() { 79 | 80 | int flag = 0; 81 | foMPI_Test(&request, &flag, &status); 82 | foMPI_Start(&request); 83 | 84 | //foMPI_Wait(&request, &status); 85 | //DLOG_ALWAYS("NotifiedCommunicator", "Flag of %d is %d", globalRank, flag); 86 | 87 | if(flag == 1) { 88 | int32_t offset = status.MPI_TAG; 89 | // DLOG_ALWAYS("NotifiedCommunicator", "Process %d received message from process %d", globalRank, offset); 90 | return (hdb::messages::Message *) ((((char *) buffer) + offset * MAX_MESSAGE_SIZE)); 91 | } else { 92 | return NULL; 93 | } 94 | 95 | } 96 | 97 | hdb::messages::Message* NotifiedCommunicator::getMessageBlocking() { 98 | 99 | foMPI_Wait(&request, &status); 100 | foMPI_Start(&request); 101 | int32_t offset = status.MPI_TAG; 102 | return (hdb::messages::Message *) ((((char *) buffer) + offset * MAX_MESSAGE_SIZE)); 103 | 104 | } 105 | 106 | } /* namespace communication */ 107 | } /* namespace hdb */ 108 | 109 | 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/transactions/TransactionAgent.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TransactionAgent.cpp 3 | * 4 | * Created on: Mar 27, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include "TransactionAgent.h" 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | namespace hdb { 22 | namespace transactions { 23 | 24 | TransactionAgent::TransactionAgent(hdb::configuration::SystemConfig *config) { 25 | 26 | this->config = config; 27 | this->stats.globalRank = config->globalRank; 28 | this->communicator = new hdb::communication::Communicator(config); 29 | this->manager = new hdb::transactions::TransactionManager(config, communicator, &stats); 30 | 31 | } 32 | 33 | TransactionAgent::~TransactionAgent() { 34 | 35 | delete manager; 36 | delete communicator; 37 | 38 | } 39 | 40 | 41 | 42 | void TransactionAgent::shutdown() { 43 | hdb::messages::Shutdown *message = new hdb::messages::Shutdown(config->globalRank); 44 | for (uint32_t i = 0; i < config->globalNumberOfLockTableAgents; ++i) { 45 | communicator->sendMessage(message, config->lockServerGlobalRanks[i]); 46 | } 47 | } 48 | 49 | void TransactionAgent::debugPrintTransactions() { 50 | 51 | for(uint64_t i=0; itransactionTypeId); 54 | for(uint64_t j=0; jrequests.size(); ++j) { 55 | printf("{%lu, %d} ", tx->requests[j].first, tx->requests[j].second); 56 | } 57 | printf("\n----\n"); 58 | } 59 | fflush(stdout); 60 | } 61 | 62 | void TransactionAgent::tpccExecute(uint32_t warehouse, uint32_t workloadSize) { 63 | 64 | uint64_t numberoftransactions = transactions.size(); 65 | 66 | stats.startExecution(); 67 | 68 | manager->start_time=std::chrono::high_resolution_clock::now(); 69 | 70 | auto endtime = manager->start_time + std::chrono::seconds(config->timelimit); 71 | 72 | for (uint64_t txId = 0; txId < workloadSize; ++txId) { 73 | hdb::transactions::Transaction *transaction = &transactions[txId % numberoftransactions]; 74 | manager->startTransaction(); 75 | uint64_t lockSize = transaction->requests.size(); 76 | bool success = true; 77 | 78 | stats.startLocking(); 79 | for (uint64_t lId = 0; lId < lockSize; ++lId) { 80 | success = manager->requestLock(transaction->requests[lId].first, transaction->requests[lId].second); 81 | if (!success) { 82 | break; 83 | } 84 | } 85 | stats.stopLocking(); 86 | 87 | if(success){ 88 | stats.startDataAccess(); 89 | switch(transaction->transactionTypeId){ 90 | case hdb::transactions::DataMode::NONE: 91 | break; 92 | case hdb::transactions::DataMode::NEWORD: 93 | communicator->dataLayer->newOrder(warehouse, manager->involvedVoteServers.size() > 1, &(manager->involvedLockServers)); 94 | break; 95 | case hdb::transactions::DataMode::PAYMENT: 96 | communicator->dataLayer->payment(warehouse); 97 | break; 98 | case hdb::transactions::DataMode::ORDSTAT: 99 | communicator->dataLayer->orderStat(warehouse); 100 | break; 101 | case hdb::transactions::DataMode::DELIVERY: 102 | communicator->dataLayer->delivery(warehouse); 103 | break; 104 | case hdb::transactions::DataMode::SLEV: 105 | communicator->dataLayer->slev(warehouse); 106 | break; 107 | case hdb::transactions::DataMode::YCSB: 108 | communicator->dataLayer->ycsb(warehouse); 109 | break; 110 | default: 111 | DLOG_ALWAYS("TransactionAgent", "Encounter transaction of type %d", transaction->transactionTypeId); 112 | } 113 | stats.stopDataAccess(); 114 | } 115 | 116 | if(success) { 117 | manager->commitTransaction(transaction->transactionTypeId); 118 | } else { 119 | manager->abortTransaction(transaction->transactionTypeId); 120 | } 121 | 122 | if(txId % 8192 == 0){ 123 | if(endtime < std::chrono::high_resolution_clock::now()){ 124 | DLOG("TransactionAgent", "Terminate earlier"); 125 | break; 126 | } 127 | } 128 | } 129 | 130 | stats.stopExecution(); 131 | } 132 | 133 | } /* namespace transactions */ 134 | } /* namespace hdb */ 135 | 136 | 137 | -------------------------------------------------------------------------------- /data/plots/tx-breakdown.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import numpy as np 5 | import pandas as pd 6 | from matplotlib import pyplot as plt, font_manager 7 | from palettable import tableau 8 | from exp_helpers import MEASURES 9 | 10 | parser = argparse.ArgumentParser() 11 | parser.add_argument('-p', '--paper', action='store_true', 12 | help='Produce only configurations used in paper.') 13 | args = parser.parse_args() 14 | 15 | # Read data and group by configs (=everything that is neither a series nor on an axis) 16 | df = pd.read_csv('./tx-breakdown.csv').fillna('') 17 | df = df.sort_values(by=['num_tx_agents']) 18 | dimensions = [c for c in sorted(df.columns.values) if c not in MEASURES] 19 | 20 | if args.paper: 21 | df = df[(df['network_delay'] == '') & 22 | (df['isolation_mode'] == 'serializable') & 23 | (df['mechanism'] == '2pl-bw') & 24 | ((df['num_warehouses'] == 64) | 25 | (df['num_warehouses'] == 2048))] 26 | 27 | plot_dims = ['num_tx_agents', 'num_cores', 'num_nodes', 'num_server_agents'] 28 | config_dims = [d for d in dimensions if d not in plot_dims] 29 | nonunique_config_dims = [d for d in config_dims if len(df[d].unique()) > 1] 30 | 31 | groups = df.groupby(by=config_dims) 32 | 33 | # Produce a plot for each config 34 | for g in groups: 35 | config_name = "".join(["-{}={}".format(k, v) for k, v in zip(config_dims, list(g[0])) 36 | if k in nonunique_config_dims]) 37 | 38 | plt.style.use(['./ethplot.mplstyle']) 39 | 40 | fig, ax = plt.subplots() 41 | 42 | df_g = g[1] 43 | 44 | measA = df_g['ClientLockingTimePerTx mean'] # (155.61, 158.31, 162.97, 161.16, 164.4, 164.09, 163.07) 45 | measB = df_g['ClientDataAccessTimePerTx mean'] # (0.72, 3.16, 6.43, 5.69, 7.1, 7.5, 7.22) 46 | measC = df_g['ClientVotingTimePerTx mean'] # (0, 0.71, 1.34, 1.35, 1.52, 1.54, 1.49) 47 | measD = df_g['ClientEndingTimePerTx mean'] # (12.39, 12.63, 13.01, 12.95, 13.11, 13.14, 13.11) 48 | measE = df_g['ClientOtherTimePerTx mean'] # (0.38, 0.4, 0.4, 0.41, 0.41, 0.41, 0.41) 49 | X = df_g['num_tx_agents'] 50 | ind = np.arange(len(df_g.index)) 51 | 52 | bottomA = measA * 0 53 | bottomB = bottomA + measA 54 | bottomC = bottomB + measB 55 | bottomD = bottomC + measC 56 | bottomE = bottomD + measD 57 | 58 | ############################################################## 59 | 60 | width = 0.5 # the width of the bars 61 | 62 | #colors = colorbrewer.qualitative.Paired_6.mpl_colors 63 | colors = tableau.TableauLight_10.mpl_colors 64 | 65 | rects1 = ax.bar(ind, measA.tolist(), width, bottom=bottomA.tolist(), color=colors[0], hatch='/', ec='black') 66 | rects2 = ax.bar(ind, measB.tolist(), width, bottom=bottomB.tolist(), color=colors[1], hatch='\\', ec='black') 67 | rects3 = ax.bar(ind, measC.tolist(), width, bottom=bottomC.tolist(), color=colors[2], hatch='', ec='black') 68 | rects4 = ax.bar(ind, measD.tolist(), width, bottom=bottomD.tolist(), color=colors[3], hatch='.', ec='black') 69 | rects5 = ax.bar(ind, measE.tolist(), width, bottom=bottomE.tolist(), color=colors[4], hatch='', ec='black') 70 | 71 | ############################################################## 72 | 73 | ax.set_ylim(bottom=0) 74 | y_max = 400 75 | (ncol, loc, bbox_to_anchor) = (5, 'lower right', (1, 0.99)) 76 | if (bottomE + measE).max() > y_max: 77 | ax.set_ylim(top=y_max) 78 | (ncol, loc, bbox_to_anchor) = (3, 'lower left', (0, 0.99)) 79 | for (x, y) in zip(ind, bottomE + measE): 80 | if y > y_max: 81 | plt.text(x, 403, '{:.4g}'.format((y)), ha='center') 82 | 83 | ############################################################## 84 | 85 | ax.set_ylabel('Transaction Latency [microseconds]') 86 | ax.get_xaxis().tick_bottom() 87 | ax.get_yaxis().tick_left() 88 | ax.xaxis.grid(False) 89 | ax.set_xlabel('Transaction Processing Agents') 90 | 91 | ax.set_xticks(ind) 92 | ax.set_xticklabels(X, weight='light') 93 | ax.legend((rects1[0], rects2[0], rects3[0], rects4[0], rects5[0]), 94 | ('Requests', 'Data Access', '2PC voting', 'TX end', 'Other'), 95 | prop={ 'weight': 'light' }, ncol=ncol, loc=loc, 96 | bbox_to_anchor=bbox_to_anchor) 97 | 98 | plt.savefig("./tx-breakdown{}.pdf".format(config_name), format='pdf') 99 | plt.close() 100 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/locktable/Lock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Lock.h 3 | * 4 | * Created on: Apr 17, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_LOCKTABLE_LOCK_H_ 9 | #define SRC_HDB_LOCKTABLE_LOCK_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace hdb { 23 | namespace locktable { 24 | 25 | 26 | enum LockReturn { 27 | Granted = 0, Expired = 1, Queued = 2 28 | }; 29 | 30 | 31 | class Lock2PL { 32 | 33 | public: 34 | 35 | Lock2PL(); 36 | Lock2PL(uint32_t lockOffset); 37 | 38 | public: 39 | 40 | uint32_t lockOffset; 41 | hdb::locktable::LockMode currentMode; 42 | 43 | protected: 44 | 45 | uint32_t grantedCounters[hdb::locktable::LockMode::MODE_COUNT]; 46 | std::queue > requestQueue; 48 | 49 | public: 50 | 51 | bool insertNewRequest(hdb::messages::LockRequest request, hdb::messages::LockGrant* grant); 52 | bool processNextElementFromQueue(hdb::messages::LockGrant *grant); 53 | void releaseLock(hdb::locktable::LockMode modeToRelease); 54 | 55 | bool processExpiredElementsFromQueue(hdb::messages::LockGrant *grant); 56 | bool queueHasPendingElements(); 57 | 58 | protected: 59 | 60 | void computeLockMode(); 61 | void instantGrant(hdb::messages::LockRequest request, hdb::messages::LockGrant* grant); 62 | }; 63 | 64 | 65 | 66 | 67 | 68 | class LockWaitDie { 69 | 70 | public: 71 | 72 | LockWaitDie(); 73 | LockWaitDie(uint32_t lockOffset); 74 | 75 | public: 76 | 77 | uint32_t lockOffset; 78 | uint64_t version; 79 | hdb::locktable::LockMode currentMode; 80 | 81 | protected: 82 | 83 | uint32_t grantedCounters[hdb::locktable::LockMode::MODE_COUNT]; 84 | 85 | std::priority_queue, 87 | std::greater::value_type>> requestQueue; 88 | 89 | public: 90 | 91 | LockReturn insertNewRequest(hdb::messages::LockRequest request, hdb::messages::LockGrant* grant); 92 | bool processNextElementFromQueue(hdb::messages::LockGrant *grant); 93 | void releaseLock(hdb::locktable::LockMode modeToRelease); 94 | 95 | 96 | bool checkTimestamp(hdb::messages::LockRequest request, hdb::messages::LockGrant* grant); 97 | uint64_t GetTimestamp(hdb::locktable::LockMode mode); 98 | void UpdateTimestamp(hdb::locktable::LockMode mode, uint64_t timestamp); 99 | 100 | 101 | public: 102 | 103 | bool processExpiredElementsFromQueue(hdb::messages::LockGrant *grant); 104 | bool queueHasPendingElements(); 105 | 106 | protected: 107 | 108 | void computeLockMode(); 109 | void instantGrant(hdb::messages::LockRequest request, hdb::messages::LockGrant* grant); 110 | void instantExpire(hdb::messages::LockRequest request, hdb::messages::LockGrant* grant); 111 | 112 | }; 113 | 114 | class LockNoWait { 115 | 116 | public: 117 | 118 | LockNoWait(); 119 | LockNoWait(uint32_t lockOffset); 120 | 121 | public: 122 | 123 | uint32_t lockOffset; 124 | hdb::locktable::LockMode currentMode; 125 | 126 | protected: 127 | 128 | uint32_t grantedCounters[hdb::locktable::LockMode::MODE_COUNT]; 129 | 130 | 131 | public: 132 | 133 | bool insertNewRequest(hdb::messages::LockRequest request, hdb::messages::LockGrant* grant); 134 | bool processNextElementFromQueue(hdb::messages::LockGrant *grant); 135 | void releaseLock(hdb::locktable::LockMode modeToRelease); 136 | 137 | protected: 138 | 139 | void computeLockMode(); 140 | void instantGrant(hdb::messages::LockRequest request, hdb::messages::LockGrant* grant); 141 | void instantExpire(hdb::messages::LockRequest request, hdb::messages::LockGrant* grant); 142 | 143 | }; 144 | 145 | // for timestamp ordering 146 | class Row { 147 | 148 | public: 149 | 150 | Row(); 151 | 152 | 153 | public: 154 | uint64_t rts; // read timestamp 155 | uint64_t wts; // write timestamp 156 | 157 | std::set reads; 158 | std::set writes; 159 | std::set prewrites; 160 | 161 | 162 | // it is used only for waiting S (read) requests 163 | std::map pendingreq; 164 | }; 165 | 166 | 167 | 168 | 169 | 170 | } /* namespace locktable */ 171 | } /* namespace hdb */ 172 | 173 | #endif /* SRC_HDB_LOCKTABLE_LOCK_H_ */ 174 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/communication/HybridCommunicator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * HybridCommunicator.cpp 3 | * 4 | * Created on: Apr 28, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include "HybridCommunicator.h" 9 | 10 | #ifdef USE_FOMPI 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace hdb { 17 | namespace communication { 18 | 19 | HybridCommunicator::HybridCommunicator(hdb::configuration::SystemConfig* config): comdelay(config->comdelay) { 20 | 21 | globalRank = config->globalRank; 22 | internalRank = config->internalRank; 23 | numberOfProcessesPerMachine = config->localNumberOfProcesses; 24 | localMachineId = globalRank / numberOfProcessesPerMachine; 25 | isLockServerEndPoint = config->isLockTableAgent; 26 | windowSizeInSlots = (isLockServerEndPoint) ? (config->globalNumberOfProcesses - config->globalNumberOfLockTableAgents) : (1); 27 | 28 | // Slots only for local communication 29 | uint32_t transAgentsPerNode = (config->globalNumberOfProcesses - config->globalNumberOfLockTableAgents) / config->numberOfNodes; 30 | 31 | this->Slots = (isLockServerEndPoint) ? (transAgentsPerNode) : (1); 32 | 33 | 34 | foMPI_Win_allocate(windowSizeInSlots * MAX_MESSAGE_SIZE, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &(buffer), &(window)); 35 | 36 | memset(buffer, 0, windowSizeInSlots * MAX_MESSAGE_SIZE); 37 | 38 | receiveBuffer = (void**)malloc(sizeof(void*)*Slots); 39 | if(isLockServerEndPoint){ 40 | for(uint32_t i = 0 ; i < Slots; i++){ 41 | uint32_t offset = localMachineId*transAgentsPerNode + i; 42 | receiveBuffer[i] = ((((char *) buffer) + offset * MAX_MESSAGE_SIZE)); 43 | } 44 | }else{ 45 | receiveBuffer[0] = buffer; 46 | } 47 | 48 | requests = (MPI_Request*)malloc(sizeof(MPI_Request)*Slots); 49 | for(uint32_t i=0; i < Slots; i++){ 50 | MPI_Irecv(receiveBuffer[i],MAX_MESSAGE_SIZE, MPI_BYTE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &requests[i]); 51 | } 52 | 53 | MPI_Barrier(MPI_COMM_WORLD); 54 | 55 | foMPI_Win_lock_all(0, window); 56 | foMPI_Notify_init(window, foMPI_ANY_SOURCE, foMPI_ANY_TAG, 1, &(request)); 57 | 58 | foMPI_Start(&request); 59 | 60 | 61 | } 62 | 63 | HybridCommunicator::~HybridCommunicator() { 64 | for(uint32_t i = 0; i< Slots; i++){ 65 | MPI_Cancel(&requests[i]); 66 | } 67 | free(receiveBuffer); 68 | foMPI_Win_unlock_all(window); 69 | foMPI_Win_free(&(window)); 70 | 71 | } 72 | 73 | bool HybridCommunicator::sendMessage(hdb::messages::Message* message, uint32_t targetGlobalRank) { 74 | 75 | uint32_t messageSize = message->messageSize; 76 | 77 | bool islocal = targetGlobalRank/numberOfProcessesPerMachine == localMachineId; 78 | if(!islocal && this->comdelay != 0){ 79 | auto const sleep_end_time = std::chrono::high_resolution_clock::now() + 80 | std::chrono::nanoseconds(this->comdelay); 81 | while (std::chrono::high_resolution_clock::now() < sleep_end_time); 82 | } 83 | if(islocal){ 84 | MPI_Send(message, messageSize, MPI_BYTE, targetGlobalRank, 0, MPI_COMM_WORLD); 85 | }else{ 86 | uint32_t targetOffset = (!isLockServerEndPoint) ? (internalRank) : (0); 87 | foMPI_Put_notify(message, messageSize, MPI_BYTE, targetGlobalRank, targetOffset * MAX_MESSAGE_SIZE, messageSize, MPI_BYTE, window, targetOffset); 88 | foMPI_Win_flush_local(targetGlobalRank, window); 89 | } 90 | 91 | 92 | return islocal; 93 | 94 | } 95 | 96 | hdb::messages::Message* HybridCommunicator::getMessage() { 97 | 98 | int flag = 0; 99 | 100 | int indx; 101 | MPI_Testany(Slots, requests, &indx, &flag, MPI_STATUS_IGNORE); 102 | if(flag){ 103 | MPI_Irecv(receiveBuffer[indx],MAX_MESSAGE_SIZE, MPI_BYTE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &requests[indx]); 104 | return (hdb::messages::Message*) receiveBuffer[indx]; 105 | } 106 | 107 | foMPI_Test(&request, &flag, &status); 108 | foMPI_Start(&request); 109 | if(flag == 1) { 110 | int32_t offset = status.MPI_TAG; 111 | return (hdb::messages::Message *) ((((char *) buffer) + offset * MAX_MESSAGE_SIZE)); 112 | } 113 | 114 | return NULL; 115 | } 116 | 117 | hdb::messages::Message* HybridCommunicator::getMessageBlocking() { 118 | 119 | hdb::messages::Message* msg = NULL; 120 | while(msg == NULL){ 121 | msg = getMessage(); 122 | } 123 | return msg; 124 | 125 | } 126 | 127 | } /* namespace communication */ 128 | } /* namespace hdb */ 129 | 130 | 131 | 132 | #endif 133 | -------------------------------------------------------------------------------- /workload-traces/mysql/tpcc/parse_segment.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import fileinput 4 | import re 5 | import json 6 | import sys 7 | 8 | def eprint(*args, **kwargs): 9 | print(*args, file=sys.stderr, **kwargs) 10 | 11 | class PropertyStack: 12 | def __init__(self): 13 | self.Clear() 14 | 15 | def Clear(self): 16 | self.current_depth = 0 17 | self.property_stack = [{}] 18 | 19 | def Push(self): 20 | self.current_depth += 1 21 | self.property_stack.append({}) 22 | 23 | def Pop(self): 24 | if self.current_depth > 0: 25 | self.current_depth -= 1 26 | self.property_stack.pop() 27 | else: 28 | eprint("Warning: unbalanced start/stop: Pop from empty stack") 29 | 30 | def Add(self, name, value): 31 | self.property_stack[-1][name] = value 32 | 33 | def Properties(self): 34 | ret = {} 35 | for d in self.property_stack: 36 | ret.update(d) 37 | return ret 38 | 39 | def ParseIntOrDefault(i, default): 40 | try: 41 | return int(i) 42 | except: 43 | return default 44 | 45 | def ParseLine(property_stack, line): 46 | if line.startswith('UNLOCK RECORD ') or line.startswith('RECORD '): 47 | result = re.match('(UNLOCK )?RECORD LOCK (space ([0-9]*) page_no ([0-9]*) heap_no ([0-9]*) (.*?(/\\* Partition `p([0-9]*)` \\*/)?)) trx id ([0-9]*) lock_mode ([A-Z]*)( ORDINARY)?( GAP)?( REC_NOT_GAP)?( INSERT_INTENTION)?', line) 48 | 49 | if not result: 50 | eprint("Warning: line not in expected format: " + line) 51 | return 52 | 53 | property_stack.Add('action', 'unlock' if result.group(1) else 'lock') 54 | property_stack.Add('object_name', result.group(2)) 55 | property_stack.Add('space_no', int(result.group(3))) 56 | property_stack.Add('page_no', int(result.group(4))) 57 | property_stack.Add('heap_no', int(result.group(5))) 58 | property_stack.Add('table_name', result.group(6)) 59 | property_stack.Add('object_type', 'record') 60 | property_stack.Add('partition_no', ParseIntOrDefault(result.group(8), -1)) 61 | property_stack.Add('trx_id', int(result.group(9))) 62 | property_stack.Add('lock_mode', result.group(10)) 63 | property_stack.Add('ordinary', True if result.group(11) else False) 64 | property_stack.Add('gap', True if result.group(12) else False) 65 | property_stack.Add('recnotgap', True if result.group(13) else False) 66 | property_stack.Add('insertint', True if result.group(14) else False) 67 | 68 | if line.startswith('UNLOCK TABLE ') or line.startswith('TABLE '): 69 | result = re.match('(UNLOCK )?TABLE LOCK (.*?(/\\* Partition `p([0-9]*)` \\*/)?) trx id ([0-9]*) lock_mode ([-A-Z]*)', line) 70 | 71 | if not result: 72 | eprint("Warning: line not in expected format: " + line) 73 | return 74 | 75 | property_stack.Add('action', 'unlock' if result.group(1) else 'lock') 76 | property_stack.Add('object_name', result.group(2)) 77 | property_stack.Add('object_type', 'table') 78 | property_stack.Add('partition_no', ParseIntOrDefault(result.group(4), -1)) 79 | property_stack.Add('trx_id', int(result.group(5))) 80 | property_stack.Add('lock_mode', result.group(6)) 81 | 82 | if line.startswith('start: trx'): 83 | result = re.match('start: trx ([a-z]*) on home w_id ([0-9]*) trx_num ([0-9]*)', line) 84 | if not result: 85 | eprint('Warning: could not parse line: ' + line); 86 | return 87 | property_stack.Add('trx_name', result.group(1)) 88 | property_stack.Add('home_ware_house', int(result.group(2))) 89 | property_stack.Add('trx_num', int(result.group(3))) 90 | 91 | elif 'start' in line and 'ware house' in line: 92 | result = re.match('.* ware house ([0-9]+).*', line) 93 | if not result: 94 | eprint('Warning: could not parse line: ' + line); 95 | return 96 | property_stack.Add('ware_house', int(result.group(1))) 97 | 98 | property_stack = PropertyStack() 99 | 100 | for line in fileinput.input(): 101 | 102 | if line.startswith('end: '): 103 | property_stack.Pop() 104 | 105 | # Fall-back in case a 'start' misses a matching 'end' 106 | if line.startswith('start: trx'): 107 | if property_stack.current_depth != 0: 108 | eprint("Warning: start of transaction found at depth != 0!") 109 | property_stack.Clear() 110 | 111 | ParseLine(property_stack, line) 112 | 113 | if line.startswith('start: '): 114 | property_stack.Push() 115 | 116 | print(json.dumps(property_stack.Properties())) 117 | -------------------------------------------------------------------------------- /workload-traces/mysql/tpcc/make_trace/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | namespace po = boost::program_options; 19 | 20 | std::string LockName(const int ware_house, const std::string& object_name) 21 | { 22 | return std::to_string(ware_house) + "###" + object_name; 23 | } 24 | 25 | int main(int argc, char** argv) 26 | { 27 | // Parse command line parameters 28 | std::string lockids_file_name; 29 | std::vector input_file_names; 30 | std::vector output_file_names; 31 | 32 | po::options_description desc("Allowed options"); 33 | // clang-format off 34 | desc.add_options() 35 | ("lockids_file,l", 36 | po::value(&lockids_file_name)->required()) 37 | ("input_files,i", 38 | po::value(&input_file_names)->multitoken()) 39 | ("output_files,o", 40 | po::value(&output_file_names)->multitoken()) 41 | ("help,h", "Produce this help message.") 42 | ; 43 | // clang-format on 44 | 45 | po::variables_map vm; 46 | po::store(po::parse_command_line(argc, argv, desc), vm); 47 | 48 | if (vm.count("help")) 49 | { 50 | std::printf( 51 | "Convert JSON lock trace into CSV locktrace while translating " 52 | "lock names into IDs.\n"); 53 | std::cout << desc << "\n"; 54 | return 0; 55 | } 56 | 57 | po::notify(vm); 58 | 59 | if (input_file_names.size() != output_file_names.size()) 60 | { 61 | throw std::invalid_argument( 62 | "The number of input and output files must match"); 63 | } 64 | 65 | // Read lock IDs 66 | std::unordered_map locks; 67 | { 68 | std::ifstream lockids_file(lockids_file_name); 69 | for (std::string line; std::getline(lockids_file, line);) 70 | { 71 | rapidjson::Document d; 72 | d.Parse(line.c_str()); 73 | auto const ware_house = d["ware_house"].GetInt(); 74 | auto const object_name = d["object_name"].GetString(); 75 | auto const lock_id = d["lock_id"].GetInt(); 76 | 77 | auto const ret = 78 | locks.emplace(LockName(ware_house, object_name), lock_id); 79 | 80 | if (!ret.second) 81 | { 82 | throw std::runtime_error(std::string("duplicate lock: ") + 83 | std::to_string(lock_id) + " vs " + 84 | std::to_string(ret.first->second)); 85 | } 86 | } 87 | } 88 | 89 | std::printf("done loading lock IDs (%zi locks)\n", locks.size()); 90 | 91 | #pragma omp parallel for 92 | for (size_t i = 0; i < input_file_names.size(); i++) 93 | { 94 | std::ifstream input_file(input_file_names[i]); 95 | std::ofstream output_file(output_file_names[i]); 96 | 97 | int current_trx_num = std::numeric_limits::max(); 98 | std::unordered_set current_locks; 99 | 100 | for (std::string line; std::getline(input_file, line);) 101 | { 102 | rapidjson::Document d; 103 | d.Parse(line.c_str()); 104 | auto const ware_house = d["ware_house"].GetInt(); 105 | auto const object_name = d["object_name"].GetString(); 106 | 107 | auto const lock_mode = d["lock_mode"].GetString(); 108 | auto const trx_name = d["trx_name"].GetString(); 109 | auto const trx_num = d["trx_num"].GetInt(); 110 | 111 | auto const ret = locks.find(LockName(ware_house, object_name)); 112 | if (ret == locks.end()) 113 | { 114 | throw std::runtime_error( 115 | std::string("lock not found: ") + 116 | std::string(LockName(ware_house, object_name))); 117 | } 118 | auto const lock_id = ret->second; 119 | 120 | // Reset current locks on new transaction 121 | if (current_trx_num != trx_num) 122 | { 123 | current_trx_num = trx_num; 124 | current_locks.clear(); 125 | } 126 | // Remember locks of current TRX, skip output if lock already held 127 | if (!current_locks.insert(lock_id).second) 128 | continue; 129 | 130 | output_file << trx_num << "," << lock_id << "," << lock_mode << "," 131 | << trx_name << std::endl; 132 | } 133 | 134 | #pragma omp critical 135 | { 136 | std::printf("Done converting %s to %s\n", 137 | input_file_names[i].c_str(), 138 | output_file_names[i].c_str()); 139 | } 140 | } 141 | 142 | // Leak memory of locks to save time 143 | { 144 | auto p = new decltype(locks)(); 145 | p->swap(locks); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /test_general_mpi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | usage () { 4 | echo "Script for running with mpi" 5 | echo "options:" 6 | echo " --dir=PATH (default=PWD) #absolute path to the project" 7 | echo " --out=FILENAME (default=out-PARAMS) #output filename which will be create at --dir" 8 | echo " --nodes=INT (default=1) #the number of nodes" 9 | echo " --sockets=INT (default=1) #the number of sockets per node" 10 | echo " --processes=INT (default=2) #the number of transaction processes per node," 11 | echo " #it also specifies the number of lock processes per node" 12 | echo " --locksperwh=INT (default=1024) #the number of locks per warehouse" 13 | echo " --numwhs=INT (default=128) #the number of warehouses" 14 | echo " --remotelockprob=0-100 (default=0) #the probability of remote lock" 15 | echo " --workloadsize=INT (default=100000) #the number of transactions to be executed per client" 16 | echo " --timilimit=INT (default=120) #limit runtime in seconds" 17 | echo " --comdelay=INT (default=0) #add a delay in nanosec before each communication" 18 | echo "" 19 | echo "" 20 | echo " Transaction algorithm:" 21 | echo " --simple2pl (default) #simple 2PL " 22 | echo " --waitdie #wait-die strategy" 23 | echo " --nowait #nowait lock strategy" 24 | echo " --timestamp #timestamp lock strategy" 25 | echo "" 26 | echo "" 27 | echo " MPI additional arguments: " 28 | echo " --mpiargs=STRING (default="") #add additional MPI arguments. Can be used to pass --hostfile" 29 | } 30 | 31 | 32 | WORKDIR=${PWD}/ 33 | NODES=1 34 | SOCKETS_PER_NODE=1 35 | TRAN_PROCESSES_PER_NODE=2 36 | WORKLOADSIZE=100000 37 | COMDELAY=0 38 | ALGORITHM="simple2pl" 39 | TIMELIMIT=120 40 | LOCKSPERWH="1024" 41 | NUMWHS="128" 42 | REMOTEPROB=0 43 | FILENAME="" 44 | 45 | for arg in "$@" 46 | do 47 | case ${arg} in 48 | --help|-help|-h) 49 | usage 50 | exit 1 51 | ;; 52 | --dir=*) 53 | WORKDIR=`echo $arg | sed -e 's/--dir=//'` 54 | WORKDIR=`eval echo ${WORKDIR}` # tilde and variable expansion 55 | ;; 56 | --nodes=*) 57 | NODES=`echo $arg | sed -e 's/--nodes=//'` 58 | NODES=`eval echo ${NODES}` # tilde and variable expansion 59 | ;; 60 | --sockets=*) 61 | SOCKETS_PER_NODE=`echo $arg | sed -e 's/--sockets=//'` 62 | SOCKETS_PER_NODE=`eval echo ${SOCKETS_PER_NODE}` # tilde and variable expansion 63 | ;; 64 | --processes=*) 65 | TRAN_PROCESSES_PER_NODE=`echo $arg | sed -e 's/--processes=//'` 66 | TRAN_PROCESSES_PER_NODE=`eval echo ${TRAN_PROCESSES_PER_NODE}` # tilde and variable expansion 67 | ;; 68 | --workloadsize=*) 69 | WORKLOADSIZE=`echo $arg | sed -e 's/--workloadsize=//'` 70 | WORKLOADSIZE=`eval echo ${WORKLOADSIZE}` # tilde and variable expansion 71 | ;; 72 | --comdelay=*) 73 | COMDELAY=`echo $arg | sed -e 's/--comdelay=//'` 74 | COMDELAY=`eval echo ${COMDELAY}` # tilde and variable expansion 75 | ;; 76 | --timelimit=*) 77 | TIMELIMIT=`echo $arg | sed -e 's/--timelimit=//'` 78 | TIMELIMIT=`eval echo ${TIMELIMIT}` # tilde and variable expansion 79 | ;; 80 | --losksperwh=*) 81 | LOCKSPERWH=`echo $arg | sed -e 's/--losksperwh=//'` 82 | LOCKSPERWH=`eval echo ${LOCKSPERWH}` # tilde and variable expansion 83 | ;; 84 | --numwhs=*) 85 | NUMWHS=`echo $arg | sed -e 's/--numwhs=//'` 86 | NUMWHS=`eval echo ${NUMWHS}` # tilde and variable expansion 87 | ;; 88 | --remotelockprob=*) 89 | REMOTEPROB=`echo $arg | sed -e 's/--remotelockprob=//'` 90 | REMOTEPROB=`eval echo ${REMOTEPROB}` # tilde and variable expansion 91 | ;; 92 | --waitdie) 93 | ALGORITHM="waitdie" 94 | ;; 95 | --nowait) 96 | ALGORITHM="nowait" 97 | ;; 98 | --timestamp) 99 | ALGORITHM="timestamp" 100 | ;; 101 | --mpiargs=*) 102 | MPIARGS=`echo $arg | sed -e 's/--mpiargs=//'` 103 | MPIARGS=`eval echo ${MPIARGS}` # tilde and variable expansion 104 | ;; 105 | --out=*) 106 | FILENAME=`echo $arg | sed -e 's/--out=//'` 107 | FILENAME=`eval echo ${FILENAME}` # tilde and variable expansion 108 | ;; 109 | esac 110 | done 111 | 112 | 113 | 114 | echo "Start mpi job" 115 | 116 | if [ -z "${FILENAME}" ]; then 117 | OUTFILENAME="out-synthetic-${NUMWHS}-${NODES}-${TRAN_PROCESSES_PER_NODE}-${TRAN_PROCESSES_PER_NODE}-${COMDELAY}-${ALGORITHM}" 118 | else 119 | OUTFILENAME=${FILENAME} 120 | fi 121 | 122 | MPIPROC_PER_NODE=$((2*${TRAN_PROCESSES_PER_NODE})) 123 | TOTAL=$((${NODES}*${MPIPROC_PER_NODE})) 124 | MPIPROC_PER_SOCKET=$((${MPIPROC_PER_NODE}/${SOCKETS_PER_NODE})) 125 | 126 | mpirun -np ${TOTAL} -npersocket ${MPIPROC_PER_SOCKET} ${MPIARGS} ${WORKDIR}/HumongousLock/release/hdb-lock --synthetic --remotelockprob=${REMOTEPROB} \ 127 | --timelimit=${TIMELIMIT} \ 128 | --warehouses=${NUMWHS} \ 129 | --processespernode=${TRAN_PROCESSES_PER_NODE} \ 130 | --locksperwh=${LOCKSPERWH} --socketspernode=${SOCKETS_PER_NODE} \ 131 | --localworkloadsize=${WORKLOADSIZE} \ 132 | --comdelay=${COMDELAY} \ 133 | --logname=${WORKDIR}/${OUTFILENAME} --${ALGORITHM} 134 | 135 | 136 | echo "mpi job has been finished" 137 | 138 | -------------------------------------------------------------------------------- /HumongousLock/Makefile: -------------------------------------------------------------------------------- 1 | # Load local config, if it exists (needs to be the first command in the makefile) 2 | SCRIPT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) 3 | # To configure this Makefile, define variables in Makefile.local in the same directory 4 | -include $(SCRIPT_DIR)/Makefile.local 5 | 6 | ######################################## 7 | 8 | DEBUG ?= 0 # Set to 0 if unset 9 | ifeq ($(DEBUG), 1) 10 | CXXFLAGS += -g3 -DDEBUG 11 | LDFLAGS += -g 12 | else 13 | CXXFLAGS += -DNDEBUG -O3 -std=c++0x -march=native -mtune=native 14 | endif 15 | 16 | 17 | ifneq ($(USE_LOGGING),) 18 | CXXFLAGS+=-D USE_LOGGING 19 | endif 20 | 21 | # Set to 0 if not overwritten 22 | USE_CRAY ?= 0 23 | 24 | ifeq ($(USE_CRAY), 1) 25 | COMPILER = CC 26 | CXXFLAGS+=-D USE_FOMPI 27 | 28 | ifeq ($(FOMPI_LOCATION),) 29 | $(error FOMPI_LOCATION is not specified) 30 | endif 31 | 32 | CXXFLAGS+=-I $(FOMPI_LOCATION) -I /opt/cray/dmapp/default/include/ -I $(FOMPI_LOCATION)/libtopodisc -I $(FOMPI_LOCATION)/mpitypes/install/include -DXPMEM -DUGNI 33 | FOMPI_LIBS = -L $(FOMPI_LOCATION) -lfompi -L $(FOMPI_LOCATION)/mpitypes/install/lib -lmpitypes -L /opt/cray/dmapp/default/include/lib64 -ldmapp -DXPMEM -DUGNI 34 | LDFLAGS+=$(FOMPI_LIBS) 35 | else 36 | COMPILER = mpic++ 37 | endif 38 | 39 | BOOSTLD= 40 | ifneq ($(BOOST_LIB),) 41 | BOOSTLD+=-Wl,-rpath=$(BOOST_LIB) -L ${BOOST_LIB} 42 | endif 43 | 44 | BOOSTLD+=-lboost_program_options -lboost_serialization 45 | 46 | 47 | ######################################## 48 | 49 | SOURCE_FILES = src/hdb/main.cpp \ 50 | src/hdb/locktable/LockTableAgent.cpp \ 51 | src/hdb/transactions/TransactionAgent.cpp \ 52 | src/hdb/communication/VoteCommunicator.cpp \ 53 | src/hdb/communication/DataLayer.cpp \ 54 | src/hdb/communication/Communicator.cpp \ 55 | src/hdb/communication/NotifiedCommunicator.cpp \ 56 | src/hdb/communication/SendReceiveCommunicator.cpp \ 57 | src/hdb/communication/HybridCommunicator.cpp \ 58 | src/hdb/messages/MessageSlot.cpp \ 59 | src/hdb/messages/Message.cpp \ 60 | src/hdb/messages/LockRequest.cpp \ 61 | src/hdb/messages/LockGrant.cpp \ 62 | src/hdb/messages/LockRelease.cpp \ 63 | src/hdb/messages/VoteRequest.cpp \ 64 | src/hdb/messages/TransactionEnd.cpp \ 65 | src/hdb/messages/AbortTransaction.cpp \ 66 | src/hdb/messages/Shutdown.cpp \ 67 | src/hdb/locktable/Lock.cpp \ 68 | src/hdb/locktable/Table.cpp \ 69 | src/hdb/transactions/Transaction.cpp \ 70 | src/hdb/transactions/TransactionManager.cpp \ 71 | src/hdb/transactions/SimpleClient.cpp \ 72 | src/hdb/transactions/ReplayClient.cpp \ 73 | src/hdb/stats/ClientStats.cpp 74 | 75 | HEADER_FILES = src/hdb/configuration/SystemConfig.h \ 76 | src/hdb/locktable/LockTableAgent.h \ 77 | src/hdb/transactions/TransactionAgent.h \ 78 | src/hdb/communication/VoteCommunicator.h \ 79 | src/hdb/communication/DataLayer.h \ 80 | src/hdb/communication/NotifiedCommunicator.h \ 81 | src/hdb/communication/SendReceiveCommunicator.h \ 82 | src/hdb/communication/Communicator.h \ 83 | src/hdb/communication/HybridCommunicator.h \ 84 | src/hdb/messages/MessageUtils.h \ 85 | src/hdb/messages/MessageSlot.h \ 86 | src/hdb/messages/Message.h \ 87 | src/hdb/messages/LockRequest.h \ 88 | src/hdb/messages/LockGrant.h \ 89 | src/hdb/messages/LockRelease.h \ 90 | src/hdb/messages/VoteRequest.h \ 91 | src/hdb/messages/TransactionEnd.h \ 92 | src/hdb/messages/AbortTransaction.h \ 93 | src/hdb/messages/Shutdown.h \ 94 | src/hdb/locktable/Lock.h \ 95 | src/hdb/locktable/Table.h \ 96 | src/hdb/transactions/Transaction.h \ 97 | src/hdb/transactions/TransactionManager.h \ 98 | src/hdb/transactions/SimpleClient.h \ 99 | src/hdb/transactions/ReplayClient.h \ 100 | src/hdb/stats/ClientStats.h \ 101 | src/hdb/utils/Debug.h 102 | 103 | ######################################## 104 | 105 | PROJECT_NAME = hdb-lock 106 | 107 | ######################################## 108 | 109 | SOURCE_FOLDER = src 110 | BUILD_FOLDER = build 111 | RELEASE_FOLDER = release 112 | 113 | ######################################## 114 | 115 | OBJECT_FILES = $(patsubst $(SOURCE_FOLDER)/%.cpp,$(BUILD_FOLDER)/%.o,$(SOURCE_FILES)) 116 | SOURCE_DIRECTORIES = $(dir $(HEADER_FILES)) 117 | BUILD_DIRECTORIES = $(patsubst $(SOURCE_FOLDER)/%,$(BUILD_FOLDER)/%,$(SOURCE_DIRECTORIES)) 118 | 119 | ######################################## 120 | 121 | all: program preprocess 122 | 123 | ######################################## 124 | 125 | $(BUILD_FOLDER)/%.o: $(SOURCE_FILES) $(HEADER_FILES) 126 | mkdir -p $(BUILD_FOLDER) 127 | mkdir -p $(BUILD_DIRECTORIES) 128 | $(COMPILER) $(CXXFLAGS) $(BOOST_INCLUDE) -c $(SOURCE_FOLDER)/$*.cpp -I $(SOURCE_FOLDER) $(LDFLAGS) -o $(BUILD_FOLDER)/$*.o 129 | 130 | ######################################## 131 | 132 | program: $(OBJECT_FILES) 133 | mkdir -p $(RELEASE_FOLDER) 134 | $(COMPILER) $(OBJECT_FILES) $(CXXFLAGS) $(BOOST_INCLUDE) $(LDFLAGS) $(BOOSTLD) -o $(RELEASE_FOLDER)/$(PROJECT_NAME) 135 | 136 | ####################################### 137 | 138 | 139 | preprocess: 140 | mkdir -p $(RELEASE_FOLDER) 141 | $(COMPILER) src/hdb/preprocess.cpp src/hdb/transactions/Transaction.cpp -DNDEBUG -O3 -std=c++0x -march=native -mtune=native -I src/ $(BOOST_INCLUDE) $(BOOSTLD) -o $(RELEASE_FOLDER)/preprocess 142 | 143 | ######################################## 144 | clean: 145 | rm -rf $(BUILD_FOLDER) 146 | rm -rf $(RELEASE_FOLDER) 147 | 148 | ######################################## 149 | 150 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/locktable/Table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Table.h 3 | * 4 | * Created on: Apr 18, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #ifndef SRC_HDB_LOCKTABLE_TABLE_H_ 9 | #define SRC_HDB_LOCKTABLE_TABLE_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace hdb { 26 | namespace locktable { 27 | 28 | // general interface for Table implementations 29 | class Table { 30 | 31 | public: 32 | 33 | virtual void insertNewRequest(hdb::messages::LockRequest *request) = 0; 34 | virtual void releaseLock(hdb::messages::LockRelease *release) = 0; 35 | virtual void releaseTransaction(hdb::messages::TransactionEnd *endTransaction) = 0; 36 | virtual void abortTransaction(hdb::messages::AbortTransaction *abortTransaction) = 0; 37 | 38 | virtual void handleExpiredRequests() = 0; 39 | }; 40 | 41 | /* 42 | Original version of simple 2PL coded by Claude 43 | */ 44 | 45 | class Table2PL: public Table { 46 | 47 | typedef std::pair lockpointer_mode_pair_t; 48 | 49 | 50 | public: 51 | Table2PL(uint64_t numberOfElements, hdb::communication::Communicator *communicator); 52 | virtual ~Table2PL(); 53 | 54 | public: 55 | 56 | void insertNewRequest(hdb::messages::LockRequest *request) override; 57 | void releaseLock(hdb::messages::LockRelease *release) override; 58 | void releaseTransaction(hdb::messages::TransactionEnd *endTransaction) override; 59 | void abortTransaction(hdb::messages::AbortTransaction *abortTransaction) override; 60 | void handleExpiredRequests() override; 61 | 62 | 63 | protected: 64 | void processAndSendNotifications(uint32_t lockOffset); 65 | 66 | std::set locksWithPendingRequests; 67 | uint32_t numberOfElements; 68 | std::vector aquiredLockCopy; 69 | hdb::messages::LockGrant *grantMessageBuffer; 70 | hdb::communication::Communicator *communicator; 71 | std::multimap transactionLockMap; 72 | 73 | 74 | Lock2PL *locks; 75 | 76 | }; 77 | 78 | 79 | 80 | class TableWaitDie: public Table { 81 | typedef std::pair lockpointer_mode_pair_t; 82 | 83 | public: 84 | TableWaitDie(uint64_t numberOfElements, hdb::communication::Communicator *communicator); 85 | virtual ~TableWaitDie(); 86 | 87 | public: 88 | 89 | void insertNewRequest(hdb::messages::LockRequest *request) override; 90 | void releaseLock(hdb::messages::LockRelease *release) override; 91 | void releaseTransaction(hdb::messages::TransactionEnd *endTransaction) override; 92 | void abortTransaction(hdb::messages::AbortTransaction *abortTransaction) override; 93 | void handleExpiredRequests() override; 94 | 95 | 96 | protected: 97 | 98 | 99 | void processAndSendNotifications(uint32_t lockOffset); 100 | 101 | std::set locksWithPendingRequests; 102 | uint32_t numberOfElements; 103 | std::vector aquiredLockCopy; 104 | hdb::messages::LockGrant *grantMessageBuffer; 105 | hdb::communication::Communicator *communicator; 106 | std::multimap transactionLockMap; 107 | 108 | 109 | LockWaitDie *locks; 110 | }; 111 | 112 | 113 | 114 | 115 | class TableNoWait: public Table { 116 | typedef std::pair lockpointer_mode_pair_t; 117 | 118 | public: 119 | TableNoWait(uint64_t numberOfElements, hdb::communication::Communicator *communicator); 120 | virtual ~TableNoWait(); 121 | 122 | public: 123 | 124 | void insertNewRequest(hdb::messages::LockRequest *request) override; 125 | void releaseLock(hdb::messages::LockRelease *release) override; 126 | void releaseTransaction(hdb::messages::TransactionEnd *endTransaction) override; 127 | void abortTransaction(hdb::messages::AbortTransaction *abortTransaction) override; 128 | void handleExpiredRequests() override; 129 | 130 | 131 | protected: 132 | 133 | uint32_t numberOfElements; 134 | std::vector aquiredLockCopy; 135 | hdb::communication::Communicator *communicator; 136 | std::multimap transactionLockMap; 137 | hdb::messages::LockGrant *grantMessageBuffer; 138 | 139 | 140 | LockNoWait *locks; 141 | }; 142 | 143 | 144 | 145 | /* 146 | We don't know the implementation 147 | We need some prewrites! 148 | 149 | */ 150 | 151 | class TableTimestamp: public Table { 152 | 153 | public: 154 | TableTimestamp(uint64_t numberOfElements, hdb::communication::Communicator *communicator); 155 | virtual ~TableTimestamp(); 156 | 157 | public: 158 | 159 | void insertNewRequest(hdb::messages::LockRequest *request) override; 160 | void releaseLock(hdb::messages::LockRelease *release) override; 161 | void releaseTransaction(hdb::messages::TransactionEnd *endTransaction) override; 162 | void abortTransaction(hdb::messages::AbortTransaction *abortTransaction) override; 163 | void handleExpiredRequests() override; 164 | 165 | protected: 166 | void trigger(uint64_t minpts,hdb::locktable::Row* row); 167 | 168 | uint32_t numberOfElements; 169 | hdb::communication::Communicator *communicator; 170 | hdb::messages::LockGrant *grantMessageBuffer; 171 | 172 | hdb::locktable::Row *rows; 173 | std::vector aquiredLockCopy; 174 | std::multimap transactionLockMap; 175 | 176 | 177 | }; 178 | 179 | } /* namespace locktable */ 180 | } /* namespace hdb */ 181 | 182 | #endif /* SRC_HDB_LOCKTABLE_TABLE_H_ */ 183 | -------------------------------------------------------------------------------- /run_general_mpi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | usage () { 4 | echo "Script for running with mpi" 5 | echo "options:" 6 | echo " --dir=PATH (default=PWD) #absolute path to the project" 7 | echo " --workloadDir=PATH (required) #absolute path to the workload" 8 | echo " --out=FILENAME (default=out-PARAMS) #output filename which will be create at --dir" 9 | echo " --nodes=INT (default=1) #the number of nodes" 10 | echo " --sockets=INT (default=1) #the number of sockets per node" 11 | echo " --processes=INT (default=16) #the number of transaction processes per node," 12 | echo " #it also specifies the number of lock processes per node" 13 | echo " --workloadsize=INT (default=1000000) #the number of transactions to be executed per client" 14 | echo " --timelimit=INT (default=120) #limit runtime in seconds" 15 | echo " --nopreprocessing #disable preprocessing of the workload before execution" 16 | echo " --comdelay=INT (default=0) #add a delay in nanosec before each communication" 17 | echo "" 18 | echo "" 19 | echo " Transaction algorithm:" 20 | echo " --simple2pl (default) #simple 2PL " 21 | echo " --waitdie #wait-die strategy" 22 | echo " --nowait #nowait lock strategy" 23 | echo " --timestamp #timestamp lock strategy" 24 | echo "" 25 | echo "" 26 | echo " MPI additional arguments: " 27 | echo " --mpiargs=STRING (default="") #add additional MPI arguments. Can be used to pass --hostfile" 28 | } 29 | 30 | 31 | WORKDIR=${PWD}/ 32 | DATADIR="" 33 | NODES=1 34 | SOCKETS_PER_NODE=1 35 | TRAN_PROCESSES_PER_NODE=16 36 | WORKLOADSIZE=1000000 37 | COMDELAY=0 38 | PREPROCESSING=1 39 | ALGORITHM="simple2pl" 40 | TIMELIMIT=120 41 | MPIARGS="" 42 | FILENAME="" 43 | 44 | for arg in "$@" 45 | do 46 | case ${arg} in 47 | --help|-help|-h) 48 | usage 49 | exit 1 50 | ;; 51 | --dir=*) 52 | WORKDIR=`echo $arg | sed -e 's/--dir=//'` 53 | WORKDIR=`eval echo ${WORKDIR}` # tilde and variable expansion 54 | ;; 55 | --workloadDir=*) 56 | DATADIR=`echo $arg | sed -e 's/--workloadDir=//'` 57 | DATADIR=`eval echo ${DATADIR}` # tilde and variable expansion 58 | ;; 59 | --nodes=*) 60 | NODES=`echo $arg | sed -e 's/--nodes=//'` 61 | NODES=`eval echo ${NODES}` # tilde and variable expansion 62 | ;; 63 | --sockets=*) 64 | SOCKETS_PER_NODE=`echo $arg | sed -e 's/--sockets=//'` 65 | SOCKETS_PER_NODE=`eval echo ${SOCKETS_PER_NODE}` # tilde and variable expansion 66 | ;; 67 | --processes=*) 68 | TRAN_PROCESSES_PER_NODE=`echo $arg | sed -e 's/--processes=//'` 69 | TRAN_PROCESSES_PER_NODE=`eval echo ${TRAN_PROCESSES_PER_NODE}` # tilde and variable expansion 70 | ;; 71 | --workloadsize=*) 72 | WORKLOADSIZE=`echo $arg | sed -e 's/--workloadsize=//'` 73 | WORKLOADSIZE=`eval echo ${WORKLOADSIZE}` # tilde and variable expansion 74 | ;; 75 | --comdelay=*) 76 | COMDELAY=`echo $arg | sed -e 's/--comdelay=//'` 77 | COMDELAY=`eval echo ${COMDELAY}` # tilde and variable expansion 78 | ;; 79 | --timelimit=*) 80 | TIMELIMIT=`echo $arg | sed -e 's/--timelimit=//'` 81 | TIMELIMIT=`eval echo ${TIMELIMIT}` # tilde and variable expansion 82 | ;; 83 | --nopreprocessing) 84 | PREPROCESSING=0 85 | ;; 86 | --waitdie) 87 | ALGORITHM="waitdie" 88 | ;; 89 | --nowait) 90 | ALGORITHM="nowait" 91 | ;; 92 | --timestamp) 93 | ALGORITHM="timestamp" 94 | ;; 95 | --mpiargs=*) 96 | MPIARGS=`echo $arg | sed -e 's/--mpiargs=//'` 97 | MPIARGS=`eval echo ${MPIARGS}` # tilde and variable expansion 98 | ;; 99 | --out=*) 100 | FILENAME=`echo $arg | sed -e 's/--out=//'` 101 | FILENAME=`eval echo ${FILENAME}` # tilde and variable expansion 102 | ;; 103 | esac 104 | done 105 | 106 | if [ -z "$DATADIR" ] 107 | then 108 | echo "[Error] --workloadDir is not specified" 109 | usage 110 | exit 1 111 | fi 112 | 113 | NUMWHS=$(ls ${DATADIR}/*.csv | sed 's!.*/!!' | grep -o -E '[0-9]+' | sort -nr | head -1 | sed 's/^0*//') 114 | LOCKSPERWH=$(cat ${DATADIR}/max-locks-per-wh.meta | grep -oP '^[^0-9]*\K[0-9]+') 115 | 116 | FOLDERNAME=$(basename ${DATADIR}) 117 | 118 | if [ -z "${FILENAME}" ]; then 119 | OUTFILENAME="out-${FOLDERNAME}-${NUMWHS}-${NODES}-${TRAN_PROCESSES_PER_NODE}-${TRAN_PROCESSES_PER_NODE}-${COMDELAY}-${ALGORITHM}" 120 | else 121 | OUTFILENAME=${FILENAME} 122 | fi 123 | 124 | 125 | if [ "$PREPROCESSING" -eq "1" ]; then 126 | echo "Start Preprocessing the workload" 127 | ${WORKDIR}/HumongousLock/release/preprocess --warehouses=${NUMWHS} --processespernode=${TRAN_PROCESSES_PER_NODE} --locksperwh=${LOCKSPERWH} --localworkloadsize=${WORKLOADSIZE} --workloadlocation=${DATADIR} --numberofnodes=${NODES} 128 | echo "The workload has been preprocessed" 129 | fi 130 | 131 | 132 | echo "Start mpi job" 133 | 134 | MPIPROC_PER_NODE=$((2*${TRAN_PROCESSES_PER_NODE})) 135 | TOTAL=$((${NODES}*${MPIPROC_PER_NODE})) 136 | MPIPROC_PER_SOCKET=$((${MPIPROC_PER_NODE}/${SOCKETS_PER_NODE})) 137 | 138 | mpirun -np ${TOTAL} -npersocket ${MPIPROC_PER_SOCKET} ${MPIARGS} ${WORKDIR}/HumongousLock/release/hdb-lock \ 139 | --timelimit=${TIMELIMIT} \ 140 | --warehouses=${NUMWHS} \ 141 | --processespernode=${TRAN_PROCESSES_PER_NODE} \ 142 | --locksperwh=${LOCKSPERWH} --socketspernode=${SOCKETS_PER_NODE} \ 143 | --localworkloadsize=${WORKLOADSIZE} \ 144 | --workloadlocation=${DATADIR} \ 145 | --comdelay=${COMDELAY} \ 146 | --logname=${WORKDIR}/${OUTFILENAME} --${ALGORITHM} 147 | 148 | 149 | echo "mpi job has been finished" 150 | 151 | -------------------------------------------------------------------------------- /workload-traces/README.md: -------------------------------------------------------------------------------- 1 | ## Installation 2 | 3 | The traces used for the plots in the paper are available for download [here](https://doi.org/10.3929/ethz-b-000374738). 4 | This guide explains how to reproduce them. 5 | 6 | This guide assumes that `MAINREPO` is set to the path of this repository. 7 | 8 | ### Instrumentalized MySQL 9 | 10 | Checkout repository: 11 | 12 | ```bash 13 | git clone git@gitlab.inf.ethz.ch:muellein/mysql-server-tracing.git $MAINREPO/workload-traces/mysql/3rdparty/mysql-server --branch locktrace 14 | # or 15 | $MAINREPO/workload-traces/mysql/3rdparty/download-mysql-server.sh 16 | cd $MAINREPO/workload-traces/mysql/3rdparty/mysql-server 17 | MYSQL_REPO=$PWD 18 | ``` 19 | 20 | Build and install. 21 | If the build fails with a recent compiler, try an older one; 22 | the MySQL version we use is from 2015 and does not compile with some newer compilers 23 | (GCC 6, 7, and 8 work). 24 | Make sure that any user has read acces to `MYSQL_PREFIX` 25 | (for that reason, avoid setting it to a folder under your home folder). 26 | 27 | ```bash 28 | sudo apt install bison cmake 29 | MYSQL_PREFIX=/mnt/local/muellein/mysql/ 30 | mkdir -p $MYSQL_PREFIX $MYSQL_REPO/build 31 | cd $MYSQL_REPO/build 32 | rm -rf * 33 | cmake .. -DCMAKE_INSTALL_PREFIX=$MYSQL_PREFIX/usr/local/mysql -DTMPDIR=$MYSQL_PREFIX/tmp/ -DSYSCONFDIR=$MYSQL_PREFIX/usr/local/mysql 34 | make 35 | make install 36 | ``` 37 | 38 | Copy the config file from this repository. 39 | Modify `innodb_buffer_pool_size` to a value of main memory that you can dedicate to MySQL. 40 | The current value is `200GB`, which may be too much for your machine. 41 | 42 | ```bash 43 | cp $MAINREPO/workload-traces/mysql/my.cnf $MYSQL_PREFIX/usr/local/mysql/ 44 | ``` 45 | 46 | Set up MySQL server: 47 | 48 | ```bash 49 | sudo groupadd mysql 50 | sudo useradd -g mysql mysql 51 | sudo mkdir $MYSQL_PREFIX/tmp 52 | sudo chown -R mysql:mysql $MYSQL_PREFIX/tmp 53 | cd $MYSQL_PREFIX/usr/local/mysql/ 54 | sudo scripts/mysql_install_db --defaults-file=$MYSQL_PREFIX/usr/local/mysql/my.cnf --user=mysql 55 | export PATH=$MYSQL_PREFIX/usr/local/mysql/bin:$PATH 56 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MYSQL_PREFIX/usr/local/mysql/lib 57 | ``` 58 | 59 | Create a folder for the trace files and export `TRACEDIR` with its path. Start MySQL server: 60 | 61 | ```bash 62 | # pick one 63 | sudo -u mysql $MYSQL_PREFIX/usr/local/mysql/bin/mysqld --defaults-file=$MYSQL_PREFIX/usr/local/mysql/my.cnf --transaction-isolation READ-COMMITTED 2> $TRACEDIR/server.trc & 64 | sudo -u mysql $MYSQL_PREFIX/usr/local/mysql/bin/mysqld --defaults-file=$MYSQL_PREFIX/usr/local/mysql/my.cnf --transaction-isolation REPEATABLE-READ 2> $TRACEDIR/server.trc & 65 | sudo -u mysql $MYSQL_PREFIX/usr/local/mysql/bin/mysqld --defaults-file=$MYSQL_PREFIX/usr/local/mysql/my.cnf --transaction-isolation SERIALIZABLE 2> $TRACEDIR/server.trc & 66 | ``` 67 | 68 | ### Benchmark drivers 69 | 70 | #### TPC-C 71 | 72 | Checkout repository: 73 | 74 | ```bash 75 | git clone git@gitlab.inf.ethz.ch:muellein/tpcc-mysql.git $MAINREPO/workload-traces/mysql/3rdparty/tpcc-mysql 76 | # or 77 | $MAINREPO/workload-traces/mysql/3rdparty/download-tpcc-mysql.sh 78 | ``` 79 | 80 | Build and install (this assumes that `PATH` has been modified as described above): 81 | 82 | ```bash 83 | cd $MAINREPO/workload-traces/mysql/3rdparty/tpcc-mysql 84 | export TPCC_REPO=$PWD 85 | cd $TPCC_REPO/src 86 | make 87 | ``` 88 | 89 | Load data: 90 | 91 | ```bash 92 | mysql --defaults-file=$MYSQL_PREFIX/usr/local/mysql/my.cnf -u root -e "CREATE DATABASE tpcc;" 93 | mysql --defaults-file=$MYSQL_PREFIX/usr/local/mysql/my.cnf -u root tpcc < $TPCC_REPO/create_table.sql 94 | mysql --defaults-file=$MYSQL_PREFIX/usr/local/mysql/my.cnf -u root tpcc < $TPCC_REPO/add_fkey_idx.sql 95 | $TPCC_REPO/tpcc_load -h 127.0.0.1 -d tpcc -u root -w 2 96 | ``` 97 | 98 | **Restart MySQL** with a fresh trace file, then run the benchmark: 99 | 100 | ```bash 101 | $TPCC_REPO/tpcc_start -h 127.0.0.1 -d tpcc -u root -w 2 -c 1 -r 10 -l$((1*60)) -i 10 > $TRACEDIR/client.trc 102 | sudo -u mysql killall mysqld 103 | ``` 104 | 105 | ##### Configurations used in the paper 106 | 107 | Generate data sets for `NUMWH` warehouses using this configuration of `tpcc_load`: 108 | (the paper shows numbers for `NUMWH`=64, 1024, 2048). 109 | 110 | ```bash 111 | $TPCC_REPO/tpcc_load -h 127.0.0.1 -d tpcc$NUMWH -u root -w $NUMWH 112 | ``` 113 | 114 | Run benchmark using this configuration of `tpcc_start` 115 | for all data sets and all isolation modes mentioned above 116 | (nine configurations in total, each running for 24 hours): 117 | 118 | ```bash 119 | $TPCC_REPO/tpcc_start -h 127.0.0.1 -d tpcc$NUMWH -u root -w $NUMWH -c 1 -r 10 -l$((24*60*60)) -i 10 120 | ``` 121 | 122 | #### Common 123 | 124 | Backup generated data (to reuse it in another experiment): 125 | 126 | ```bash 127 | sudo -u mysql killall mysqld 128 | cd $MYSQL_PREFIX/usr/local/mysql 129 | sudo find . -regextype egrep -iregex "./(data/(ibdata.*|.*.ibd|.*.frm|ib_logfile.*)|my.cnf)" \ 130 | | xargs sudo tar -cpSf tpcc-1024wh.tar 131 | ``` 132 | 133 | Restore backup: 134 | 135 | ```bash 136 | sudo -u mysql killall mysqld 137 | cd $MYSQL_PREFIX/usr/local/mysql 138 | sudo rm -rf $MYSQL_PREFIX/usr/local/mysql/data 139 | sudo scripts/mysql_install_db --user=mysql 140 | sudo tar -xpf tpcc-1024wh.tar 141 | ``` 142 | 143 | ### Parse results 144 | 145 | Install prerequisites: 146 | 147 | ```bash 148 | sudo apt install \ 149 | cmake \ 150 | jq \ 151 | libboost-program-options-dev \ 152 | pixz \ 153 | xz-utils 154 | ``` 155 | 156 | Build parsing utility: 157 | 158 | ```bash 159 | cd $MAINREPO/workload-traces/mysql/tpcc/make_trace/build 160 | cmake ../src 161 | make 162 | ``` 163 | 164 | #### TPC-C 165 | 166 | Produce final trace file (you may need to adapt the flags in `SORTFLAGS_BIG` and `SORTFLAGS_SMALL` to fit the main memory of your machine): 167 | 168 | ```bash 169 | cd $TRACEDIR 170 | make -f $MAINREPO/workload-traces/mysql/tpcc/Makefile-parse.mk 171 | ``` 172 | 173 | The result files are the `wh*.csv.xz` files with the locks traced for each warehouse as well as `max-locks-per-wh.meta` with the maximum number of locks assigned to any warehouse (which defines the size of a lock range of lock table servers). 174 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/transactions/ReplayClient.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ReplayClient.cpp 3 | * 4 | * Created on: Apr 22, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include "ReplayClient.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | namespace hdb { 17 | namespace transactions { 18 | 19 | ReplayClient::ReplayClient(hdb::configuration::SystemConfig* config, std::string fileLocation, uint64_t numberOfTransactions) : 20 | TransactionAgent(config) { 21 | 22 | this->numberOfTransactions = numberOfTransactions; 23 | 24 | 25 | this->clientId = config->internalRank; 26 | 27 | uint32_t clientsPerWarehouse = config->globalNumberOfTransactionAgents / config->globalNumberOfWarehouses; 28 | 29 | if(clientsPerWarehouse == 0){ 30 | float delta = (float)config->globalNumberOfWarehouses / (float)config->globalNumberOfTransactionAgents; 31 | this->warehouseId = static_cast(this->clientId * delta) ; 32 | this->clientsPerWarehouse = 1; 33 | this->localclientid = 0; 34 | } else { 35 | 36 | uint32_t idx = 0; 37 | for( ; idx < config->globalNumberOfWarehouses; idx++){ 38 | if(this->clientId>=config->warehouseToLockServer[idx] && this->clientIdwarehouseToLockServer[idx+1]){ 39 | //found 40 | break; 41 | } 42 | } 43 | 44 | this->warehouseId = idx; 45 | this->clientsPerWarehouse = config->warehouseToLockServer[idx+1] - config->warehouseToLockServer[idx]; 46 | this->localclientid = this->clientId - config->warehouseToLockServer[idx]; 47 | } 48 | 49 | this->fileLocation = fileLocation; 50 | 51 | this->globalTableSize = config->globalNumberOfLocks; 52 | } 53 | 54 | ReplayClient::~ReplayClient() { 55 | 56 | } 57 | 58 | void ReplayClient::generate() { 59 | 60 | hdb::transactions::Transaction *item = NULL; 61 | uint64_t currentTransactionId = 0; 62 | 63 | uint64_t transactioncounter = 0; 64 | uint64_t skip = 0; 65 | 66 | transactions.reserve(numberOfTransactions); 67 | 68 | 69 | // Check binary first. 70 | std::ostringstream stringStream; 71 | stringStream << fileLocation << "/wh" << this->warehouseId + 1 << "_" << numberOfTransactions << "_" <warehouseId + 1,numberOfTransactions,localclientid,clientsPerWarehouse); 74 | for(std::string str : config->transaction_constraints){ 75 | stringStream << "_"; 76 | stringStream << str; 77 | } 78 | stringStream << ".bin"; 79 | 80 | std::string copyOfStr = stringStream.str(); 81 | 82 | 83 | std::ifstream ifs(copyOfStr.c_str()); 84 | if(ifs.good()) { // file exist 85 | boost::archive::binary_iarchive ia(ifs); 86 | uint32_t size = 0; 87 | ia >> size; 88 | transactions.resize(size); 89 | ia >> boost::serialization::make_array(transactions.data(), size); 90 | return; 91 | } 92 | DLOG_ALWAYS("ReplayClient", "binary did not exist"); 93 | // return; 94 | char fileName[1024]; 95 | memset(fileName, 0, 1024); 96 | sprintf(fileName, "%s/wh%06d.csv", fileLocation.c_str(), this->warehouseId + 1 ); 97 | FILE *file = fopen(fileName, "r"); 98 | 99 | 100 | while (transactions.size() < numberOfTransactions) { 101 | 102 | uint64_t transactionId; 103 | uint64_t lockId; 104 | char lockMode[2]; 105 | char queryType[16]; 106 | 107 | char lineBuffer[128]; 108 | bool validRead = (fgets(lineBuffer, sizeof(lineBuffer), file) != NULL); 109 | if(validRead){ 110 | int readItems = sscanf(lineBuffer, "%lu,%lu,%2[^,],%s", &transactionId, &lockId, lockMode, queryType); 111 | validRead = (readItems == 4); 112 | } 113 | if (!validRead) { 114 | if (skip != transactionId && item != NULL) { 115 | transactions.push_back(*item); 116 | } 117 | delete item; 118 | 119 | //stop processing 120 | break; 121 | } 122 | 123 | 124 | if(skip == transactionId){ 125 | continue; 126 | } 127 | 128 | if (transactionId != currentTransactionId) { // new transaction 129 | 130 | 131 | if (item != NULL) { 132 | if(item->requests.size() < 750) { 133 | transactions.push_back(*item); 134 | } else { 135 | DLOG_ALWAYS("ReplayClient", "Ignoring transaction that has %lu locks", item->requests.size()); 136 | } 137 | delete item; 138 | item = NULL; 139 | } 140 | 141 | currentTransactionId = transactionId; 142 | 143 | // check constraints 144 | if( !config->transaction_constraints.empty() ){ 145 | // if not in the list 146 | if (std::find(config->transaction_constraints.begin(), config->transaction_constraints.end(), queryType) == config->transaction_constraints.end()){ 147 | skip = transactionId; 148 | continue; 149 | } 150 | } 151 | 152 | transactioncounter++; 153 | 154 | if( (transactioncounter - 1) % clientsPerWarehouse != localclientid){ 155 | skip = transactionId; 156 | continue; 157 | } 158 | 159 | // the trace has only one type per transaction 160 | item = new hdb::transactions::Transaction(hdb::transactions::DATA_MODE_FROM_STRING(queryType)); 161 | DLOG("ReplayClient", "Starting new transaction"); 162 | } 163 | 164 | 165 | DLOG("ReplayClient", "Read workload item (%lu %lu %s %s).", transactionId, lockId, lockMode, queryType); 166 | item->requests.push_back(lockid_mode_pair_t(lockId , hdb::locktable::LOCK_MODE_FROM_STRING(lockMode))); 167 | } 168 | 169 | fclose(file); 170 | 171 | // printf("Saving %s\n", copyOfStr.c_str()); 172 | 173 | std::ofstream ofs(copyOfStr.c_str()); 174 | { 175 | boost::archive::binary_oarchive oa(ofs); 176 | uint32_t size = transactions.size(); 177 | oa << size; 178 | oa << boost::serialization::make_array(transactions.data(), size); 179 | } 180 | 181 | // DLOG("ReplayClient", "Client %d finished reading file and has %lu transactions", config->internalRank, transactions.size()); 182 | 183 | } 184 | 185 | void ReplayClient::execute() { 186 | 187 | tpccExecute(warehouseId, numberOfTransactions); 188 | } 189 | 190 | } /* namespace transactions */ 191 | } /* namespace hdb */ 192 | -------------------------------------------------------------------------------- /test_cray_mpi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | usage () { 4 | echo "Script for running with mpi" 5 | echo "options:" 6 | echo " --dir=PATH (default=PWD) #absolute path to the project" 7 | echo " --out=FILENAME (default=out-PARAMS) #output filename which will be create at --dir" 8 | echo " --nodes=INT (default=1) #the number of nodes" 9 | echo " --sockets=INT (default=2) #the number of sockets per node" 10 | echo " --processes=INT (default=16) #the number of transaction processes per node," 11 | echo " #it also specifies the number of lock processes per node" 12 | echo " --locksperwh=INT (default=1024) #the number of locks per warehouse" 13 | echo " --numwhs=INT (default=1024) #the number of warehouses" 14 | echo " --remotelockprob=0-100 (default=0) #the probability of remote lock" 15 | echo " --workloadsize=INT (default=1000000) #the number of transactions to be executed per client" 16 | echo " --timelimit=INT (default=120) #limit runtime in seconds" 17 | echo " --comdelay=INT (default=0) #add a delay in nanosec before each communication" 18 | echo "" 19 | echo "" 20 | echo " Transaction algorithm:" 21 | echo " --simple2pl (default) #simple 2PL " 22 | echo " --waitdie #wait-die strategy" 23 | echo " --nowait #nowait lock strategy" 24 | echo " --timestamp #timestamp lock strategy" 25 | echo "" 26 | echo "" 27 | echo " Job additional arguments: " 28 | echo " --jobname=STRING (default=job.sh) #the name if output script" 29 | echo " --jobtime=HOURS:MIN:SEC (default=00:18:00) #add time limit of a job script" 30 | } 31 | 32 | 33 | WORKDIR=${PWD}/ 34 | NODES=1 35 | SOCKETS_PER_NODE=2 36 | TRAN_PROCESSES_PER_NODE=16 37 | WORKLOADSIZE=1000000 38 | COMDELAY=0 39 | ALGORITHM="simple2pl" 40 | TIMELIMIT=120 41 | LOCKSPERWH="1024" 42 | NUMWHS="1024" 43 | REMOTEPROB=0 44 | JOBTIME="00:18:00" 45 | JOBNAME="job.sh" 46 | FILENAME="" 47 | 48 | for arg in "$@" 49 | do 50 | case ${arg} in 51 | --help|-help|-h) 52 | usage 53 | exit 1 54 | ;; 55 | --dir=*) 56 | WORKDIR=`echo $arg | sed -e 's/--dir=//'` 57 | WORKDIR=`eval echo ${WORKDIR}` # tilde and variable expansion 58 | ;; 59 | --workloadDir=*) 60 | DATADIR=`echo $arg | sed -e 's/--workloadDir=//'` 61 | DATADIR=`eval echo ${DATADIR}` # tilde and variable expansion 62 | ;; 63 | --nodes=*) 64 | NODES=`echo $arg | sed -e 's/--nodes=//'` 65 | NODES=`eval echo ${NODES}` # tilde and variable expansion 66 | ;; 67 | --sockets=*) 68 | SOCKETS_PER_NODE=`echo $arg | sed -e 's/--sockets=//'` 69 | SOCKETS_PER_NODE=`eval echo ${SOCKETS_PER_NODE}` # tilde and variable expansion 70 | ;; 71 | --processes=*) 72 | TRAN_PROCESSES_PER_NODE=`echo $arg | sed -e 's/--processes=//'` 73 | TRAN_PROCESSES_PER_NODE=`eval echo ${TRAN_PROCESSES_PER_NODE}` # tilde and variable expansion 74 | ;; 75 | --workloadsize=*) 76 | WORKLOADSIZE=`echo $arg | sed -e 's/--workloadsize=//'` 77 | WORKLOADSIZE=`eval echo ${WORKLOADSIZE}` # tilde and variable expansion 78 | ;; 79 | --comdelay=*) 80 | COMDELAY=`echo $arg | sed -e 's/--comdelay=//'` 81 | COMDELAY=`eval echo ${COMDELAY}` # tilde and variable expansion 82 | ;; 83 | --timelimit=*) 84 | TIMELIMIT=`echo $arg | sed -e 's/--timelimit=//'` 85 | TIMELIMIT=`eval echo ${TIMELIMIT}` # tilde and variable expansion 86 | ;; 87 | --losksperwh=*) 88 | LOCKSPERWH=`echo $arg | sed -e 's/--losksperwh=//'` 89 | LOCKSPERWH=`eval echo ${LOCKSPERWH}` # tilde and variable expansion 90 | ;; 91 | --numwhs=*) 92 | NUMWHS=`echo $arg | sed -e 's/--numwhs=//'` 93 | NUMWHS=`eval echo ${NUMWHS}` # tilde and variable expansion 94 | ;; 95 | --remotelockprob=*) 96 | REMOTEPROB=`echo $arg | sed -e 's/--remotelockprob=//'` 97 | REMOTEPROB=`eval echo ${REMOTEPROB}` # tilde and variable expansion 98 | ;; 99 | --jobtime=*) 100 | JOBTIME=`echo $arg | sed -e 's/--jobtime=//'` 101 | JOBTIME=`eval echo ${JOBTIME}` # tilde and variable expansion 102 | ;; 103 | --jobname=*) 104 | JOBNAME=`echo $arg | sed -e 's/--jobname=//'` 105 | JOBNAME=`eval echo ${JOBNAME}` # tilde and variable expansion 106 | ;; 107 | --waitdie) 108 | ALGORITHM="waitdie" 109 | ;; 110 | --nowait) 111 | ALGORITHM="nowait" 112 | ;; 113 | --timestamp) 114 | ALGORITHM="timestamp" 115 | ;; 116 | --out=*) 117 | FILENAME=`echo $arg | sed -e 's/--out=//'` 118 | FILENAME=`eval echo ${FILENAME}` # tilde and variable expansion 119 | ;; 120 | esac 121 | done 122 | 123 | echo "Start Generating the job script" 124 | 125 | if [ -z "${FILENAME}" ]; then 126 | OUTFILENAME="out-synthetic-${NUMWHS}-${NODES}-${TRAN_PROCESSES_PER_NODE}-${TRAN_PROCESSES_PER_NODE}-${COMDELAY}-${ALGORITHM}" 127 | else 128 | OUTFILENAME=${FILENAME} 129 | fi 130 | 131 | echo "#!/bin/bash -l" > ${JOBNAME} 132 | echo "#SBATCH --job-name=${OUTFILENAME}" >> ${JOBNAME} 133 | echo "#SBATCH --time=${JOBTIME}" >> ${JOBNAME} 134 | echo "#SBATCH --nodes=${NODES}" >> ${JOBNAME} 135 | echo "#SBATCH --ntasks-per-node=$((${TRAN_PROCESSES_PER_NODE}*2))" >> ${JOBNAME} 136 | echo "#SBATCH --ntasks-per-core=1" >> ${JOBNAME} 137 | echo "#SBATCH --partition=normal" >> ${JOBNAME} 138 | echo "#SBATCH --constraint=mc" >> ${JOBNAME} 139 | echo "#SBATCH --hint=nomultithread" >> ${JOBNAME} 140 | echo "" >> ${JOBNAME} 141 | 142 | echo "srun ${WORKDIR}/HumongousLock/release/hdb-lock --synthetic --remotelockprob=${REMOTEPROB} --timelimit=${TIMELIMIT} --warehouses=${NUMWHS} --processespernode=${TRAN_PROCESSES_PER_NODE} --locksperwh=${LOCKSPERWH} --socketspernode=${SOCKETS_PER_NODE} --localworkloadsize=${WORKLOADSIZE} --comdelay=${COMDELAY} --logname=${WORKDIR}/${OUTFILENAME} --${ALGORITHM}" >> ${JOBNAME} 143 | 144 | echo "The job script has been created" 145 | 146 | echo "Now, you can submit the job using:" 147 | echo "sbatch ${JOBNAME}" 148 | 149 | 150 | -------------------------------------------------------------------------------- /run_cray_mpi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | usage () { 4 | echo "Script for running with mpi" 5 | echo "options:" 6 | echo " --dir=PATH (default=PWD) #absolute path to the project" 7 | echo " --workloadDir=PATH (required) #absolute path to the workload" 8 | echo " --out=FILENAME (default=out-PARAMS) #output filename which will be create at --dir" 9 | echo " --nodes=INT (default=1) #the number of nodes" 10 | echo " --sockets=INT (default=2) #the number of sockets per node" 11 | echo " --processes=INT (default=16) #the number of transaction processes per node," 12 | echo " #it also specifies the number of lock processes per node" 13 | echo " --workloadsize=INT (default=1000000) #the number of transactions to be executed per client" 14 | echo " --timelimit=INT (default=120) #limit runtime in seconds" 15 | echo " --nopreprocessing #disable preprocessing of the workload before execution" 16 | echo " --comdelay=INT (default=0) #add a delay in nanosec before each communication" 17 | echo "" 18 | echo "" 19 | echo " Transaction algorithm:" 20 | echo " --simple2pl (default) #simple 2PL " 21 | echo " --waitdie #wait-die strategy" 22 | echo " --nowait #nowait lock strategy" 23 | echo " --timestamp #timestamp lock strategy" 24 | echo "" 25 | echo "" 26 | echo " Job additional arguments: " 27 | echo " --jobname=STRING (default=job.sh) #the name if output script" 28 | echo " --jobtime=HOURS:MIN:SEC (default=00:18:00) #add time limit of a job script" 29 | } 30 | 31 | 32 | WORKDIR=${PWD}/ 33 | DATADIR="" 34 | NODES=1 35 | SOCKETS_PER_NODE=2 36 | TRAN_PROCESSES_PER_NODE=16 37 | WORKLOADSIZE=1000000 38 | COMDELAY=0 39 | PREPROCESSING=1 40 | ALGORITHM="simple2pl" 41 | TIMELIMIT=120 42 | JOBTIME="00:18:00" 43 | JOBNAME="job.sh" 44 | 45 | FILENAME="" 46 | 47 | for arg in "$@" 48 | do 49 | case ${arg} in 50 | --help|-help|-h) 51 | usage 52 | exit 1 53 | ;; 54 | --dir=*) 55 | WORKDIR=`echo $arg | sed -e 's/--dir=//'` 56 | WORKDIR=`eval echo ${WORKDIR}` # tilde and variable expansion 57 | ;; 58 | --workloadDir=*) 59 | DATADIR=`echo $arg | sed -e 's/--workloadDir=//'` 60 | DATADIR=`eval echo ${DATADIR}` # tilde and variable expansion 61 | ;; 62 | --nodes=*) 63 | NODES=`echo $arg | sed -e 's/--nodes=//'` 64 | NODES=`eval echo ${NODES}` # tilde and variable expansion 65 | ;; 66 | --sockets=*) 67 | SOCKETS_PER_NODE=`echo $arg | sed -e 's/--sockets=//'` 68 | SOCKETS_PER_NODE=`eval echo ${SOCKETS_PER_NODE}` # tilde and variable expansion 69 | ;; 70 | --processes=*) 71 | TRAN_PROCESSES_PER_NODE=`echo $arg | sed -e 's/--processes=//'` 72 | TRAN_PROCESSES_PER_NODE=`eval echo ${TRAN_PROCESSES_PER_NODE}` # tilde and variable expansion 73 | ;; 74 | --workloadsize=*) 75 | WORKLOADSIZE=`echo $arg | sed -e 's/--workloadsize=//'` 76 | WORKLOADSIZE=`eval echo ${WORKLOADSIZE}` # tilde and variable expansion 77 | ;; 78 | --comdelay=*) 79 | COMDELAY=`echo $arg | sed -e 's/--comdelay=//'` 80 | COMDELAY=`eval echo ${COMDELAY}` # tilde and variable expansion 81 | ;; 82 | --timelimit=*) 83 | TIMELIMIT=`echo $arg | sed -e 's/--timelimit=//'` 84 | TIMELIMIT=`eval echo ${TIMELIMIT}` # tilde and variable expansion 85 | ;; 86 | --jobtime=*) 87 | JOBTIME=`echo $arg | sed -e 's/--jobtime=//'` 88 | JOBTIME=`eval echo ${JOBTIME}` # tilde and variable expansion 89 | ;; 90 | --jobname=*) 91 | JOBNAME=`echo $arg | sed -e 's/--jobname=//'` 92 | JOBNAME=`eval echo ${JOBNAME}` # tilde and variable expansion 93 | ;; 94 | --nopreprocessing) 95 | PREPROCESSING=0 96 | ;; 97 | --waitdie) 98 | ALGORITHM="waitdie" 99 | ;; 100 | --nowait) 101 | ALGORITHM="nowait" 102 | ;; 103 | --timestamp) 104 | ALGORITHM="timestamp" 105 | ;; 106 | --out=*) 107 | FILENAME=`echo $arg | sed -e 's/--out=//'` 108 | FILENAME=`eval echo ${FILENAME}` # tilde and variable expansion 109 | ;; 110 | esac 111 | done 112 | 113 | if [ -z "$DATADIR" ] 114 | then 115 | echo "[Error] --workloadDir is not specified" 116 | usage 117 | exit 1 118 | fi 119 | 120 | 121 | NUMWHS=$(ls ${DATADIR}/*.csv | sed 's!.*/!!' | grep -o -E '[0-9]+' | sort -nr | head -1 | sed 's/^0*//') 122 | LOCKSPERWH=$(cat ${DATADIR}/max-locks-per-wh.meta | grep -oP '^[^0-9]*\K[0-9]+') 123 | 124 | 125 | FOLDERNAME=$(basename ${DATADIR}) 126 | 127 | if [ -z "${FILENAME}" ]; then 128 | OUTFILENAME="out-${FOLDERNAME}-${NUMWHS}-${NODES}-${TRAN_PROCESSES_PER_NODE}-${TRAN_PROCESSES_PER_NODE}-${COMDELAY}-${ALGORITHM}" 129 | else 130 | OUTFILENAME=${FILENAME} 131 | fi 132 | 133 | 134 | 135 | if [ "$PREPROCESSING" -eq "1" ]; then 136 | echo "Start Preprocessing the workload" 137 | ${WORKDIR}/HumongousLock/release/preprocess --warehouses=${NUMWHS} --processespernode=${TRAN_PROCESSES_PER_NODE} --locksperwh=${LOCKSPERWH} --localworkloadsize=${WORKLOADSIZE} --workloadlocation=${DATADIR} --numberofnodes=${NODES} 138 | echo "The workload has been preprocessed" 139 | fi 140 | 141 | 142 | echo "Start Generating the job script" 143 | 144 | echo "#!/bin/bash -l" > ${JOBNAME} 145 | echo "#SBATCH --job-name=${OUTFILENAME}" >> ${JOBNAME} 146 | echo "#SBATCH --time=${JOBTIME}" >> ${JOBNAME} 147 | echo "#SBATCH --nodes=${NODES}" >> ${JOBNAME} 148 | echo "#SBATCH --ntasks-per-node=$((${TRAN_PROCESSES_PER_NODE}*2))" >> ${JOBNAME} 149 | echo "#SBATCH --ntasks-per-core=1" >> ${JOBNAME} 150 | echo "#SBATCH --partition=normal" >> ${JOBNAME} 151 | echo "#SBATCH --constraint=mc" >> ${JOBNAME} 152 | echo "#SBATCH --hint=nomultithread" >> ${JOBNAME} 153 | echo "" >> ${JOBNAME} 154 | 155 | echo "srun ${WORKDIR}/HumongousLock/release/hdb-lock --timelimit=${TIMELIMIT} --warehouses=${NUMWHS} --processespernode=${TRAN_PROCESSES_PER_NODE} --locksperwh=${LOCKSPERWH} --socketspernode=${SOCKETS_PER_NODE} --localworkloadsize=${WORKLOADSIZE} --workloadlocation=${DATADIR} --comdelay=${COMDELAY} --logname=${WORKDIR}/${OUTFILENAME} --${ALGORITHM}" >> ${JOBNAME} 156 | 157 | echo "The job script has been created" 158 | 159 | echo "Now, you can submit the job using:" 160 | echo "sbatch ${JOBNAME}" 161 | 162 | 163 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/transactions/TransactionManager.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TransactionManager.cpp 3 | * 4 | * Created on: Apr 19, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include "TransactionManager.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | 17 | namespace hdb { 18 | namespace transactions { 19 | 20 | TransactionManager::TransactionManager(hdb::configuration::SystemConfig *config, 21 | hdb::communication::Communicator *communicator, 22 | hdb::stats::ClientStats *stats): randomLockAssign(config->hashlock), globalNumberOfWarehouses(config->globalNumberOfWarehouses), timestampordering(config->timestamp), warehouseToLockServer(config->warehouseToLockServer){ 23 | 24 | this->communicator = communicator; 25 | this->stats = stats; 26 | this->lockServerGlobalRanks = config->lockServerGlobalRanks; 27 | this->locksPerWarehouse = config->locksPerWarehouse; 28 | this->globalRank = config->globalRank; 29 | 30 | transaction_time = -1; 31 | transactionId = 0; 32 | involvedLockServers.clear(); 33 | involvedVoteServers.clear(); 34 | voteNeeded = false; 35 | 36 | } 37 | 38 | TransactionManager::~TransactionManager() { 39 | 40 | } 41 | 42 | void TransactionManager::startTransaction() { 43 | //++transactionId; 44 | involvedLockServers.clear(); 45 | involvedVoteServers.clear(); 46 | voteNeeded = false; 47 | uint64_t temp = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); 48 | if(transaction_time == temp){ 49 | transaction_time = temp + 1; 50 | DLOG_ALWAYS("TransactionManager", "Increment time"); 51 | }else{ 52 | transaction_time = temp; 53 | } 54 | transactionId = (transaction_time<<24) + globalRank; 55 | DLOG("TransactionManager", "Starting transaction %d", transactionId); 56 | } 57 | 58 | void TransactionManager::abortTransaction(hdb::transactions::DataMode txId) { 59 | 60 | DLOG("TransactionManager", "Transaction %d wants to abort", transactionId); 61 | bool isNewOrderTx = (txId == hdb::transactions::DataMode::NEWORD); 62 | stats->startTransactionEnd(isNewOrderTx, involvedLockServers.size()); 63 | new (&abortRequest) hdb::messages::AbortTransaction(globalRank, transactionId); 64 | for (auto it = involvedLockServers.begin(); it != involvedLockServers.end(); ++it) { 65 | uint32_t lockServerId = (*it); 66 | communicator->sendMessage(&abortRequest, lockServerId); 67 | } 68 | communicator->waitForTransactionEndSignals(involvedLockServers.size()); 69 | stats->stopTransactionEnd(false,isNewOrderTx); 70 | 71 | } 72 | 73 | void TransactionManager::commitTransaction(hdb::transactions::DataMode txId) { 74 | 75 | if (involvedVoteServers.size() > 1 && !this->timestampordering) { 76 | DLOG("TransactionManager", "Transaction %d required vote", transactionId); 77 | stats->startVote(); 78 | for (auto it = involvedVoteServers.begin(); it != involvedVoteServers.end(); ++it) { 79 | uint32_t lockServerId = (*it); 80 | new (&voteRequest) hdb::messages::VoteRequest(globalRank, transactionId); 81 | communicator->sendMessage(&voteRequest, lockServerId); 82 | } 83 | bool outcome = false; 84 | while (!communicator->checkVoteReady(&outcome, involvedVoteServers.size())) 85 | ; 86 | stats->stopVote(outcome); 87 | DLOG("TransactionManager", "Transaction %d completed vote", transactionId); 88 | } 89 | 90 | DLOG("TransactionManager", "Transaction %d wants to commit", transactionId); 91 | bool isNewOrderTx = (txId == hdb::transactions::DataMode::NEWORD); 92 | stats->startTransactionEnd(isNewOrderTx, involvedLockServers.size()); 93 | new (&endTransaction) hdb::messages::TransactionEnd(globalRank, transactionId); 94 | for (auto it = involvedLockServers.begin(); it != involvedLockServers.end(); ++it) { 95 | uint32_t lockServerId = (*it); 96 | communicator->sendMessage(&endTransaction, lockServerId); 97 | } 98 | communicator->waitForTransactionEndSignals(involvedLockServers.size()); 99 | stats->stopTransactionEnd(true,isNewOrderTx); 100 | 101 | } 102 | 103 | 104 | inline static uint32_t hash(uint32_t x) { 105 | x = ((x >> 16) ^ x) * 0x45d9f3b; 106 | x = ((x >> 16) ^ x) * 0x45d9f3b; 107 | x = (x >> 16) ^ x; 108 | return x; 109 | } 110 | 111 | 112 | bool TransactionManager::requestLock(uint64_t lockId, hdb::locktable::LockMode mode) { 113 | 114 | if (this->timestampordering && !LOCK_READ_OR_WRITE(mode)) { 115 | return true; 116 | } 117 | 118 | uint32_t temp = (randomLockAssign ? hash(lockId) : lockId ); 119 | uint32_t targetWarehouse = (temp / locksPerWarehouse) % globalNumberOfWarehouses; 120 | uint32_t targetLockServerInternalRank = this->warehouseToLockServer[targetWarehouse]; 121 | 122 | uint32_t warehouseSharedBy = this->warehouseToLockServer[targetWarehouse + 1] - this->warehouseToLockServer[targetWarehouse]; 123 | if(warehouseSharedBy > 1){ 124 | targetLockServerInternalRank += (temp / (locksPerWarehouse/ warehouseSharedBy)) % warehouseSharedBy; 125 | } 126 | 127 | uint32_t targetGlobalRank = lockServerGlobalRanks[targetLockServerInternalRank]; 128 | 129 | DLOG("TransactionManager", "Target lock manager is %d for request (%lu, %d)", targetGlobalRank, lockId, (uint32_t) mode); 130 | 131 | new (&lockRequest) hdb::messages::LockRequest(globalRank, transactionId, lockId, mode); 132 | #ifdef USE_LOGGING 133 | lockRequest.clientSendTime = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); 134 | #endif 135 | bool communicationIsLocal = communicator->sendMessage(&lockRequest, targetGlobalRank); 136 | 137 | involvedLockServers.insert(targetGlobalRank); 138 | stats->issuedLockRequest(&lockRequest, !communicationIsLocal); 139 | 140 | if(mode == hdb::locktable::LockMode::X){ 141 | involvedVoteServers.insert(targetGlobalRank); 142 | } 143 | 144 | hdb::messages::Message *message = communicator->getMessageBlocking(); 145 | 146 | assert(message->messageType == hdb::messages::MessageType::LOCK_GRANT_MESSAGE); 147 | 148 | hdb::messages::LockGrant *grant = (hdb::messages::LockGrant *) message; 149 | #ifdef USE_LOGGING 150 | grant->clientReceiveTime = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); 151 | #endif 152 | stats->receivedLockAnswer(grant); 153 | 154 | assert(grant->transactionNumber == transactionId); 155 | assert(grant->lockId == lockId); 156 | assert(grant->mode == mode); 157 | assert(grant->clientGlobalRank == globalRank); 158 | DLOG("TransactionManager", "Transaction get reply for lock %lu in transaction %lu ",lockId, transactionId); 159 | 160 | if(!grant->granted) { 161 | DLOG("TransactionManager", "Lock (%lu, %d) was not granted", lockId, (uint32_t) mode); 162 | } 163 | 164 | 165 | return grant->granted; 166 | 167 | } 168 | 169 | 170 | } /* namespace transactions */ 171 | } /* namespace hdb */ 172 | -------------------------------------------------------------------------------- /generate_batch_job.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | usage () { 4 | echo "Script for generating batch job scripts" 5 | echo "options:" 6 | echo " --dir=PATH (default=PWD) #absolute path to the project" 7 | echo " --workloadsDir=PATH (required) #absolute path to the folder with workloads" 8 | echo " #the script will iterate through folders to find workloads" 9 | echo " --workloadDir=PATH (required) #absolute path to the folder with the workload you want to execute" 10 | echo " #workloadsDir or workloadDir must be specified" 11 | echo " --nodes=INT (default=1) #the number of nodes" 12 | echo " --comdelays=INT[,INT] (default=0) #add a delay in nanosec before each communication" 13 | echo " #specify delays separated with comma" 14 | echo "" 15 | echo " Transaction algorithms:" 16 | echo " Use the flags you want to use to generate scripts for the following algorithms " 17 | echo " --simple2pl #simple 2PL " 18 | echo " --waitdie #wait-die strategy" 19 | echo " --nowait #nowait lock strategy" 20 | echo " --timestamp #timestamp lock strategy" 21 | echo "" 22 | echo " Job additional arguments: " 23 | echo " --jobname=STRING (default=job.sh) #the name if output script" 24 | echo " --jobtime=INT (default=5) #expected time of 1 job in minutes" 25 | } 26 | 27 | 28 | WORKDIR=${PWD}/ 29 | DATADIR="" 30 | THEWORKLOADDIR="" 31 | NODES="1" 32 | COMDELAYS="0" 33 | ALGORITHMS=() 34 | JOBTIME="5" 35 | JOBNAME="job.sh" 36 | 37 | 38 | for arg in "$@" 39 | do 40 | case ${arg} in 41 | --help|-help|-h) 42 | usage 43 | exit 1 44 | ;; 45 | --dir=*) 46 | WORKDIR=`echo $arg | sed -e 's/--dir=//'` 47 | WORKDIR=`eval echo ${WORKDIR}` # tilde and variable expansion 48 | ;; 49 | --workloadsDir=*) 50 | DATADIR=`echo $arg | sed -e 's/--workloadsDir=//'` 51 | DATADIR=`eval echo ${DATADIR}` # tilde and variable expansion 52 | ;; 53 | --workloadDir=*) 54 | THEWORKLOADDIR=`echo $arg | sed -e 's/--workloadDir=//'` 55 | THEWORKLOADDIR=`eval echo ${THEWORKLOADDIR}` # tilde and variable expansion 56 | ;; 57 | --nodes=*) 58 | NODES=`echo $arg | sed -e 's/--nodes=//'` 59 | NODES=`eval echo ${NODES}` # tilde and variable expansion 60 | ;; 61 | --comdelays=*) 62 | COMDELAYS=`echo $arg | sed -e 's/--comdelay=//'` 63 | COMDELAYS=`eval echo ${COMDELAYS}` # tilde and variable expansion 64 | ;; 65 | --jobtime=*) 66 | JOBTIME=`echo $arg | sed -e 's/--jobtime=//'` 67 | JOBTIME=`eval echo ${JOBTIME}` # tilde and variable expansion 68 | ;; 69 | --jobname=*) 70 | JOBNAME=`echo $arg | sed -e 's/--jobname=//'` 71 | JOBNAME=`eval echo ${JOBNAME}` # tilde and variable expansion 72 | ;; 73 | --simple2pl) 74 | ALGORITHMS+=("simple2pl") 75 | ;; 76 | --waitdie) 77 | ALGORITHMS+=("waitdie") 78 | ;; 79 | --nowait) 80 | ALGORITHMS+=("nowait") 81 | ;; 82 | --timestamp) 83 | ALGORITHMS+=("timestamp") 84 | ;; 85 | esac 86 | done 87 | 88 | 89 | NUMJOBS=1 90 | 91 | convertmins() { 92 | ((h=${1}/60)) 93 | ((m=${1}%60)) 94 | printf "%02d:%02d:00\n" $h $m 95 | } 96 | 97 | if [ -z "$DATADIR" ] && [ -z "$THEWORKLOADDIR" ] 98 | then 99 | echo "[Error] --workloadsDir or --workloadDir must be specified" 100 | usage 101 | exit 1 102 | fi 103 | 104 | counter=0 105 | ALGORITHMSSTR="" 106 | for var in "${ALGORITHMS[@]}" 107 | do 108 | counter=$(($counter+1)) 109 | if [ -z "${ALGORITHMSSTR}" ] 110 | then 111 | ALGORITHMSSTR="\"${var}\"" 112 | else 113 | ALGORITHMSSTR="${ALGORITHMSSTR} \"${var}\"" 114 | fi 115 | done 116 | 117 | NUMJOBS=$((${NUMJOBS}*${counter})) 118 | 119 | if [ -z "${ALGORITHMSSTR}" ] 120 | then 121 | echo "[Error] algorithms are not specified" 122 | usage 123 | exit 1 124 | fi 125 | 126 | counter=0 127 | COMDELAYSSTR="" 128 | for var in $(echo $COMDELAYS | sed "s/,/ /g") 129 | do 130 | counter=$(($counter+1)) 131 | if [ -z "${COMDELAYSSTR}" ] 132 | then 133 | COMDELAYSSTR="\"${var}\"" 134 | else 135 | COMDELAYSSTR="${COMDELAYSSTR} \"${var}\"" 136 | fi 137 | done 138 | NUMJOBS=$((${NUMJOBS}*${counter})) 139 | 140 | if [ -z "${COMDELAYSSTR}" ] 141 | then 142 | COMDELAYSSTR=\"0\" 143 | fi 144 | 145 | counter=0 146 | WORKLOADSSTR="" 147 | 148 | if [ ! -z "$DATADIR" ] 149 | then 150 | for entry in $(ls -d ${DATADIR}/*/ ) 151 | do 152 | if [ -f "$entry/max-locks-per-wh.meta" ]; then 153 | counter=$(($counter+1)) 154 | if [ -z "${WORKLOADSSTR}" ] 155 | then 156 | WORKLOADSSTR="\"$(basename $entry)\"" 157 | else 158 | WORKLOADSSTR="${WORKLOADSSTR} \"$(basename $entry)\"" 159 | fi 160 | fi 161 | done 162 | else 163 | if [ -f "${THEWORKLOADDIR}/max-locks-per-wh.meta" ]; then 164 | counter=$(($counter+1)) 165 | if [ -z "${WORKLOADSSTR}" ] 166 | then 167 | WORKLOADSSTR="\"$(basename ${THEWORKLOADDIR})\"" 168 | else 169 | WORKLOADSSTR="${WORKLOADSSTR} \"$(basename ${THEWORKLOADDIR})\"" 170 | fi 171 | fi 172 | 173 | fi 174 | 175 | NUMJOBS=$((${NUMJOBS}*${counter})) 176 | 177 | 178 | if [ -z "${WORKLOADSSTR}" ] 179 | then 180 | echo "[Error] no workload found in ${DATADIR} or ${THEWORKLOADDIR}" 181 | usage 182 | exit 1 183 | fi 184 | 185 | TOTALTIME=$(convertmins $(($JOBTIME*$NUMJOBS))) 186 | EXECUTABLE="${WORKDIR}/HumongousLock/release/hdb-lock" 187 | 188 | if [ ! -f "$EXECUTABLE" ]; then 189 | echo "[Error] executable is not found at ${EXECUTABLE}" 190 | usage 191 | exit 1 192 | fi 193 | 194 | cp job.template ${JOBNAME} 195 | sed -i "s/\$JOBNAME/${JOBNAME}/g" ${JOBNAME} 196 | sed -i "s/\$NODES/${NODES}/g" ${JOBNAME} 197 | sed -i "s|\$EXECUTABLE|${EXECUTABLE}|" ${JOBNAME} 198 | sed -i "s|\$TOTALTIME|${TOTALTIME}|" ${JOBNAME} 199 | sed -i "s|\$ALGORITHMS|${ALGORITHMSSTR}|" ${JOBNAME} 200 | sed -i "s|\$DELAYS|${COMDELAYSSTR}|" ${JOBNAME} 201 | sed -i "s|\$WORKLOADS|${WORKLOADSSTR}|" ${JOBNAME} 202 | sed -i "s|\$DATADIR|${DATADIR}|" ${JOBNAME} 203 | 204 | 205 | echo "Script ${JOBNAME} has been created" 206 | 207 | echo "We recommend to run preprocess_${JOBNAME} before submitting ${JOBNAME}" 208 | 209 | EXECUTABLE="${WORKDIR}/HumongousLock/release/preprocess" 210 | cp preprocess.template preprocess_${JOBNAME} 211 | chmod +x preprocess_${JOBNAME} 212 | sed -i "s/\$NODES/${NODES}/g" preprocess_${JOBNAME} 213 | sed -i "s|\$EXECUTABLE|${EXECUTABLE}|" preprocess_${JOBNAME} 214 | sed -i "s|\$WORKLOADS|${WORKLOADSSTR}|" preprocess_${JOBNAME} 215 | sed -i "s|\$DATADIR|${DATADIR}|" preprocess_${JOBNAME} 216 | 217 | 218 | -------------------------------------------------------------------------------- /HumongousLock/src/hdb/stats/ClientStats.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ClientStats.cpp 3 | * 4 | * Created on: Apr 22, 2018 5 | * Author: claudeb 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace hdb { 13 | namespace stats { 14 | 15 | ClientStats::ClientStats() { 16 | 17 | this->globalRank = 0; 18 | this->accumulatedDataAccessTime = 0; 19 | this->accumulatedLockingTime = 0; 20 | this->totalLocksRequests = 0; 21 | this->totalRemoteLocks = 0; 22 | this->totalLocalLocks = 0; 23 | this->totalDeniedLocks = 0; 24 | this->totalGrantedLocks = 0; 25 | #ifdef USE_LOGGING 26 | this->lockRequestTotalTimeAccumulated = 0; 27 | this->lockRequestNetworkTimeAccumulated = 0; 28 | this->lockRequestServerProcessingTimeAccumulated = 0; 29 | this->lockRequestQueueingTimeAccumulated = 0; 30 | #endif 31 | this->accumulatedVotingTime = 0; 32 | this->totalVotes = 0; 33 | this->totalVotesYes = 0; 34 | this->totalVotesNo = 0; 35 | this->accumulatedEndingTime = 0; 36 | this->totalTransactions = 0; 37 | this->totalTransactionsCommitted = 0; 38 | this->totalTransactionsAborted = 0; 39 | this->totalNewOrderTransactions = 0; 40 | this->totalNewOrderTransactionsCommitted = 0; 41 | this->totalServersInvolved = 0; 42 | this->executionTime = 0; 43 | for (uint32_t i = 0; i < hdb::locktable::LockMode::MODE_COUNT; ++i) { 44 | this->totalRequestedLocksByType[i] = 0; 45 | } 46 | 47 | } 48 | 49 | ClientStats::~ClientStats() { 50 | 51 | } 52 | 53 | void ClientStats::sendDataToRoot() { 54 | MPI_Send(this, sizeof(ClientStats), MPI_BYTE, 0, CLIENT_STAT_TAG, MPI_COMM_WORLD); 55 | } 56 | 57 | void ClientStats::dumpToFile(FILE* output) { 58 | 59 | fprintf(output, "####\n"); 60 | fprintf(output, "ClientGlobalRank\t%d\n", globalRank); 61 | fprintf(output, "ClientDataAccessTimeAccumulated\t%lu\n", accumulatedDataAccessTime); 62 | fprintf(output, "ClientLockingTimeAccumulated\t%lu\n", accumulatedLockingTime); 63 | fprintf(output, "ClientLocksNL\t%lu\n", totalRequestedLocksByType[0]); 64 | fprintf(output, "ClientLocksIS\t%lu\n", totalRequestedLocksByType[1]); 65 | fprintf(output, "ClientLocksIX\t%lu\n", totalRequestedLocksByType[2]); 66 | fprintf(output, "ClientLocksS\t%lu\n", totalRequestedLocksByType[3]); 67 | fprintf(output, "ClientLocksSIX\t%lu\n", totalRequestedLocksByType[4]); 68 | fprintf(output, "ClientLocksX\t%lu\n", totalRequestedLocksByType[5]); 69 | fprintf(output, "ClientTotalLocks\t%lu\n", totalLocksRequests); 70 | fprintf(output, "ClientRemoteLocks\t%lu\n", totalRemoteLocks); 71 | fprintf(output, "ClientLocalLocks\t%lu\n", totalLocalLocks); 72 | fprintf(output, "ClientDeniedLocks\t%lu\n", totalDeniedLocks); 73 | fprintf(output, "ClientGrantedLocks\t%lu\n", totalGrantedLocks); 74 | #ifdef USE_LOGGING 75 | fprintf(output, "ClientLockRequestTotalTime\t%lu\n", lockRequestTotalTimeAccumulated); 76 | fprintf(output, "ClientLockRequestNetworkTime\t%lu\n", lockRequestNetworkTimeAccumulated); 77 | fprintf(output, "ClientLockRequestQueueingTime\t%lu\n", lockRequestQueueingTimeAccumulated); 78 | fprintf(output, "ClientLockRequestServerTime\t%lu\n", lockRequestServerProcessingTimeAccumulated); 79 | #endif 80 | fprintf(output, "ClientVotingTimeAccumulated\t%lu\n", accumulatedVotingTime); 81 | fprintf(output, "ClientTotalVotes\t%lu\n", totalVotes); 82 | fprintf(output, "ClientVotesYes\t%lu\n", totalVotesYes); 83 | fprintf(output, "ClientVotesNo\t%lu\n", totalVotesNo); 84 | fprintf(output, "ClientEndingTimeAccumulated\t%lu\n", accumulatedEndingTime); 85 | fprintf(output, "ClientTotalTransactions\t%lu\n", totalTransactions); 86 | fprintf(output, "ClientTransactionsCommitted\t%lu\n", totalTransactionsCommitted); 87 | fprintf(output, "ClientTransactionsAborted\t%lu\n", totalTransactionsAborted); 88 | fprintf(output, "ClientNewOrderTransactions\t%lu\n", totalNewOrderTransactions); 89 | fprintf(output, "ClientNewOrderTransactionsCommitted\t%lu\n", totalNewOrderTransactionsCommitted); 90 | fprintf(output, "ClientServersContacted\t%lu\n", totalServersInvolved); 91 | fprintf(output, "ClientExecutionTime\t%lu\n", executionTime); 92 | 93 | } 94 | 95 | void ClientStats::startDataAccess() { 96 | gettimeofday(&(start), NULL); 97 | } 98 | 99 | void ClientStats::stopDataAccess() { 100 | struct timeval stop; 101 | gettimeofday(&(stop), NULL); 102 | this->accumulatedDataAccessTime += (stop.tv_sec * 1000000L + stop.tv_usec) - (start.tv_sec * 1000000L + start.tv_usec); 103 | } 104 | 105 | void ClientStats::startLocking() { 106 | gettimeofday(&(start), NULL); 107 | } 108 | 109 | void ClientStats::stopLocking() { 110 | struct timeval stop; 111 | gettimeofday(&(stop), NULL); 112 | this->accumulatedLockingTime += (stop.tv_sec * 1000000L + stop.tv_usec) - (start.tv_sec * 1000000L + start.tv_usec); 113 | 114 | } 115 | 116 | void ClientStats::issuedLockRequest(hdb::messages::LockRequest* request, bool remoteServer) { 117 | ++totalLocksRequests; 118 | ++(totalRequestedLocksByType[(uint32_t) (request->mode)]); 119 | if (remoteServer) { 120 | ++totalRemoteLocks; 121 | } else { 122 | ++totalLocalLocks; 123 | } 124 | } 125 | 126 | void ClientStats::receivedLockAnswer(hdb::messages::LockGrant* grant) { 127 | if (grant->granted) { 128 | ++totalGrantedLocks; 129 | } else { 130 | ++totalDeniedLocks; 131 | } 132 | #ifdef USE_LOGGING 133 | lockRequestTotalTimeAccumulated += grant->clientReceiveTime - grant->clientSendTime; 134 | lockRequestNetworkTimeAccumulated += (grant->clientReceiveTime - grant->clientSendTime) - (grant->serverSendTime - grant->serverReceiveTime); 135 | lockRequestQueueingTimeAccumulated += grant->serverDequeueTime - grant->serverEnqueueTime; 136 | lockRequestServerProcessingTimeAccumulated += (grant->serverEnqueueTime - grant->serverReceiveTime) + (grant->serverSendTime - grant->serverDequeueTime); 137 | #endif 138 | } 139 | 140 | void ClientStats::startVote() { 141 | gettimeofday(&(start), NULL); 142 | } 143 | 144 | void ClientStats::stopVote(bool outcome) { 145 | struct timeval stop; 146 | gettimeofday(&(stop), NULL); 147 | this->accumulatedVotingTime += (stop.tv_sec * 1000000L + stop.tv_usec) - (start.tv_sec * 1000000L + start.tv_usec); 148 | ++totalVotes; 149 | if (outcome) { 150 | ++totalVotesYes; 151 | } else { 152 | ++totalVotesNo; 153 | } 154 | } 155 | 156 | void ClientStats::startTransactionEnd(bool isNewOrder, uint64_t numberOfInvolvedServers) { 157 | gettimeofday(&(start), NULL); 158 | ++totalTransactions; 159 | if (isNewOrder) 160 | ++totalNewOrderTransactions; 161 | totalServersInvolved += numberOfInvolvedServers; 162 | } 163 | 164 | void ClientStats::stopTransactionEnd(bool outcome, bool isNewOrder) { 165 | struct timeval stop; 166 | gettimeofday(&(stop), NULL); 167 | this->accumulatedEndingTime += (stop.tv_sec * 1000000L + stop.tv_usec) - (start.tv_sec * 1000000L + start.tv_usec); 168 | if (outcome) { 169 | ++totalTransactionsCommitted; 170 | } else { 171 | ++totalTransactionsAborted; 172 | } 173 | if(isNewOrder && outcome){ 174 | ++totalNewOrderTransactionsCommitted; 175 | } 176 | } 177 | 178 | void ClientStats::startExecution() { 179 | gettimeofday(&(executionStart), NULL); 180 | } 181 | 182 | void ClientStats::stopExecution() { 183 | struct timeval stop; 184 | gettimeofday(&(stop), NULL); 185 | this->executionTime = (stop.tv_sec * 1000000L + stop.tv_usec) - (executionStart.tv_sec * 1000000L + executionStart.tv_usec); 186 | } 187 | 188 | } /* namespace stats */ 189 | } /* namespace hdb */ 190 | 191 | 192 | --------------------------------------------------------------------------------