Preliminary benchmark program uploads for SEDA-style response time percentiles vs requests / second
Also added a few cute little utilities: - truncate_log - run_recovery Upped max # of concurrent transactions. (Current throughput during benchmarking remains ~flat up to 32,000 threads, but past max concurrent transactions was 1,000...)
This commit is contained in:
parent
18c772234d
commit
1bfb634103
20 changed files with 1436 additions and 76 deletions
|
@ -1,19 +1,19 @@
|
|||
./logicalMultThreaded 200 500
|
||||
./logicalMultThreaded 200 750
|
||||
./logicalMultThreaded 200 1000
|
||||
./logicalMultThreaded 200 1250
|
||||
./logicalMultThreaded 200 1500
|
||||
./logicalMultThreaded 200 1750
|
||||
./logicalMultThreaded 200 2000
|
||||
./logicalMultThreaded 200 2250
|
||||
./logicalMultThreaded 200 2500
|
||||
./logicalMultThreaded 200 2750
|
||||
./logicalMultThreaded 200 3000
|
||||
./logicalMultThreaded 200 3250
|
||||
./logicalMultThreaded 200 3500
|
||||
./logicalMultThreaded 200 3750
|
||||
./logicalMultThreaded 200 4000
|
||||
./logicalMultThreaded 200 4250
|
||||
./logicalMultThreaded 200 4500
|
||||
./logicalMultThreaded 200 4750
|
||||
./logicalMultThreaded 200 5000
|
||||
./linearHashNTAThreaded 50 2000
|
||||
./linearHashNTAThreaded 50 3000
|
||||
./linearHashNTAThreaded 50 4000
|
||||
./linearHashNTAThreaded 50 5000
|
||||
./linearHashNTAThreaded 50 6000
|
||||
./linearHashNTAThreaded 50 7000
|
||||
./linearHashNTAThreaded 50 8000
|
||||
./linearHashNTAThreaded 50 9000
|
||||
./linearHashNTAThreaded 50 10000
|
||||
./linearHashNTAThreaded 50 11000
|
||||
./linearHashNTAThreaded 50 12000
|
||||
./linearHashNTAThreaded 50 13000
|
||||
./linearHashNTAThreaded 50 14000
|
||||
./linearHashNTAThreaded 50 15000
|
||||
./linearHashNTAThreaded 50 16000
|
||||
./linearHashNTAThreaded 50 17000
|
||||
./linearHashNTAThreaded 50 18000
|
||||
./linearHashNTAThreaded 50 19000
|
||||
./linearHashNTAThreaded 50 20000
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
./logicalMultThreaded 1 500000
|
||||
./logicalMultThreaded 2 250000
|
||||
./logicalMultThreaded 3 166666.666666667
|
||||
./logicalMultThreaded 4 125000
|
||||
./logicalMultThreaded 5 100000
|
||||
./logicalMultThreaded 6 83333.3333333333
|
||||
./logicalMultThreaded 7 71428.5714285714
|
||||
./logicalMultThreaded 8 62500
|
||||
./logicalMultThreaded 9 55555.5555555556
|
||||
./logicalMultThreaded 10 50000
|
||||
./logicalMultThreaded 20 25000
|
||||
./logicalMultThreaded 30 16666.6666666667
|
||||
./logicalMultThreaded 40 12500
|
||||
./logicalMultThreaded 50 10000
|
||||
./logicalMultThreaded 60 8333.33333333333
|
||||
./logicalMultThreaded 70 7142.85714285714
|
||||
./logicalMultThreaded 80 6250
|
||||
./logicalMultThreaded 90 5555.55555555556
|
||||
./logicalMultThreaded 100 5000
|
||||
./logicalMultThreaded 110 4545.45454545455
|
||||
./logicalMultThreaded 120 4166.66666666667
|
||||
./logicalMultThreaded 130 3846.15384615385
|
||||
./logicalMultThreaded 140 3571.42857142857
|
||||
./logicalMultThreaded 150 3333.33333333333
|
||||
./logicalMultThreaded 160 3125
|
||||
./logicalMultThreaded 170 2941.17647058824
|
||||
./logicalMultThreaded 180 2777.77777777778
|
||||
./logicalMultThreaded 190 2631.57894736842
|
||||
./logicalMultThreaded 200 2500
|
||||
./logicalMultThreaded 210 2380.95238095238
|
||||
./logicalMultThreaded 220 2272.72727272727
|
||||
./logicalMultThreaded 230 2173.91304347826
|
||||
./logicalMultThreaded 240 2083.33333333333
|
||||
./logicalMultThreaded 250 2000
|
||||
./linearHashNTAMultiReader 1 50000
|
||||
./linearHashNTAMultiReader 2 25000
|
||||
./linearHashNTAMultiReader 3 16666.6666666667
|
||||
./linearHashNTAMultiReader 4 12500
|
||||
./linearHashNTAMultiReader 5 10000
|
||||
./linearHashNTAMultiReader 6 8333.33333333333
|
||||
./linearHashNTAMultiReader 7 7142.85714285714
|
||||
./linearHashNTAMultiReader 8 6250
|
||||
./linearHashNTAMultiReader 9 5555.55555555556
|
||||
./linearHashNTAMultiReader 10 5000
|
||||
./linearHashNTAMultiReader 20 2500
|
||||
./linearHashNTAMultiReader 30 1666.66666666667
|
||||
./linearHashNTAMultiReader 40 1250
|
||||
./linearHashNTAMultiReader 50 1000
|
||||
./linearHashNTAMultiReader 60 833.333333333333
|
||||
./linearHashNTAMultiReader 70 714.285714285714
|
||||
./linearHashNTAMultiReader 80 625
|
||||
./linearHashNTAMultiReader 90 555.555555555556
|
||||
./linearHashNTAMultiReader 100 500
|
||||
./linearHashNTAMultiReader 110 454.545454545455
|
||||
./linearHashNTAMultiReader 120 416.666666666667
|
||||
./linearHashNTAMultiReader 130 384.615384615385
|
||||
./linearHashNTAMultiReader 140 357.142857142857
|
||||
./linearHashNTAMultiReader 150 333.333333333333
|
||||
./linearHashNTAMultiReader 160 312.5
|
||||
./linearHashNTAMultiReader 170 294.117647058824
|
||||
./linearHashNTAMultiReader 180 277.777777777778
|
||||
./linearHashNTAMultiReader 190 263.157894736842
|
||||
./linearHashNTAMultiReader 200 250
|
||||
./linearHashNTAMultiReader 210 238.095238095238
|
||||
./linearHashNTAMultiReader 220 227.272727272727
|
||||
./linearHashNTAMultiReader 230 217.391304347826
|
||||
./linearHashNTAMultiReader 240 208.333333333333
|
||||
./linearHashNTAMultiReader 250 200
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
LDADD=$(top_builddir)/src/2pc/lib2pc.a $(top_builddir)/src/libdfa/libdfa.a \
|
||||
$(top_builddir)/src/lladd/liblladd.a $(top_builddir)/src/pbl/libpbl.a \
|
||||
$(top_builddir)/src/libdfa/librw.a
|
||||
bin_PROGRAMS=naiveHash logicalHash readLogicalHash naiveMultiThreaded logicalMultThreaded rawSet arrayListSet logicalMultiReaders linearHashNTA linkedListNTA
|
||||
bin_PROGRAMS=naiveHash logicalHash readLogicalHash naiveMultiThreaded logicalMultThreaded rawSet \
|
||||
arrayListSet logicalMultiReaders linearHashNTA linkedListNTA pageOrientedListNTA \
|
||||
linearHashNTAThreaded linearHashNTAMultiReader linearHashNTAWriteRequests
|
||||
AM_CFLAGS= -g -Wall -pedantic -std=gnu99
|
||||
|
||||
SUBDIRS=berkeleyDB
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
LDADD=-ldb -lpthread
|
||||
bin_PROGRAMS=transapp bdbRaw bdbHash
|
||||
bin_PROGRAMS=transapp bdbRaw bdbHash bdbHashThreaded
|
||||
AM_CFLAGS=-g
|
||||
|
|
681
benchmarks/berkeleyDB/bdbHashThreaded.c
Normal file
681
benchmarks/berkeleyDB/bdbHashThreaded.c
Normal file
|
@ -0,0 +1,681 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
// if we're using linux's crazy version of the pthread header,
|
||||
// it probably forgot to include PTHREAD_STACK_MIN
|
||||
|
||||
#ifndef PTHREAD_STACK_MIN
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <db.h>
|
||||
|
||||
#define ENV_DIRECTORY "TXNAPP"
|
||||
|
||||
int activeThreads = 0;
|
||||
int max_active = 0;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
|
||||
void add_cat(DB_ENV *, DB *, char *, ...);
|
||||
void run_xact(DB_ENV *, DB *, int, int);
|
||||
/*void add_color(DB_ENV *, DB *, char *, int);
|
||||
void add_fruit(DB_ENV *, DB *, char *, char *); */
|
||||
void *checkpoint_thread(void *);
|
||||
void log_archlist(DB_ENV *);
|
||||
void *logfile_thread(void *);
|
||||
void db_open(DB_ENV *, DB **, char *, int);
|
||||
void env_dir_create(void);
|
||||
void env_open(DB_ENV **);
|
||||
void usage(void);
|
||||
|
||||
DB_ENV *dbenv;
|
||||
DB *db_cats; /*, *db_color, *db_fruit; */
|
||||
|
||||
int num_xact;
|
||||
int insert_per_xact;
|
||||
void * runThread(void * arg);
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
extern int optind;
|
||||
|
||||
pthread_t ptid;
|
||||
int ch, ret;
|
||||
|
||||
/* while ((ch = getopt(argc, argv, "")) != EOF)
|
||||
switch (ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind; */
|
||||
|
||||
assert(argc == 3);
|
||||
/* threads have static thread sizes. Ughh. */
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
|
||||
pthread_attr_setstacksize (&attr, 4 * PTHREAD_STACK_MIN);
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
|
||||
|
||||
env_dir_create();
|
||||
env_open(&dbenv);
|
||||
|
||||
/* Start a checkpoint thread. */
|
||||
if ((ret = pthread_create(
|
||||
&ptid, &attr, checkpoint_thread, (void *)dbenv)) != 0) {
|
||||
fprintf(stderr,
|
||||
"txnapp: failed spawning checkpoint thread: %s\n",
|
||||
strerror(ret));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Start a logfile removal thread. */
|
||||
if ((ret = pthread_create(
|
||||
&ptid, &attr, logfile_thread, (void *)dbenv)) != 0) {
|
||||
fprintf(stderr,
|
||||
"txnapp: failed spawning log file removal thread: %s\n",
|
||||
strerror(ret));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Open database: Key is fruit class; Data is specific type. */
|
||||
/* db_open(dbenv, &db_fruit, "fruit", 0); */
|
||||
|
||||
/* Open database: Key is a color; Data is an integer. */
|
||||
/*db_open(dbenv, &db_color, "color", 0); */
|
||||
|
||||
/*
|
||||
* Open database:
|
||||
* Key is a name; Data is: company name, address, cat breeds.
|
||||
*/
|
||||
db_open(dbenv, &db_cats, "cats", 1);
|
||||
|
||||
/* add_fruit(dbenv, db_fruit, "apple", "yellow delicious");
|
||||
|
||||
add_color(dbenv, db_color, "blue", 0);
|
||||
add_color(dbenv, db_color, "blue", 3); */
|
||||
|
||||
/* add_cat(dbenv, db_cats,
|
||||
"Amy Adams",
|
||||
"Sleepycat Software",
|
||||
"394 E. Riding Dr., Carlisle, MA 01741, USA",
|
||||
"abyssinian",
|
||||
"bengal",
|
||||
"chartreaux",
|
||||
NULL);*/
|
||||
int r;
|
||||
int num_threads = atoi(argv[1]);
|
||||
/*int */num_xact = 1; //atoi(argv[2]); //100;
|
||||
/*int */insert_per_xact = atoi(argv[2]); //1000;
|
||||
// int num_threads = 100;
|
||||
|
||||
|
||||
|
||||
pthread_t * threads = malloc(num_threads * sizeof(pthread_t));
|
||||
int i ;
|
||||
for(i = 0; i < num_threads; i++) {
|
||||
|
||||
if ((ret = pthread_create(&(threads[i]), &attr, runThread, (void *)i)) != 0){
|
||||
fprintf(stderr,
|
||||
"txnapp: failed spawning worker thread: %s\n",
|
||||
strerror(ret));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
for(r = 0; r < num_xact; r ++) {
|
||||
run_xact(dbenv, db_cats, 1+r*insert_per_xact, insert_per_xact);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
for(i = 0; i < num_threads; i++) {
|
||||
pthread_join(threads[i], NULL);
|
||||
}
|
||||
|
||||
free(threads);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
void * runThread(void * arg) {
|
||||
int offset = (int) arg;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
activeThreads++;
|
||||
if(activeThreads > max_active) {
|
||||
max_active = activeThreads;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
|
||||
int r;
|
||||
|
||||
for(r = 0; r < num_xact; r ++) {
|
||||
run_xact(dbenv, db_cats, offset*(1+r)*insert_per_xact, insert_per_xact);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
activeThreads--;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
|
||||
// printf("%d done\n", offset);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
env_dir_create()
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
/*
|
||||
* If the directory exists, we're done. We do not further check
|
||||
* the type of the file, DB will fail appropriately if it's the
|
||||
* wrong type.
|
||||
*/
|
||||
if (stat(ENV_DIRECTORY, &sb) == 0)
|
||||
return;
|
||||
|
||||
/* Create the directory, read/write/access owner only. */
|
||||
if (mkdir(ENV_DIRECTORY, S_IRWXU) != 0) {
|
||||
fprintf(stderr,
|
||||
"txnapp: mkdir: %s: %s\n", ENV_DIRECTORY, strerror(errno));
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_open(DB_ENV **dbenvp)
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
int ret;
|
||||
|
||||
/* Create the environment handle. */
|
||||
if ((ret = db_env_create(&dbenv, 0)) != 0) {
|
||||
fprintf(stderr,
|
||||
"txnapp: db_env_create: %s\n", db_strerror(ret));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Set up error handling. */
|
||||
dbenv->set_errpfx(dbenv, "txnapp");
|
||||
dbenv->set_errfile(dbenv, stderr);
|
||||
|
||||
/* Do deadlock detection internally. */
|
||||
if ((ret = dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT)) != 0) {
|
||||
dbenv->err(dbenv, ret, "set_lk_detect: DB_LOCK_DEFAULT");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a transactional environment:
|
||||
* create if it doesn't exist
|
||||
* free-threaded handle
|
||||
* run recovery
|
||||
* read/write owner only
|
||||
*/
|
||||
if ((ret = dbenv->open(dbenv, ENV_DIRECTORY,
|
||||
DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG |
|
||||
DB_INIT_MPOOL | DB_INIT_TXN | DB_RECOVER | DB_THREAD,
|
||||
S_IRUSR | S_IWUSR)) != 0) {
|
||||
dbenv->err(dbenv, ret, "dbenv->open: %s", ENV_DIRECTORY);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
*dbenvp = dbenv;
|
||||
}
|
||||
|
||||
void *
|
||||
checkpoint_thread(void *arg)
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
int ret;
|
||||
|
||||
dbenv = arg;
|
||||
dbenv->errx(dbenv, "Checkpoint thread: %lu", (u_long)pthread_self());
|
||||
|
||||
/* Checkpoint once a minute. */
|
||||
for (;; sleep(60))
|
||||
if ((ret = dbenv->txn_checkpoint(dbenv, 0, 0, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "checkpoint thread");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
void *
|
||||
logfile_thread(void *arg)
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
int ret;
|
||||
char **begin, **list;
|
||||
|
||||
dbenv = arg;
|
||||
dbenv->errx(dbenv,
|
||||
"Log file removal thread: %lu", (u_long)pthread_self());
|
||||
|
||||
/* Check once every 5 minutes. */
|
||||
for (;; sleep(300)) {
|
||||
/* Get the list of log files. */
|
||||
if ((ret =
|
||||
dbenv->log_archive(dbenv, &list, DB_ARCH_ABS)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_ENV->log_archive");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Remove the log files. */
|
||||
if (list != NULL) {
|
||||
for (begin = list; *list != NULL; ++list)
|
||||
if ((ret = remove(*list)) != 0) {
|
||||
dbenv->err(dbenv,
|
||||
ret, "remove %s", *list);
|
||||
exit (1);
|
||||
}
|
||||
free (begin);
|
||||
}
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
void
|
||||
log_archlist(DB_ENV *dbenv)
|
||||
{
|
||||
int ret;
|
||||
char **begin, **list;
|
||||
|
||||
/* Get the list of database files. */
|
||||
if ((ret = dbenv->log_archive(dbenv,
|
||||
&list, DB_ARCH_ABS | DB_ARCH_DATA)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_ENV->log_archive: DB_ARCH_DATA");
|
||||
exit (1);
|
||||
}
|
||||
if (list != NULL) {
|
||||
for (begin = list; *list != NULL; ++list)
|
||||
printf("database file: %s\n", *list);
|
||||
free (begin);
|
||||
}
|
||||
|
||||
/* Get the list of log files. */
|
||||
if ((ret = dbenv->log_archive(dbenv,
|
||||
&list, DB_ARCH_ABS | DB_ARCH_LOG)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_ENV->log_archive: DB_ARCH_LOG");
|
||||
exit (1);
|
||||
}
|
||||
if (list != NULL) {
|
||||
for (begin = list; *list != NULL; ++list)
|
||||
printf("log file: %s\n", *list);
|
||||
free (begin);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
db_open(DB_ENV *dbenv, DB **dbp, char *name, int dups)
|
||||
{
|
||||
DB *db;
|
||||
int ret;
|
||||
|
||||
/* Create the database handle. */
|
||||
if ((ret = db_create(&db, dbenv, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "db_create");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Optionally, turn on duplicate data items. */
|
||||
/* if (dups && (ret = db->set_flags(db, DB_DUP)) != 0) {
|
||||
dbenv->err(dbenv, ret, "db->set_flags: DB_DUP");
|
||||
exit (1);
|
||||
} */
|
||||
|
||||
/*
|
||||
* Open a database in the environment:
|
||||
* create if it doesn't exist
|
||||
* free-threaded handle
|
||||
* read/write owner only
|
||||
*/
|
||||
if ((ret = db->open(db, NULL, name, NULL, /*DB_BTREE*//* DB_RECNO */DB_HASH,
|
||||
DB_AUTO_COMMIT | DB_DIRTY_READ | DB_TXN_SYNC | DB_CREATE | DB_THREAD, S_IRUSR | S_IWUSR)) != 0) {
|
||||
(void)db->close(db, 0);
|
||||
dbenv->err(dbenv, ret, "db->open: %s", name);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
*dbp = db;
|
||||
}
|
||||
|
||||
void
|
||||
add_fruit(DB_ENV *dbenv, DB *db, char *fruit, char *name)
|
||||
{
|
||||
DBT key, data;
|
||||
DB_TXN *tid;
|
||||
int ret;
|
||||
|
||||
/* Initialization. */
|
||||
memset(&key, 0, sizeof(key));
|
||||
memset(&data, 0, sizeof(data));
|
||||
key.data = fruit;
|
||||
key.size = strlen(fruit);
|
||||
data.data = name;
|
||||
data.size = strlen(name);
|
||||
|
||||
for (;;) {
|
||||
/* Begin the transaction. */
|
||||
if ((ret = dbenv->txn_begin(dbenv, NULL, &tid, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_ENV->txn_begin");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Store the value. */
|
||||
switch (ret = db->put(db, tid, &key, &data, 0)) {
|
||||
case 0:
|
||||
/* Success: commit the change. */
|
||||
if ((ret = tid->commit(tid, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_TXN->commit");
|
||||
exit (1);
|
||||
}
|
||||
return;
|
||||
case DB_LOCK_DEADLOCK:
|
||||
/* Deadlock: retry the operation. */
|
||||
if ((ret = tid->abort(tid)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_TXN->abort");
|
||||
exit (1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Error: run recovery. */
|
||||
dbenv->err(dbenv, ret, "dbc->put: %s/%s", fruit, name);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
add_color(DB_ENV *dbenv, DB *dbp, char *color, int increment)
|
||||
{
|
||||
DBT key, data;
|
||||
DB_TXN *tid;
|
||||
int original, ret;
|
||||
char buf[64];
|
||||
|
||||
/* Initialization. */
|
||||
memset(&key, 0, sizeof(key));
|
||||
key.data = color;
|
||||
key.size = strlen(color);
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.flags = DB_DBT_MALLOC;
|
||||
|
||||
for (;;) {
|
||||
/* Begin the transaction. */
|
||||
if ((ret = dbenv->txn_begin(dbenv, NULL, &tid, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_ENV->txn_begin");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the key. If it exists, we increment the value. If it
|
||||
* doesn't exist, we create it.
|
||||
*/
|
||||
switch (ret = dbp->get(dbp, tid, &key, &data, 0)) {
|
||||
case 0:
|
||||
original = atoi(data.data);
|
||||
break;
|
||||
case DB_LOCK_DEADLOCK:
|
||||
/* Deadlock: retry the operation. */
|
||||
if ((ret = tid->abort(tid)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_TXN->abort");
|
||||
exit (1);
|
||||
}
|
||||
continue;
|
||||
case DB_NOTFOUND:
|
||||
original = 0;
|
||||
break;
|
||||
default:
|
||||
/* Error: run recovery. */
|
||||
dbenv->err(
|
||||
dbenv, ret, "dbc->get: %s/%d", color, increment);
|
||||
exit (1);
|
||||
}
|
||||
if (data.data != NULL)
|
||||
free(data.data);
|
||||
|
||||
/* Create the new data item. */
|
||||
(void)snprintf(buf, sizeof(buf), "%d", original + increment);
|
||||
data.data = buf;
|
||||
data.size = strlen(buf) + 1;
|
||||
|
||||
/* Store the new value. */
|
||||
switch (ret = dbp->put(dbp, tid, &key, &data, 0)) {
|
||||
case 0:
|
||||
/* Success: commit the change. */
|
||||
if ((ret = tid->commit(tid, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_TXN->commit");
|
||||
exit (1);
|
||||
}
|
||||
return;
|
||||
case DB_LOCK_DEADLOCK:
|
||||
/* Deadlock: retry the operation. */
|
||||
if ((ret = tid->abort(tid)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_TXN->abort");
|
||||
exit (1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Error: run recovery. */
|
||||
dbenv->err(
|
||||
dbenv, ret, "dbc->put: %s/%d", color, increment);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
add_cat(DB_ENV *dbenv, DB *db, char *name, ...)
|
||||
{
|
||||
va_list ap;
|
||||
DBC *dbc;
|
||||
DBT key, data;
|
||||
DB_TXN *tid;
|
||||
int ret;
|
||||
char *s;
|
||||
|
||||
/* Initialization. */
|
||||
memset(&key, 0, sizeof(key));
|
||||
memset(&data, 0, sizeof(data));
|
||||
key.data = name;
|
||||
key.size = strlen(name);
|
||||
|
||||
retry: /* Begin the transaction. */
|
||||
if ((ret = dbenv->txn_begin(dbenv, NULL, &tid, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_ENV->txn_begin");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Delete any previously existing item. */
|
||||
switch (ret = db->del(db, tid, &key, 0)) {
|
||||
case 0:
|
||||
case DB_NOTFOUND:
|
||||
break;
|
||||
case DB_LOCK_DEADLOCK:
|
||||
/* Deadlock: retry the operation. */
|
||||
if ((ret = tid->abort(tid)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_TXN->abort");
|
||||
exit (1);
|
||||
}
|
||||
goto retry;
|
||||
default:
|
||||
dbenv->err(dbenv, ret, "db->del: %s", name);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Create a cursor. */
|
||||
if ((ret = db->cursor(db, tid, &dbc, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "db->cursor");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Append the items, in order. */
|
||||
va_start(ap, name);
|
||||
while ((s = va_arg(ap, char *)) != NULL) {
|
||||
data.data = s;
|
||||
data.size = strlen(s);
|
||||
switch (ret = dbc->c_put(dbc, &key, &data, DB_KEYLAST)) {
|
||||
case 0:
|
||||
break;
|
||||
case DB_LOCK_DEADLOCK:
|
||||
va_end(ap);
|
||||
|
||||
/* Deadlock: retry the operation. */
|
||||
if ((ret = dbc->c_close(dbc)) != 0) {
|
||||
dbenv->err(
|
||||
dbenv, ret, "dbc->c_close");
|
||||
exit (1);
|
||||
}
|
||||
if ((ret = tid->abort(tid)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_TXN->abort");
|
||||
exit (1);
|
||||
}
|
||||
goto retry;
|
||||
default:
|
||||
/* Error: run recovery. */
|
||||
dbenv->err(dbenv, ret, "dbc->put: %s/%s", name, s);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
/* Success: commit the change. */
|
||||
if ((ret = dbc->c_close(dbc)) != 0) {
|
||||
dbenv->err(dbenv, ret, "dbc->c_close");
|
||||
exit (1);
|
||||
}
|
||||
if ((ret = tid->commit(tid, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_TXN->commit");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run_xact(DB_ENV *dbenv, DB *db, int offset, int count)
|
||||
{
|
||||
va_list ap;
|
||||
DBC *dbc;
|
||||
DBT key, data;
|
||||
DB_TXN *tid;
|
||||
int ret;
|
||||
char *s;
|
||||
|
||||
/* Initialization. */
|
||||
memset(&key, 0, sizeof(key));
|
||||
memset(&data, 0, sizeof(data));
|
||||
int keyPtr;
|
||||
int valPtr;
|
||||
key.data = &keyPtr;
|
||||
key.size = sizeof(int);/*strlen(name);*/
|
||||
data.data = &valPtr;
|
||||
data.size = sizeof(int);
|
||||
|
||||
retry: /* Begin the transaction. */
|
||||
if ((ret = dbenv->txn_begin(dbenv, NULL, &tid, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_ENV->txn_begin");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Delete any previously existing item. */
|
||||
/* switch (ret = db->del(db, tid, &key, 0)) {
|
||||
case 0:
|
||||
case DB_NOTFOUND:
|
||||
break;
|
||||
case DB_LOCK_DEADLOCK:
|
||||
/ * Deadlock: retry the operation. * /
|
||||
if ((ret = tid->abort(tid)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_TXN->abort");
|
||||
exit (1);
|
||||
}
|
||||
goto retry;
|
||||
default:
|
||||
dbenv->err(dbenv, ret, "db->del: %s", name);
|
||||
exit (1);
|
||||
} */
|
||||
|
||||
/* Create a cursor. */
|
||||
if ((ret = db->cursor(db, tid, &dbc, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "db->cursor");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Append the items, in order. */
|
||||
// va_start(ap, name);
|
||||
// while ((s = va_arg(ap, char *)) != NULL) {
|
||||
int q;
|
||||
for(q = offset; q < offset + count; q++) {
|
||||
keyPtr = q;
|
||||
valPtr = q;
|
||||
/* data.data = s;
|
||||
data.size = strlen(s); */
|
||||
// printf("A"); fflush(NULL);
|
||||
switch (ret = dbc->c_put(dbc, &key, &data, DB_KEYLAST)) {
|
||||
case 0:
|
||||
// printf("B"); fflush(NULL);
|
||||
break;
|
||||
case DB_LOCK_DEADLOCK:
|
||||
va_end(ap);
|
||||
|
||||
/* Deadlock: retry the operation. */
|
||||
if ((ret = dbc->c_close(dbc)) != 0) {
|
||||
dbenv->err(
|
||||
dbenv, ret, "dbc->c_close");
|
||||
exit (1);
|
||||
}
|
||||
if ((ret = tid->abort(tid)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_TXN->abort");
|
||||
exit (1);
|
||||
}
|
||||
goto retry;
|
||||
default:
|
||||
/* Error: run recovery. */
|
||||
dbenv->err(dbenv, ret, "dbc->put: %d/%d", q, q);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
/* Success: commit the change. */
|
||||
if ((ret = dbc->c_close(dbc)) != 0) {
|
||||
dbenv->err(dbenv, ret, "dbc->c_close");
|
||||
exit (1);
|
||||
}
|
||||
if ((ret = tid->commit(tid, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_TXN->commit");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: txnapp\n");
|
||||
exit(1);
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use strict;
|
||||
|
||||
my $num_threads = 50;
|
||||
|
||||
## This perl script generates the input to timer.pl, which in turn
|
||||
## generates the input to plotting.pl, which generates performance
|
||||
|
@ -14,26 +15,46 @@ open(LLADD_RAW_PHYSICAL, ">LLADD_RAW_PHYSICAL.script");
|
|||
open(BDB_RAW_INSERT, ">BDB_RAW_INSERT.script" );
|
||||
open(BDB_HASH_INSERT, ">BDB_HASH_INSERT.script" );
|
||||
|
||||
# New tests
|
||||
|
||||
open(LLADD_NTA, ">LLADD_NTA.script");
|
||||
open(LLADD_LINKED_LIST, ">LLADD_LINKED_LIST.script");
|
||||
open(LLADD_PAGED_LIST, ">LLADD_PAGED_LIST.script");
|
||||
open(BDB_HASH_THREADED, ">BDB_HASH_THREADED.script");
|
||||
|
||||
open(EVERYTHING, ">EVERYTHING.script" );
|
||||
|
||||
for(my $i = 1; $i <= 10; $i += .5) {
|
||||
my $insert_count = $i * 100000;
|
||||
|
||||
my $threaded_insert_count = $insert_count / 200;
|
||||
my $threaded_insert_count = $insert_count / $num_threads;
|
||||
|
||||
print LLADD_THREADED "./logicalMultThreaded 200 $threaded_insert_count\n";
|
||||
print LLADD_THREADED "./linearHashNTAThreaded $num_threads $threaded_insert_count\n";
|
||||
print LLADD_LOGICAL "./logicalHash 1 $insert_count\n";
|
||||
print LLADD_PHYSICAL "./naiveHash 1 $insert_count\n";
|
||||
print LLADD_RAW_PHYSICAL "./arrayListSet 1 $insert_count\n";
|
||||
print BDB_RAW_INSERT "./berkeleyDB/bdbRaw 1 $insert_count\n";
|
||||
print BDB_HASH_INSERT "./berkeleyDB/bdbHash 1 $insert_count\n";
|
||||
|
||||
print EVERYTHING "./logicalMultThreaded 200 $threaded_insert_count\n";
|
||||
print LLADD_NTA "./linearHashNTA 1 $insert_count\n";
|
||||
print LLADD_LINKED_LIST "./linkedListNTA 1 $insert_count\n";
|
||||
print LLADD_PAGED_LIST "./pageOrientedListNTA 1 $insert_count\n";
|
||||
|
||||
print BDB_HASH_THREADED "./berkeleyDB/bdbHashThreaded $num_threads $threaded_insert_count\n";
|
||||
|
||||
|
||||
print EVERYTHING "./linearHashNTAThreaded $num_threads $threaded_insert_count\n";
|
||||
print EVERYTHING "./logicalHash 1 $insert_count\n";
|
||||
print EVERYTHING "./naiveHash 1 $insert_count\n";
|
||||
print EVERYTHING "./arrayListSet 1 $insert_count\n";
|
||||
print EVERYTHING "./berkeleyDB/bdbRaw 1 $insert_count\n";
|
||||
|
||||
print EVERYTHING "./linearHashNTA 1 $insert_count\n";
|
||||
print EVERYTHING "./linkedListNTA 1 $insert_count\n";
|
||||
print EVERYTHING "./pageOrientedListNTA 1 $insert_count\n";
|
||||
|
||||
if($i < 4) {
|
||||
print EVERYTHING "./berkeleyDB/bdbHashThreaded $num_threads $threaded_insert_count\n";
|
||||
print EVERYTHING "./berkeleyDB/bdbHash 1 $insert_count\n";
|
||||
}
|
||||
|
||||
|
@ -46,3 +67,7 @@ close(LLADD_RAW_PHYSICAL);
|
|||
close(BDB_RAW_INSERT);
|
||||
close(BDB_HASH_INSERT);
|
||||
close(EVERYTHING);
|
||||
close(LLADD_NTA);
|
||||
close(LLADD_LINKED_LIST);
|
||||
close(LLADD_PAGED_LIST);
|
||||
close(BDB_HASH_THREADED);
|
||||
|
|
|
@ -10,26 +10,28 @@ use strict;
|
|||
open(LOGICAL_THREADS, ">LOGICAL_THREADS.script" );
|
||||
|
||||
for(my $i = 1; $i < 10; $i ++) {
|
||||
my $total = 500000;
|
||||
# my $total = 500000;
|
||||
my $total = 50000;
|
||||
|
||||
my $thread_count = $i;
|
||||
|
||||
my $insert_count = $total / $i;
|
||||
|
||||
print LOGICAL_THREADS "./logicalMultThreaded $thread_count $insert_count\n";
|
||||
# print LOGICAL_THREADS "./logicalMultThreaded $thread_count $insert_count\n";
|
||||
print LOGICAL_THREADS "./linearHashNTAMultiReader $thread_count $insert_count\n";
|
||||
|
||||
}
|
||||
|
||||
|
||||
for(my $i = 10; $i <= 254; $i += 10) {
|
||||
my $total = 500000;
|
||||
|
||||
# my $total = 500000;
|
||||
my $total = 50000;
|
||||
my $thread_count = $i;
|
||||
|
||||
my $insert_count = $total / $i;
|
||||
|
||||
print LOGICAL_THREADS "./logicalMultThreaded $thread_count $insert_count\n";
|
||||
|
||||
# print LOGICAL_THREADS "./logicalMultThreaded $thread_count $insert_count\n";
|
||||
print LOGICAL_THREADS "./linearHashNTAMultiReader $thread_count $insert_count\n";
|
||||
}
|
||||
|
||||
close(LOGICAL_THREADS);
|
||||
|
|
|
@ -22,6 +22,7 @@ int main(int argc, char** argv) {
|
|||
int xid = Tbegin();
|
||||
|
||||
recordid hash = ThashCreate(xid, sizeof(int), sizeof(int));
|
||||
//recordid hash = ThashCreate(xid, VARIABLE_LENGTH, VARIABLE_LENGTH);
|
||||
|
||||
Tcommit(xid);
|
||||
|
||||
|
|
127
benchmarks/linearHashNTAMultiReader.c
Normal file
127
benchmarks/linearHashNTAMultiReader.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <lladd/transactional.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
// if we're using linux's crazy version of the pthread header,
|
||||
// it probably forgot to include PTHREAD_STACK_MIN
|
||||
|
||||
#ifndef PTHREAD_STACK_MIN
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
|
||||
int i = 0;
|
||||
int max_active = 0;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
//static pthread_mutex_t hash_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int count;
|
||||
static recordid hash;
|
||||
|
||||
static void * go (void * arg_ptr) {
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
i++;
|
||||
if(i > max_active) {
|
||||
max_active = i;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
// pthread_mutex_lock(&hash_mutex);
|
||||
|
||||
int k = *(int*)arg_ptr;
|
||||
int j;
|
||||
int xid = Tbegin();
|
||||
|
||||
unsigned int seed = k;
|
||||
|
||||
for(j = 0; j < count ; j++) {
|
||||
unsigned int r = rand_r(&seed) % 10000;
|
||||
int * tmp = NULL;
|
||||
ThashLookup(xid, hash, (byte*)&r, sizeof(int), (byte**)&tmp);
|
||||
assert(r == *tmp);
|
||||
}
|
||||
// for(j = k * count; j < (k+1) *(count) ; j++) {
|
||||
// TlogicalHashInsert(xid, hash, &j, sizeof(int), &j, sizeof(int));
|
||||
// printf("(%d)", k);
|
||||
//}
|
||||
|
||||
Tcommit(xid);
|
||||
/*
|
||||
for(j = k * count; j < (k+1) *(count) ; j++) {
|
||||
int tmp = -100;
|
||||
TlogicalHashLookup(xid, hash, &j, sizeof(int), &tmp, sizeof(int));
|
||||
assert(j == tmp);
|
||||
} */
|
||||
|
||||
|
||||
// pthread_mutex_unlock(&hash_mutex);
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
i--;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
assert(argc == 3);
|
||||
|
||||
int thread_count = atoi(argv[1]);
|
||||
count = atoi(argv[2]);
|
||||
|
||||
/* unlink("storefile.txt");
|
||||
unlink("logfile.txt");
|
||||
unlink("blob0_file.txt");
|
||||
unlink("blob1_file.txt");*/
|
||||
|
||||
pthread_t * workers = malloc(sizeof(pthread_t) * thread_count);
|
||||
|
||||
Tinit();
|
||||
int xid = Tbegin();
|
||||
hash = ThashCreate(xid, sizeof(int), sizeof(int));
|
||||
|
||||
int k;
|
||||
|
||||
for(k = 0; k < 20000; k++) {
|
||||
ThashInsert(xid, hash, (byte*)&k, sizeof(int), (byte*)&k, sizeof(int));
|
||||
}
|
||||
|
||||
Tcommit(xid);
|
||||
|
||||
/* threads have static thread sizes. Ughh. */
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
|
||||
pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
for(k = 0; k < thread_count; k++) {
|
||||
int * k_copy = malloc(sizeof(int));
|
||||
*k_copy = k ;
|
||||
pthread_create(&workers[k], &attr, go, k_copy);
|
||||
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
|
||||
for(k = 0; k < thread_count; k++) {
|
||||
pthread_join(workers[k],NULL);
|
||||
}
|
||||
|
||||
Tdeinit();
|
||||
|
||||
printf("Max active at once: %d\n", max_active);
|
||||
|
||||
}
|
159
benchmarks/linearHashNTAThreaded.c
Normal file
159
benchmarks/linearHashNTAThreaded.c
Normal file
|
@ -0,0 +1,159 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <lladd/transactional.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
|
||||
// if we're using linux's crazy version of the pthread header,
|
||||
// it probably forgot to include PTHREAD_STACK_MIN
|
||||
|
||||
#ifndef PTHREAD_STACK_MIN
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
int activeThreads = 0;
|
||||
int max_active = 0;
|
||||
|
||||
double avg_var = 0;
|
||||
double max_var = 0;
|
||||
double avg_mean = 0;
|
||||
double max_mean = 0;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
//static pthread_mutex_t hash_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int count;
|
||||
static recordid hash;
|
||||
|
||||
static void * go (void * arg_ptr) {
|
||||
// pthread_mutex_lock(&hash_mutex);
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
activeThreads++;
|
||||
if(activeThreads > max_active) {
|
||||
max_active = activeThreads;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
int k = *(int*)arg_ptr;
|
||||
int j;
|
||||
int xid = Tbegin();
|
||||
|
||||
double sum_x_squared = 0;
|
||||
double sum = 0;
|
||||
|
||||
for(j = k * count; j < (k+1) *(count) ; j++) {
|
||||
|
||||
struct timeval start, endtime;
|
||||
|
||||
gettimeofday(&start, NULL);
|
||||
|
||||
ThashInsert(xid, hash, (byte*)&j, sizeof(int), (byte*)&j, sizeof(int));
|
||||
|
||||
gettimeofday(&endtime, NULL);
|
||||
|
||||
double microSecondsPassed = 1000000 * (endtime.tv_sec - start.tv_sec);
|
||||
|
||||
microSecondsPassed = (microSecondsPassed + endtime.tv_usec) - start.tv_usec;
|
||||
|
||||
sum += microSecondsPassed;
|
||||
sum_x_squared += (microSecondsPassed * microSecondsPassed) ;
|
||||
|
||||
|
||||
// printf("(%d)", k);
|
||||
}
|
||||
|
||||
|
||||
Tcommit(xid);
|
||||
/*
|
||||
for(j = k * count; j < (k+1) *(count) ; j++) {
|
||||
int tmp = -100;
|
||||
TlogicalHashLookup(xid, hash, &j, sizeof(int), &tmp, sizeof(int));
|
||||
assert(j == tmp);
|
||||
} */
|
||||
|
||||
double count_d = count;
|
||||
double mean = sum / count_d;
|
||||
double variance = sqrt((sum_x_squared / count_d) - (mean * mean));
|
||||
|
||||
|
||||
|
||||
// pthread_mutex_unlock(&hash_mutex);
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
activeThreads--;
|
||||
|
||||
avg_mean += mean;
|
||||
avg_var += variance;
|
||||
|
||||
if(mean > max_mean ) { max_mean = mean; }
|
||||
if(variance > max_var) { max_var = variance; }
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
assert(argc == 3);
|
||||
|
||||
int thread_count = atoi(argv[1]);
|
||||
count = atoi(argv[2]);
|
||||
|
||||
unlink("storefile.txt");
|
||||
unlink("logfile.txt");
|
||||
unlink("blob0_file.txt");
|
||||
unlink("blob1_file.txt");
|
||||
|
||||
pthread_t * workers = malloc(sizeof(pthread_t) * thread_count);
|
||||
|
||||
Tinit();
|
||||
int xid = Tbegin();
|
||||
hash = ThashCreate(xid, sizeof(int), sizeof(int));
|
||||
|
||||
Tcommit(xid);
|
||||
|
||||
int k;
|
||||
|
||||
/* threads have static thread sizes. Ughh. */
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
|
||||
pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
|
||||
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
|
||||
for(k = 0; k < thread_count; k++) {
|
||||
int * k_copy = malloc(sizeof(int));
|
||||
*k_copy = k ;
|
||||
pthread_create(&workers[k], &attr, go, k_copy);
|
||||
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
for(k = 0; k < thread_count; k++) {
|
||||
pthread_join(workers[k],NULL);
|
||||
}
|
||||
|
||||
|
||||
printf("mean: (max, avg) %f, %f\n", max_mean, avg_mean / (double)thread_count);
|
||||
|
||||
printf("variance: (max, avg) %f, %f\n", max_var, avg_var / (double)thread_count);
|
||||
|
||||
|
||||
Tdeinit();
|
||||
}
|
233
benchmarks/linearHashNTAWriteRequests.c
Normal file
233
benchmarks/linearHashNTAWriteRequests.c
Normal file
|
@ -0,0 +1,233 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <lladd/transactional.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
pthread_cond_t never;
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
#define MAX_SECONDS 100
|
||||
|
||||
#define COUNTER_RESOLUTION 240
|
||||
|
||||
int buckets[COUNTER_RESOLUTION];
|
||||
|
||||
// if we're using linux's crazy version of the pthread header,
|
||||
// it probably forgot to include PTHREAD_STACK_MIN
|
||||
|
||||
#ifndef PTHREAD_STACK_MIN
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
int activeThreads = 0;
|
||||
int max_active = 0;
|
||||
|
||||
/*double avg_var = 0;
|
||||
double max_var = 0;
|
||||
double avg_mean = 0;
|
||||
double max_mean = 0;*/
|
||||
|
||||
//static pthread_mutex_t hash_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int count;
|
||||
static recordid hash;
|
||||
|
||||
static void * go (void * arg_ptr) {
|
||||
// pthread_mutex_lock(&hash_mutex);
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
activeThreads++;
|
||||
if(activeThreads > max_active) {
|
||||
max_active = activeThreads;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
int k = *(int*)arg_ptr;
|
||||
int j;
|
||||
int xid = Tbegin();
|
||||
|
||||
double sum_x_squared = 0;
|
||||
double sum = 0;
|
||||
|
||||
double log_multiplier = COUNTER_RESOLUTION / log(MAX_SECONDS * 1000000000.0);
|
||||
|
||||
struct timeval timeout_tv;
|
||||
struct timespec timeout;
|
||||
|
||||
gettimeofday(&timeout_tv, NULL);
|
||||
|
||||
timeout.tv_sec = timeout_tv.tv_sec;
|
||||
timeout.tv_nsec = 1000 * timeout_tv.tv_usec;
|
||||
|
||||
timeout.tv_nsec = (int)(1000000000.0 * ((double)random() / (double)RAND_MAX));
|
||||
|
||||
timeout.tv_sec++;
|
||||
|
||||
// struct timeval start;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
pthread_cond_timedwait(&never, &mutex, &timeout);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
|
||||
/* gettimeofday(&start, NULL);
|
||||
assert(timeout.tv_sec <= start.tv_sec);
|
||||
assert(timeout.tv_nsec <= start.tv_nsec || timeout.tv_sec < start.tv_sec);*/
|
||||
|
||||
|
||||
|
||||
for(j = k * count; j < (k+1) *(count) ; j++) {
|
||||
|
||||
|
||||
// struct timeval start,
|
||||
struct timeval endtime_tv;
|
||||
struct timespec endtime;
|
||||
// gettimeofday(&start, NULL);
|
||||
|
||||
|
||||
// start = timeout;
|
||||
|
||||
|
||||
/* gettimeofday(&start, NULL);
|
||||
assert(timeout.tv_sec <= start.tv_sec);
|
||||
assert(timeout.tv_nsec <= start.tv_nsec || timeout.tv_sec < start.tv_sec);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
ThashInsert(xid, hash, (byte*)&j, sizeof(int), (byte*)&j, sizeof(int));
|
||||
|
||||
gettimeofday(&endtime_tv, NULL);
|
||||
|
||||
endtime.tv_sec = endtime_tv.tv_sec;
|
||||
endtime.tv_nsec = 1000 * endtime_tv.tv_usec;
|
||||
|
||||
double microSecondsPassed = 1000000000.0 * (double)(endtime.tv_sec - timeout.tv_sec);
|
||||
|
||||
|
||||
microSecondsPassed = (microSecondsPassed + (double)endtime.tv_nsec) - (double)timeout.tv_nsec;
|
||||
|
||||
assert(microSecondsPassed > 0.0);
|
||||
|
||||
|
||||
sum += microSecondsPassed;
|
||||
sum_x_squared += (microSecondsPassed * microSecondsPassed) ;
|
||||
|
||||
int bucket = (log_multiplier * log(microSecondsPassed));
|
||||
|
||||
if(bucket >= COUNTER_RESOLUTION) { bucket = COUNTER_RESOLUTION - 1; }
|
||||
|
||||
timeout.tv_sec++;
|
||||
pthread_mutex_lock(&mutex);
|
||||
buckets[bucket]++;
|
||||
pthread_cond_timedwait(&never, &mutex, &timeout);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
// printf("(%d)", k);
|
||||
}
|
||||
|
||||
|
||||
Tcommit(xid);
|
||||
/*
|
||||
for(j = k * count; j < (k+1) *(count) ; j++) {
|
||||
int tmp = -100;
|
||||
TlogicalHashLookup(xid, hash, &j, sizeof(int), &tmp, sizeof(int));
|
||||
assert(j == tmp);
|
||||
} */
|
||||
|
||||
// double count_d = count;
|
||||
// double mean = sum / count_d;
|
||||
// double variance = sqrt((sum_x_squared / count_d) - (mean * mean));
|
||||
|
||||
|
||||
|
||||
// pthread_mutex_unlock(&hash_mutex);
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
activeThreads--;
|
||||
|
||||
/* avg_mean += mean;
|
||||
avg_var += variance;
|
||||
|
||||
if(mean > max_mean ) { max_mean = mean; }
|
||||
if(variance > max_var) { max_var = variance; } */
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
assert(argc == 3);
|
||||
|
||||
int thread_count = atoi(argv[1]);
|
||||
count = atoi(argv[2]);
|
||||
|
||||
unlink("storefile.txt");
|
||||
unlink("logfile.txt");
|
||||
unlink("blob0_file.txt");
|
||||
unlink("blob1_file.txt");
|
||||
|
||||
int l;
|
||||
|
||||
for(l = 0; l < COUNTER_RESOLUTION; l++) {
|
||||
buckets[l] = 0;
|
||||
}
|
||||
|
||||
pthread_t * workers = malloc(sizeof(pthread_t) * thread_count);
|
||||
|
||||
Tinit();
|
||||
int xid = Tbegin();
|
||||
hash = ThashCreate(xid, sizeof(int), sizeof(int));
|
||||
|
||||
Tcommit(xid);
|
||||
|
||||
int k;
|
||||
|
||||
/* threads have static thread sizes. Ughh. */
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
pthread_cond_init(&never, NULL);
|
||||
|
||||
pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
|
||||
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
|
||||
for(k = 0; k < thread_count; k++) {
|
||||
int * k_copy = malloc(sizeof(int));
|
||||
*k_copy = k ;
|
||||
pthread_create(&workers[k], &attr, go, k_copy);
|
||||
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
for(k = 0; k < thread_count; k++) {
|
||||
pthread_join(workers[k],NULL);
|
||||
}
|
||||
|
||||
double log_multiplier = (COUNTER_RESOLUTION / log(MAX_SECONDS * 1000000000.0));
|
||||
|
||||
|
||||
|
||||
for(k = 0; k < COUNTER_RESOLUTION; k++) {
|
||||
printf("%3.4f\t%d\n", exp(((double)k)/log_multiplier)/1000000000.0, buckets[k]);
|
||||
}
|
||||
|
||||
/* printf("mean: (max, avg) %f, %f\n", max_mean, avg_mean / (double)thread_count);
|
||||
|
||||
printf("variance: (max, avg) %f, %f\n", max_var, avg_var / (double)thread_count); */
|
||||
|
||||
Tdeinit();
|
||||
}
|
88
benchmarks/pageOrientedListNTA.c
Normal file
88
benchmarks/pageOrientedListNTA.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <lladd/transactional.h>
|
||||
#include <unistd.h>
|
||||
|
||||
//#define CHECK_RESULTS 1
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
assert(argc == 3);
|
||||
|
||||
int xact_count = atoi(argv[1]);
|
||||
int count = atoi(argv[2]);
|
||||
int k;
|
||||
|
||||
/* unlink("storefile.txt");
|
||||
unlink("logfile.txt");
|
||||
unlink("blob0_file.txt");
|
||||
unlink("blob1_file.txt"); */
|
||||
|
||||
Tinit();
|
||||
int xid = Tbegin();
|
||||
|
||||
recordid hash = TpagedListAlloc(xid);
|
||||
|
||||
Tcommit(xid);
|
||||
|
||||
int i = 0;
|
||||
|
||||
for(k = 0; k < xact_count; k++) {
|
||||
|
||||
xid = Tbegin();
|
||||
|
||||
for(;i < count *(k+1) ; i++) {
|
||||
|
||||
TpagedListInsert(xid, hash, (byte*)&i, sizeof(int), (byte*)&i, sizeof(int));
|
||||
|
||||
}
|
||||
|
||||
Tcommit(xid);
|
||||
|
||||
}
|
||||
|
||||
#ifdef CHECK_RESULTS
|
||||
|
||||
printf("Checking results.\n");
|
||||
xid = Tbegin();
|
||||
lladd_pagedList_iterator * it = TpagedListIterator(xid, hash);
|
||||
|
||||
assert(i == xact_count * count);
|
||||
|
||||
int seen[count * xact_count];
|
||||
for(i = 0; i < xact_count * count; i++) {
|
||||
seen[i] = 0;
|
||||
}
|
||||
i = 0;
|
||||
int * key;
|
||||
int * val;
|
||||
int keySize;
|
||||
int valSize;
|
||||
while(TpagedListNext(xid, it, (byte**)&key, &keySize, (byte**)&val, &valSize)) {
|
||||
assert(*key == *val);
|
||||
assert(keySize == sizeof(int));
|
||||
assert(valSize == sizeof(int));
|
||||
assert(!seen[*key]);
|
||||
seen[*key]++;
|
||||
|
||||
free(key);
|
||||
free(val);
|
||||
|
||||
i++;
|
||||
|
||||
}
|
||||
assert(i == xact_count * count);
|
||||
for(int i = 0; i < count * xact_count; i++) {
|
||||
assert(seen[i]==1);
|
||||
}
|
||||
|
||||
Tcommit(xid);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Tdeinit();
|
||||
|
||||
}
|
|
@ -44,6 +44,7 @@ AM_CONDITIONAL(HAVE_CHECK, test x$have_check = xtrue)
|
|||
#AC_CHECK_LIB(efence,memalign)
|
||||
#fi
|
||||
|
||||
|
||||
# Linux has a broken O_DIRECT flag, but we allow people to override it from
|
||||
# the command line.
|
||||
test_host_prw=yes
|
||||
|
@ -93,6 +94,9 @@ AC_FUNC_REALLOC
|
|||
AC_FUNC_STAT
|
||||
AC_CHECK_FUNCS([bzero fdatasync getcwd gettimeofday inet_ntoa localtime_r memmove memset mkdir powl posix_memalign socket sqrt strchr strdup strerror strrchr strstr strtoul])
|
||||
|
||||
#AC_CONFIG_LIBMYSQLD
|
||||
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
benchmarks/Makefile
|
||||
benchmarks/berkeleyDB/Makefile
|
||||
|
|
|
@ -82,14 +82,14 @@ terms specified in this license.
|
|||
|
||||
/* #define MAX_BUFFER_SIZE 100003 */
|
||||
/*#define MAX_BUFFER_SIZE 20029 */
|
||||
/*#define MAX_BUFFER_SIZE 10007 */
|
||||
#define MAX_BUFFER_SIZE 10007
|
||||
/*#define MAX_BUFFER_SIZE 5003*/
|
||||
#define MAX_BUFFER_SIZE 2003
|
||||
/*#define MAX_BUFFER_SIZE 2003 */
|
||||
/* #define MAX_BUFFER_SIZE 71 */
|
||||
/*#define MAX_BUFFER_SIZE 7 */
|
||||
/*#define BUFFER_ASOOCIATIVE 2 */
|
||||
|
||||
#define MAX_TRANSACTIONS 1000
|
||||
#define MAX_TRANSACTIONS 100000
|
||||
|
||||
/** Operation types */
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ dnl AM_PATH_CHECK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
|
|||
dnl Test for check, and define CHECK_CFLAGS and CHECK_LIBS
|
||||
dnl
|
||||
|
||||
AC_DEFUN(AM_PATH_CHECK,
|
||||
AC_DEFUN([AM_PATH_CHECK],
|
||||
[
|
||||
AC_ARG_WITH(check,
|
||||
[ --with-check=PATH prefix where check is installed [default=auto]])
|
||||
|
|
|
@ -2,7 +2,7 @@ dnl
|
|||
dnl Autoconf support for finding LLADD
|
||||
dnl
|
||||
|
||||
AC_DEFUN(AC_LLADD_HELP, [
|
||||
AC_DEFUN([AC_LLADD_HELP], [
|
||||
cat <<EOF
|
||||
|
||||
Configure error with LLADD...
|
||||
|
@ -17,7 +17,7 @@ EOF
|
|||
dnl
|
||||
dnl Main macro for finding a usable LLADD installation
|
||||
dnl
|
||||
AC_DEFUN(AC_CONFIG_LLADD, [
|
||||
AC_DEFUN([AC_CONFIG_LLADD], [
|
||||
ac_lladddir='system'
|
||||
|
||||
AC_ARG_WITH(lladd,
|
||||
|
|
|
@ -29,6 +29,7 @@ compensated_function int TpagedListInsert(int xid, recordid list, const byte * k
|
|||
Tread(xid, list, &header);
|
||||
recordid headerRid = list;
|
||||
|
||||
pagedListHeader firstHeader = header;
|
||||
/* byte * garbage;
|
||||
ret = (TpagedListFind(xid, list, key, keySize, &garbage) != -1);
|
||||
if(ret) {
|
||||
|
@ -46,7 +47,7 @@ compensated_function int TpagedListInsert(int xid, recordid list, const byte * k
|
|||
while(rid.size == -1) {
|
||||
if(compensation_error()) { break; }
|
||||
if(header.nextPage.size == -1) {
|
||||
header.nextPage = Talloc(xid, sizeof(pagedListHeader));
|
||||
/* header.nextPage = Talloc(xid, sizeof(pagedListHeader));
|
||||
DEBUG("allocing on new page %d\n", header.nextPage.page);
|
||||
Tset(xid, headerRid, &header);
|
||||
pagedListHeader newHead;
|
||||
|
@ -54,11 +55,25 @@ compensated_function int TpagedListInsert(int xid, recordid list, const byte * k
|
|||
newHead.nextPage.page =0;
|
||||
newHead.nextPage.slot =0;
|
||||
newHead.nextPage.size =-1;
|
||||
Tset(xid, header.nextPage, &newHead);
|
||||
Tset(xid, header.nextPage, &newHead); */
|
||||
// We're at the end of the list
|
||||
|
||||
recordid newHeadRid = Talloc(xid, sizeof(pagedListHeader));
|
||||
pagedListHeader newHead;
|
||||
newHead.thisPage = 0;
|
||||
newHead.nextPage = firstHeader.nextPage;
|
||||
|
||||
firstHeader.nextPage = newHeadRid;
|
||||
|
||||
Tset(xid, newHeadRid, &newHead);
|
||||
Tset(xid, list, &firstHeader);
|
||||
|
||||
header = newHead;
|
||||
headerRid = newHeadRid;
|
||||
} else {
|
||||
headerRid = header.nextPage;
|
||||
Tread(xid, header.nextPage, &header);
|
||||
}
|
||||
|
||||
headerRid = header.nextPage;
|
||||
Tread(xid, header.nextPage, &header);
|
||||
rid = TallocFromPage(xid, headerRid.page, entrySize);
|
||||
DEBUG("Alloced rid: {%d %d %d}", rid.page, rid.slot, rid.size);
|
||||
}
|
||||
|
@ -75,6 +90,7 @@ compensated_function int TpagedListInsert(int xid, recordid list, const byte * k
|
|||
DEBUG("Header.thisPage = %d\n", rid.slot);
|
||||
Tset(xid, headerRid, &header);
|
||||
free(dat);
|
||||
|
||||
} end_ret(compensation_error());
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
LDADD=$(top_builddir)/src/2pc/lib2pc.a $(top_builddir)/src/libdfa/libdfa.a \
|
||||
$(top_builddir)/src/lladd/liblladd.a $(top_builddir)/src/pbl/libpbl.a \
|
||||
$(top_builddir)/src/libdfa/librw.a
|
||||
bin_PROGRAMS=logfile_dump
|
||||
bin_PROGRAMS=logfile_dump run_recovery truncate_log
|
||||
AM_CFLAGS= -g -Wall -pedantic -std=gnu99
|
||||
|
|
8
utilities/run_recovery.c
Normal file
8
utilities/run_recovery.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <lladd/transactional.h>
|
||||
|
||||
int main(void) {
|
||||
Tinit();
|
||||
Tdeinit();
|
||||
return compensation_error();
|
||||
}
|
||||
|
14
utilities/truncate_log.c
Normal file
14
utilities/truncate_log.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include <lladd/transactional.h>
|
||||
#include "../src/lladd/logger/logWriter.h"
|
||||
int main(void) {
|
||||
Tinit();
|
||||
syncLog();
|
||||
lsn_t trunc_to = flushedLSN();
|
||||
Tdeinit();
|
||||
|
||||
openLogWriter();
|
||||
truncateLog(trunc_to);
|
||||
|
||||
return compensation_error();
|
||||
}
|
||||
|
Loading…
Reference in a new issue