summaryrefslogtreecommitdiffstats
path: root/src/bench
diff options
context:
space:
mode:
authorChristian Klinger2016-07-15 10:11:04 +0200
committerChristian Klinger2016-07-15 10:11:04 +0200
commitb747910584c2eac6fd4c4c9835016c491c01f531 (patch)
tree0970c97c9d45953401672e045a549171de41de65 /src/bench
parent[SERVER] Bump debug lock tracking limits (diff)
downloaddnbd3-b747910584c2eac6fd4c4c9835016c491c01f531.tar.gz
dnbd3-b747910584c2eac6fd4c4c9835016c491c01f531.tar.xz
dnbd3-b747910584c2eac6fd4c4c9835016c491c01f531.zip
Added rudimentary benchmark tool.
Diffstat (limited to 'src/bench')
-rw-r--r--src/bench/connection.c132
-rw-r--r--src/bench/connection.h26
-rw-r--r--src/bench/helper.c37
-rw-r--r--src/bench/helper.h38
-rw-r--r--src/bench/main.c154
-rw-r--r--src/bench/serialize.c5
6 files changed, 392 insertions, 0 deletions
diff --git a/src/bench/connection.c b/src/bench/connection.c
new file mode 100644
index 0000000..94d5aee
--- /dev/null
+++ b/src/bench/connection.c
@@ -0,0 +1,132 @@
+#include "connection.h"
+#include "helper.h"
+#include "../config.h"
+#include "../shared/protocol.h"
+#include "../shared/fdsignal.h"
+#include "../shared/sockhelper.h"
+#include "../shared/log.h"
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+/* Constants */
+static const size_t SHORTBUF = 100;
+#define MAX_ALTS (8)
+#define MAX_HOSTS_PER_ADDRESS (2)
+// If a server wasn't reachable this many times, we slowly start skipping it on measurements
+static const int FAIL_BACKOFF_START_COUNT = 8;
+#define RTT_COUNT (4)
+
+/* Module variables */
+
+// Init guard
+static bool connectionInitDone = false;
+static bool keepRunning = true;
+
+static struct {
+ int sockFd;
+ pthread_mutex_t sendMutex;
+ dnbd3_signal_t* panicSignal;
+ dnbd3_host_t currentServer;
+ uint64_t startupTime;
+} connection;
+
+// Known alt servers
+typedef struct _alt_server {
+ dnbd3_host_t host;
+ int consecutiveFails;
+ int rtt;
+ int rtts[RTT_COUNT];
+ int rttIndex;
+ int bestCount;
+} alt_server_t;
+alt_server_t altservers[MAX_ALTS];
+dnbd3_server_entry_t newservers[MAX_ALTS];
+pthread_spinlock_t altLock;
+
+bool connection_init_n_times(
+ const char *hosts,
+ const char *lowerImage,
+ const uint16_t rid,
+ int ntimes,
+ BenchCounters* counters,
+ bool closeSockets
+ ) {
+ for (int run_i = 0; run_i < ntimes; ++run_i) {
+ counters->attempts++;
+
+ printf(".");
+ int sock = -1;
+ char host[SHORTBUF];
+ serialized_buffer_t buffer;
+ uint16_t remoteVersion, remoteRid;
+ char *remoteName;
+ uint64_t remoteSize;
+
+ if ( !connectionInitDone && keepRunning ) {
+ dnbd3_host_t tempHosts[MAX_HOSTS_PER_ADDRESS];
+ const char *current, *end;
+ int altIndex = 0;
+ memset( altservers, 0, sizeof altservers );
+ connection.sockFd = -1;
+ current = hosts;
+ do {
+ // Get next host from string
+ while ( *current == ' ' ) current++;
+ end = strchr( current, ' ' );
+ size_t len = (end == NULL ? SHORTBUF : (size_t)( end - current ) + 1);
+ if ( len > SHORTBUF ) len = SHORTBUF;
+ snprintf( host, len, "%s", current );
+ int newHosts = sock_resolveToDnbd3Host( host, tempHosts, MAX_HOSTS_PER_ADDRESS );
+ for ( int i = 0; i < newHosts; ++i ) {
+ if ( altIndex >= MAX_ALTS )
+ break;
+ altservers[altIndex].host = tempHosts[i];
+ altIndex += 1;
+ }
+ current = end + 1;
+ } while ( end != NULL && altIndex < MAX_ALTS );
+ logadd( LOG_INFO, "Got %d servers from init call", altIndex );
+ // Connect
+ for ( int i = 0; i < altIndex; ++i ) {
+ if ( altservers[i].host.type == 0 )
+ continue;
+ // Try to connect
+ sock = sock_connect( &altservers[i].host, 500, SOCKET_KEEPALIVE_TIMEOUT * 1000 );
+ if ( sock == -1 ) {
+ counters->fails++;
+ logadd( LOG_ERROR, "Could not connect to host" );
+ } else if ( !dnbd3_select_image( sock, lowerImage, rid, 0 ) ) {
+ counters->fails++;
+ logadd( LOG_ERROR, "Could not send select image" );
+ } else if ( !dnbd3_select_image_reply( &buffer, sock, &remoteVersion, &remoteName, &remoteRid, &remoteSize ) ) {
+ counters->fails++;
+ logadd( LOG_ERROR, "Could not read select image reply (%d)", errno );
+ } else if ( rid != 0 && rid != remoteRid ) {
+ counters->fails++;
+ logadd( LOG_ERROR, "rid mismatch" );
+ } else {
+ counters->success++;
+ break;
+ }
+ // Failed
+ logadd( LOG_DEBUG1, "Server does not offer requested image... " );
+ if ( sock != -1 ) {
+ close( sock );
+ sock = -1;
+ }
+ }
+ if ( sock != -1 ) {
+ // connectionInitDone = true;
+ if (closeSockets) {
+ close( sock );
+ }
+ }
+ }
+ }
+ return true;
+}
diff --git a/src/bench/connection.h b/src/bench/connection.h
new file mode 100644
index 0000000..9cb59ef
--- /dev/null
+++ b/src/bench/connection.h
@@ -0,0 +1,26 @@
+#ifndef _CONNECTION_H_
+#define _CONNECTION_H_
+
+#include "../shared/fdsignal.h"
+#include <stdbool.h>
+#include <stdint.h>
+#include "helper.h"
+
+struct _dnbd3_async;
+
+typedef struct _dnbd3_async {
+ struct _dnbd3_async *next; // Next in this linked list (provate field, not set by caller)
+ char* buffer; // Caller-provided buffer to be filled
+ uint64_t offset;
+ uint32_t length;
+ dnbd3_signal_t* signal; // Used to signal the caller
+ bool finished; // Will be set to true if the request has been handled
+ bool success; // Will be set to true if the request succeeded
+} dnbd3_async_t;
+
+
+bool connection_init_n_times(const char *hosts, const char *image, const uint16_t rid, int ntimes, BenchCounters* counters, bool closeSockets);
+
+bool connection_init(const char *hosts, const char *image, const uint16_t rid);
+
+#endif /* CONNECTION_H_ */
diff --git a/src/bench/helper.c b/src/bench/helper.c
new file mode 100644
index 0000000..c89b614
--- /dev/null
+++ b/src/bench/helper.c
@@ -0,0 +1,37 @@
+#include "helper.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+//BenchCounters benchC = { .attempts = 0, .success = 0, .fails = 0};
+
+void printLog( log_info *info )
+{
+ FILE *logFile;
+
+ // Create logfile
+
+ logFile = fopen( "log.txt", "w" );
+ if ( logFile == NULL ) {
+ printf( "Error creating/opening log.txt\n" );
+ return;
+ }
+
+ //rewind(file);
+ fprintf( logFile, "ImageSize: %"PRIu64" MiB\n", ( uint64_t )( info->imageSize/ ( 1024ll*1024ll ) ) );
+ fprintf( logFile, "ReceivedMiB: %"PRIu64" MiB\n", ( uint64_t )( info->receivedBytes/ ( 1024ll*1024ll ) ) );
+ fprintf( logFile, "imageBlockCount: %"PRIu64"\n", info->imageBlockCount );
+ fprintf( logFile, "Blocksize: 4KiB\n\n" );
+ fprintf( logFile, "Block access count:\n" );
+
+ uint64_t i = 0;
+ for ( ; i < info->imageBlockCount; i++ ) {
+ if ( i % 50 == 0 ) {
+ fprintf( logFile, "\n" );
+ }
+ fprintf( logFile, "%i ", ( int ) info->blockRequestCount[i] );
+ }
+ fprintf( logFile, "\n" );
+ fclose( logFile );
+}
diff --git a/src/bench/helper.h b/src/bench/helper.h
new file mode 100644
index 0000000..8342a79
--- /dev/null
+++ b/src/bench/helper.h
@@ -0,0 +1,38 @@
+#ifndef IMAGEHELPER_H
+#define IMAGEHELPER_H
+
+#include "../types.h"
+
+#include <netdb.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/socket.h>
+
+typedef struct log_info {
+ uint64_t imageSize;
+ uint64_t receivedBytes;
+ uint64_t imageBlockCount;
+ uint8_t *blockRequestCount;
+} log_info;
+
+
+typedef struct BenchCounters {
+ int attempts;
+ int success;
+ int fails;
+} BenchCounters;
+
+
+typedef struct BenchThreadData {
+ BenchCounters* counter;
+ char* server_address;
+ char * image_name;
+ int runs;
+ int threadNumber;
+ bool closeSockets;
+} BenchThreadData;
+
+
+
+#endif
diff --git a/src/bench/main.c b/src/bench/main.c
new file mode 100644
index 0000000..2f32dbf
--- /dev/null
+++ b/src/bench/main.c
@@ -0,0 +1,154 @@
+/*
+* Butchered from the dnbd3-fuse by C.K.
+**/
+
+#include "connection.h"
+#include "helper.h"
+#include "../shared/protocol.h"
+#include "../shared/log.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <getopt.h>
+#include <pthread.h>
+
+#define debugf(...) do { logadd( LOG_DEBUG1, __VA_ARGS__ ); } while (0)
+
+
+/* Debug/Benchmark variables */
+static bool useDebug = false;
+
+
+static void printUsage(char *argv0, int exitCode)
+{
+ printf( "Usage: %s [--debug] --host <serverAddress(es)> --image <imageName> [--rid revision]\n", argv0 );
+ printf( "Or: %s [-d] -h <serverAddress(es)> -i <imageName> [-r revision]\n", argv0 );
+ printf( " -h --host List of space separated hosts to use\n" );
+ printf( " -i --image Remote image name to request\n" );
+ printf( " -r --rid Revision to use (omit or pass 0 for latest)\n" );
+ printf( " -n --runs Number of connection attempts per thread\n" );
+ printf( " -t --threads number of threads\n" );
+ printf( " -l --log Write log to given location\n" );
+ printf( " -d --debug Don't fork and print debug output (fuse > stderr, dnbd3 > stdout)\n" );
+ // // fuse_main( 2, arg, &dnbd3_fuse_no_operations, NULL );
+ exit( exitCode );
+}
+
+static const char *optString = "h:i:n:t:HvVd";
+static const struct option longOpts[] = {
+ { "host", required_argument, NULL, 'h' },
+ { "image", required_argument, NULL, 'i' },
+ { "nruns", optional_argument, NULL, 'n' },
+ { "threads", optional_argument, NULL, 't' },
+ { "help", optional_argument, NULL, 'H' },
+ { "version", no_argument, NULL, 'v' },
+ { 0, 0, 0, 0 }
+};
+
+
+static void printBenchCounters(BenchCounters* c) {
+ printf ("Attempts:\t%d\n", c->attempts);
+ printf ("Success :\t%d\n", c->success);
+ printf ("Fails :\t%d\n", c->fails);
+}
+
+
+void* runBenchThread(void* t) {
+ BenchThreadData* data = t;
+ connection_init_n_times(
+ data->server_address,
+ data->server_address,
+ 0,
+ data->runs,
+ data->counter,
+ data->closeSockets);
+ printf("Thread #%d finished\n", data->threadNumber);
+ return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+ char *server_address = NULL;
+ char *image_Name = NULL;
+ int opt, lidx;
+
+ bool closeSockets = false;
+ int n_runs = 100;
+ int n_threads = 1;
+
+ if ( argc <= 1 || strcmp( argv[1], "--help" ) == 0 || strcmp( argv[1], "--usage" ) == 0 ) {
+ printUsage( argv[0], 0 );
+ }
+
+ while ( ( opt = getopt_long( argc, argv, optString, longOpts, &lidx ) ) != -1 ) {
+ switch ( opt ) {
+ case 'h':
+ server_address = optarg;
+ break;
+ case 'i':
+ image_Name = optarg;
+ break;
+ case 'n':
+ n_runs = atoi(optarg);
+ break;
+ case 't':
+ n_threads = atoi(optarg);
+ break;
+ case 'c':
+ closeSockets = true;
+ break;
+ case 'H':
+ printUsage( argv[0], 0 );
+ break;
+ case 'd':
+ useDebug = true;
+ break;
+ default:
+ printUsage( argv[0], EXIT_FAILURE );
+ }
+ }
+
+ printf("Welcome to dnbd3 benchmark tool\n");
+
+ /* all counters */
+ BenchCounters counters[n_threads];
+ BenchThreadData threadData[n_threads];
+ pthread_t threads[n_threads];
+
+ /* create all threads */
+ for (int i = 0; i < n_threads; i++) {
+ BenchCounters tmp1 = {0,0,0};
+ counters[i] = tmp1;
+ BenchThreadData tmp2 = {
+ &(counters[i]),
+ server_address,
+ image_Name,
+ n_runs,
+ i,
+ closeSockets};
+ threadData[i] = tmp2;
+ pthread_create(&(threads[i]), NULL, runBenchThread, &(threadData[i]));
+ }
+
+
+ /* join all threads*/
+ for (int i = 0; i < n_threads; ++i) {
+ pthread_join(threads[i], NULL);
+ }
+
+ /* print out all counters & sum up */
+ BenchCounters total = {0,0,0};
+ for (int i = 0; i < n_threads; ++i) {
+ printf("#### Thread %d\n", i);
+ printBenchCounters(&counters[i]);
+ total.attempts += counters[i].attempts;
+ total.success += counters[i].success;
+ total.fails += counters[i].fails;
+ }
+ /* print out summary */
+ printf("\n\n#### SUMMARY\n");
+ printBenchCounters(&total);
+ printf("\n-- End of program");
+}
diff --git a/src/bench/serialize.c b/src/bench/serialize.c
new file mode 100644
index 0000000..4934132
--- /dev/null
+++ b/src/bench/serialize.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../serialize.c"