summaryrefslogtreecommitdiff
path: root/client-responsiveness/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'client-responsiveness/scripts')
-rw-r--r--client-responsiveness/scripts/__init__.py0
-rwxr-xr-xclient-responsiveness/scripts/create_payload.py29
-rwxr-xr-xclient-responsiveness/scripts/get_client_stats.py20
-rwxr-xr-xclient-responsiveness/scripts/get_ping_rate.py19
-rwxr-xr-xclient-responsiveness/scripts/measure_perf_series.py31
-rwxr-xr-xclient-responsiveness/scripts/preload_server_database.py39
-rw-r--r--client-responsiveness/scripts/server_with_soledad_syncer.py47
-rw-r--r--client-responsiveness/scripts/soledad_sync.py96
-rwxr-xr-xclient-responsiveness/scripts/sync_stats.gnuplot23
9 files changed, 304 insertions, 0 deletions
diff --git a/client-responsiveness/scripts/__init__.py b/client-responsiveness/scripts/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/client-responsiveness/scripts/__init__.py
diff --git a/client-responsiveness/scripts/create_payload.py b/client-responsiveness/scripts/create_payload.py
new file mode 100755
index 0000000..d051661
--- /dev/null
+++ b/client-responsiveness/scripts/create_payload.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+
+"""
+Create a payload file in disk to use during tests. Reads the name of the file
+and the intended size of the payload from the "defaults.conf" file:
+
+ PAYLOAD = /path/to/payload/file
+ PAYLOAD_SIZE = 500 # in Kb
+"""
+
+import os
+from ConfigParser import ConfigParser
+
+parser = ConfigParser()
+parser.read('defaults.conf')
+
+PAYLOAD = parser.get('sync', 'payload')
+PAYLOAD_SIZE = int(parser.get('sync', 'payload_size')) * 1024
+
+if os.path.isfile(PAYLOAD):
+ os.unlink(PAYLOAD)
+
+content = 'a' * 1024
+
+with open(PAYLOAD, 'w') as f:
+ length = 0
+ while length < PAYLOAD_SIZE:
+ f.write(content)
+ length += len(content)
diff --git a/client-responsiveness/scripts/get_client_stats.py b/client-responsiveness/scripts/get_client_stats.py
new file mode 100755
index 0000000..59f9aa6
--- /dev/null
+++ b/client-responsiveness/scripts/get_client_stats.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+
+"""
+Get stats from dummy server running Soledad Client and spit them out.
+"""
+
+import commands
+import urllib
+import psutil
+
+stats = urllib.urlopen('http://localhost:8080/stats').read().split()
+
+pid, sync_phase, sync_exchange_phase = stats
+
+res = commands.getoutput("ps -p " + pid + " -o \%cpu,\%mem")
+splitted = res.split()
+cpu = splitted[2]
+mem = splitted[3]
+
+print cpu, mem, sync_phase, sync_exchange_phase
diff --git a/client-responsiveness/scripts/get_ping_rate.py b/client-responsiveness/scripts/get_ping_rate.py
new file mode 100755
index 0000000..19d63d1
--- /dev/null
+++ b/client-responsiveness/scripts/get_ping_rate.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+
+"""
+Measure the connection rate to the dummy server running Soledad Client using
+httperf and spit it out.
+"""
+
+import commands
+import re
+
+# ORIGINAL, STANDARD MEASURE (TOTALLY RANDOM)
+#res = commands.getoutput(
+ #'httperf --server localhost --port 8080 --num-calls 5 --num-conns 20 '
+ #'--uri /ping | grep "Connection rate"')
+
+res = commands.getoutput(
+ 'httperf --server localhost --port 8080 --num-calls 5 --num-conns 10 '
+ '--uri /ping | grep "Connection rate"')
+print re.findall('[-+]?([0-9]*\.?[0-9]+)', res)[0]
diff --git a/client-responsiveness/scripts/measure_perf_series.py b/client-responsiveness/scripts/measure_perf_series.py
new file mode 100755
index 0000000..587ff7a
--- /dev/null
+++ b/client-responsiveness/scripts/measure_perf_series.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+
+import commands
+import datetime
+
+# How many points to measure. Make sure that you leave the baseline
+# running for a significative amount before triggering the sync, it's possible
+# you have significant variability in there.
+POINTS = 400
+
+SCALE = 50
+
+commands.getoutput('echo time req/s cpu mem sync_phase sync_exchange_phase > ./out/series.log')
+start = datetime.datetime.now()
+
+for i in range(POINTS):
+ value = commands.getoutput('./scripts/get_ping_rate.py')
+ print "Step", i, "...", value
+ stats = commands.getoutput('./scripts/get_client_stats.py')
+ cpu, mem, sync_phase, sync_exchange_phase = stats.split()
+ sync_phase = str(int(sync_phase)*SCALE)
+ sync_exchange_phase = str(int(sync_exchange_phase)*SCALE)
+ now = datetime.datetime.now()
+ secs = (now - start).total_seconds()
+ try:
+ # make it so the script exits succesfully when the server is dead
+ commands.getoutput(
+ 'echo %s\t%s\t%s\t%s\t%s\t%s >> ./out/series.log' \
+ % (secs, value, cpu, mem, sync_phase, sync_exchange_phase))
+ except ValueError:
+ break
diff --git a/client-responsiveness/scripts/preload_server_database.py b/client-responsiveness/scripts/preload_server_database.py
new file mode 100755
index 0000000..95e8cfd
--- /dev/null
+++ b/client-responsiveness/scripts/preload_server_database.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+
+"""
+Preload the server database with a certain amount of documents so we can
+receive them during the sync process and gather meaningful statistics for that
+specific phase of sync.
+
+Gets uuid, payload file path and amount of documents to preload from
+"defaults.conf" config file:
+
+ UUID = some-uuid
+ PAYLOAD = /path/to/payload/file
+ NUM_DOCS = 100
+"""
+
+import os
+from ConfigParser import ConfigParser
+from leap.soledad.common.couch import CouchDatabase
+
+parser = ConfigParser()
+parser.read('defaults.conf')
+
+UUID = parser.get('client', 'uuid')
+PAYLOAD = parser.get('sync', 'payload')
+NUM_DOCS = int(parser.get('sync', 'num_docs'))
+
+db = CouchDatabase.open_database(
+ 'http://127.0.0.1:5984/user-%s' % UUID,
+ False) # should create database?
+
+payload = None
+if os.path.isfile(PAYLOAD):
+ with open(PAYLOAD, 'r') as f:
+ payload = f.read()
+
+for i in xrange(NUM_DOCS):
+ db.create_doc({'payload': payload})
+
+db.close()
diff --git a/client-responsiveness/scripts/server_with_soledad_syncer.py b/client-responsiveness/scripts/server_with_soledad_syncer.py
new file mode 100644
index 0000000..2890e04
--- /dev/null
+++ b/client-responsiveness/scripts/server_with_soledad_syncer.py
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+#!/usr/bin/env python
+
+
+import os
+from klein import run, route, resource
+import soledad_sync as sync
+from twisted.internet import reactor
+import datetime
+
+
+@route('/create-docs')
+def create_docs(request):
+ d = sync.create_docs()
+ return d
+
+
+@route('/start-sync')
+def start_sync(request):
+ d = sync.start_sync()
+ return d
+
+
+@route('/ping')
+def ping(request):
+ return 'easy!'
+
+
+@route('/pid')
+def pid(request):
+ return str(os.getpid())
+
+
+@route('/stop')
+def stop(request):
+ reactor.callLater(1, reactor.stop)
+ return ''
+
+@route('/stats')
+def stats(request):
+ pid = os.getpid()
+ sync_phase, sync_exchange_phase = sync.stats()
+ return "%d %d %d" % (pid, sync_phase, sync_exchange_phase)
+
+
+if __name__ == "__main__":
+ run("localhost", 8080)
diff --git a/client-responsiveness/scripts/soledad_sync.py b/client-responsiveness/scripts/soledad_sync.py
new file mode 100644
index 0000000..8c6442f
--- /dev/null
+++ b/client-responsiveness/scripts/soledad_sync.py
@@ -0,0 +1,96 @@
+import os
+import json
+from ConfigParser import ConfigParser
+from leap.soledad.client.api import Soledad
+from twisted.internet import defer, reactor
+from twisted.internet.task import deferLater
+
+
+# get configs from file
+parser = ConfigParser()
+parser.read('defaults.conf')
+
+HOST = parser.get('server', 'host')
+
+UUID = parser.get('client', 'uuid')
+CLIENT_BASEDIR = parser.get('client', 'basedir')
+PASSPHRASE = parser.get('client', 'passphrase')
+
+NUM_DOCS = int(parser.get('sync', 'num_docs'))
+PAYLOAD = parser.get('sync', 'payload')
+AUTH_TOKEN = parser.get('sync', 'auth_token')
+
+STATS_FILE = parser.get('test', 'stats_file')
+
+
+DO_THESEUS = os.environ.get('THESEUS', False)
+
+
+def _get_soledad_instance_from_uuid(uuid, passphrase, basedir, server_url,
+ cert_file, token):
+ secrets_path = os.path.join(basedir, '%s.secret' % uuid)
+ local_db_path = os.path.join(basedir, '%s.db' % uuid)
+ return Soledad(
+ uuid,
+ unicode(passphrase),
+ secrets_path=secrets_path,
+ local_db_path=local_db_path,
+ server_url=server_url,
+ cert_file=cert_file,
+ auth_token=token,
+ defer_encryption=True,
+ syncable=True)
+
+
+def _get_soledad_instance():
+ return _get_soledad_instance_from_uuid(
+ UUID, PASSPHRASE, CLIENT_BASEDIR, HOST, '', AUTH_TOKEN)
+
+s = _get_soledad_instance()
+
+
+def create_docs():
+ global s
+ # get content for docs
+ payload = 'a' * 10
+ if os.path.isfile(PAYLOAD):
+ with open(PAYLOAD, 'r') as f:
+ payload = f.read()
+
+ # create docs
+ cd = []
+ for i in range(NUM_DOCS):
+ cd.append(s.create_doc({'payload': payload}))
+ d = defer.gatherResults(cd)
+
+ d.addCallback(lambda _: s.get_all_docs())
+ d.addCallback(lambda result: "%d docs created, %d docs on db" % (NUM_DOCS, result[0]))
+ #d.addCallback(lambda _: s.close())
+
+ return d
+
+
+def start_sync():
+ global s
+
+ if DO_THESEUS:
+ from theseus import Tracer
+ t = Tracer()
+ t.install()
+
+ def stop_tracing(_):
+ if DO_THESEUS:
+ with open('callgrind.theseus', 'wb') as outfile:
+ t.write_data(outfile)
+ print "STOPPED TRACING, DUMPED IN CALLGRIND.THESEUS<<<<"
+
+ cd = []
+
+ d = s.sync()
+ d.addCallback(stop_tracing)
+
+ return d
+
+def stats():
+ global s
+ return s.sync_stats()
diff --git a/client-responsiveness/scripts/sync_stats.gnuplot b/client-responsiveness/scripts/sync_stats.gnuplot
new file mode 100755
index 0000000..7fdf29a
--- /dev/null
+++ b/client-responsiveness/scripts/sync_stats.gnuplot
@@ -0,0 +1,23 @@
+#!/usr/bin/gnuplot
+
+infile="$0"
+outfile="$1"
+
+# maybe save image file
+if (outfile ne '') \
+ set term png size 1000,400; \
+ set output "./out/sync-stats.png"
+
+# make the graph beautiful
+set title 'Soledad Sync Phases'
+set xtics 10
+set ytics 50
+set grid
+set key outside
+
+# plot!
+plot for [col=2:6] infile using 1:col with linespoints title columnheader
+
+# pause when not saving image file
+if (outfile eq '') \
+ pause -1