diff --git a/cassandra/deploy.py b/cassandra/deploy.py
index ebfe2b0..aa78b19 100644
--- a/cassandra/deploy.py
+++ b/cassandra/deploy.py
@@ -2,6 +2,7 @@
import argparse
import mmap
import time
+import csv
import itertools
@@ -9,6 +10,7 @@
from ccmlib import common, extension, repository
from ccmlib.node import Node, NodeError, TimeoutError
+
class CustomCluster(Cluster):
def __update_pids(self, started):
for node, p, _ in started:
@@ -38,7 +40,8 @@ def start(self, no_wait=False, verbose=False, wait_for_binary_proto=True,
if os.path.exists(node.logfilename()):
mark = node.mark_log()
- p = node.start(update_pid=False, jvm_args=jvm_args, profile_options=profile_options, verbose=verbose, quiet_start=quiet_start, allow_root=allow_root)
+ p = node.start(update_pid=False, jvm_args=jvm_args, profile_options=profile_options,
+ verbose=verbose, quiet_start=quiet_start, allow_root=allow_root)
# Prior to JDK8, starting every node at once could lead to a
# nanotime collision where the RNG that generates a node's tokens
@@ -48,17 +51,20 @@ def start(self, no_wait=False, verbose=False, wait_for_binary_proto=True,
# [RAYANDREW] modify this
# print('Waiting 10s before starting other node')
- time.sleep(10) # wait 10 seconds before starting other node
+ time.sleep(10) # wait 10 seconds before starting other node
started.append((node, p, mark))
if no_wait:
- time.sleep(2) # waiting 2 seconds to check for early errors and for the pid to be set
+ # waiting 2 seconds to check for early errors and for the pid to be set
+ time.sleep(2)
else:
for node, p, mark in started:
try:
- start_message = "Listening for thrift clients..." if self.cassandra_version() < "2.2" else "Starting listening for CQL clients"
- node.watch_log_for(start_message, timeout=kwargs.get('timeout',60), process=p, verbose=verbose, from_mark=mark)
+ start_message = "Listening for thrift clients..." if self.cassandra_version(
+ ) < "2.2" else "Starting listening for CQL clients"
+ node.watch_log_for(start_message, timeout=kwargs.get(
+ 'timeout', 60), process=p, verbose=verbose, from_mark=mark)
except RuntimeError:
return None
@@ -75,12 +81,13 @@ def start(self, no_wait=False, verbose=False, wait_for_binary_proto=True,
if wait_for_binary_proto:
for node, p, mark in started:
- node.wait_for_binary_interface(process=p, verbose=verbose, from_mark=mark)
+ node.wait_for_binary_interface(
+ process=p, verbose=verbose, from_mark=mark)
extension.post_cluster_start(self)
return started
-
+
def _read_logs(filename, text='Used Memory'):
line = None
@@ -90,27 +97,31 @@ def _read_logs(filename, text='Used Memory'):
return line
+
def _read_logs_2(filename, text='Used Memory'):
with open(filename, 'r') as f:
# memory-map the file, size 0 means whole file
- m = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
- # prot argument is *nix only
+ m = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
+ # prot argument is *nix only
i = m.rfind(b'Used Memory') # search for last occurrence of 'word'
m.seek(i) # seek to the location
line = m.readline() # read to the end of the line
return str(line)
+
def log_parser(args, node_count):
mems = []
for i in range(node_count):
- line = _read_logs(os.path.join(args.cluster_path, args.cluster_name, 'node{}'.format(i + 1), 'logs', 'system.log'))
+ line = _read_logs(os.path.join(
+ args.cluster_path, args.cluster_name, 'node{}'.format(i + 1), 'logs', 'system.log'))
if line is not None:
mem_digits = [int(s) for s in line.split(' ') if s.isdigit()]
mems.append(mem_digits[0])
return mems
+
def deploy_cluster(args, node_count):
cluster = CustomCluster(
path=args.cluster_path,
@@ -120,42 +131,58 @@ def deploy_cluster(args, node_count):
return cluster
+
def stop_remove_cluster(cluster):
cluster.stop()
cluster.remove()
+
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='[Cassandra] - Memory Reader')
- parser.add_argument('--node_count', '-nc', default=5, type=int, help='Cassandra Node Count')
- parser.add_argument('--cassandra_dir', '-cd', default='/mnt/extra/cassandra', help='cassandra source dir')
- parser.add_argument('--cluster_name', '-cn', default='test', help='cluster name')
- parser.add_argument('--cluster_path', '-cp', default='/mnt/extra/working', help='ccm conf dir')
+ parser.add_argument('--node_count', '-nc', default=5,
+ type=int, help='Cassandra Node Count')
+ parser.add_argument('--cassandra_dir', '-cd',
+ default='/mnt/extra/cassandra', help='cassandra source dir')
+ parser.add_argument('--cluster_name', '-cn',
+ default='test', help='cluster name')
+ parser.add_argument('--cluster_path', '-cp',
+ default='/mnt/extra/working', help='ccm conf dir')
args = parser.parse_args()
- for node_count in range(-5, args.node_count - 5, 5):
- print('Starting Cluster consists of {} nodes'.format(node_count + 10))
- cluster = deploy_cluster(args, node_count + 10)
+ # result = []
- print('Delay about 1 minute before trying to read memory logs')
- time.sleep(60)
+ with open('result.csv', mode='w') as csv_file:
+ writer = csv.DictWriter(csv_file, fieldnames=['nodes', 'mems'])
+ writer.writeheader()
- print('Start reading the logs')
+ for node_count in range(10, args.node_count + 10, 10):
+ print('Starting Cluster consists of {} nodes'.format(node_count))
+ cluster = deploy_cluster(args, node_count)
- mems = []
+ print('Delay about 1 minute before trying to read memory logs')
+ time.sleep(60)
- while True:
- mems = log_parser(args, node_count + 10)
- time.sleep(2)
- if len(mems) == (node_count + 10):
- break
+ print('Start reading the logs')
+
+ mems = []
+
+ while True:
+ mems = log_parser(args, node_count)
+ time.sleep(2)
+ if len(mems) == node_count:
+ break
+
+ total_mems = sum(mems)
+ print('List of mem used ', mems)
+ print('Total memory used for {} nodes is : {} MB'.format(
+ node_count, total_mems))
- print('List of mem used ', mems)
- print('Total memory used for {} nodes is : {} MB'.format(node_count + 10, sum(mems)))
+ writer.writerow({'nodes': node_count, 'mems': total_mems})
- print('Stopping and Remove Cluster')
- stop_remove_cluster(cluster)
+ print('Stopping and Remove Cluster')
+ stop_remove_cluster(cluster)
- print('Delaying 10 secs before spawning another cluster\n')
- time.sleep(10)
\ No newline at end of file
+ print('Delaying 10 secs before spawning another cluster\n')
+ time.sleep(10)
diff --git a/cassandra/log_100.txt b/cassandra/log_100.txt
new file mode 100644
index 0000000..e9e11ff
--- /dev/null
+++ b/cassandra/log_100.txt
@@ -0,0 +1,82 @@
+Starting Cluster consists of 10 nodes
+/usr/local/lib/python3.4/dist-packages/ccmlib/node.py:1501: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.
+ data = yaml.load(f)
+Delay about 1 minute before trying to read memory logs
+Start reading the logs
+List of mem used [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
+Total memory used for 10 nodes is : 10 MB
+Stopping and Remove Cluster
+Delaying 10 secs before spawning another cluster
+
+Starting Cluster consists of 20 nodes
+Delay about 1 minute before trying to read memory logs
+Start reading the logs
+List of mem used [2, 1, 2, 2, 1, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2]
+Total memory used for 20 nodes is : 34 MB
+Stopping and Remove Cluster
+Delaying 10 secs before spawning another cluster
+
+Starting Cluster consists of 30 nodes
+Delay about 1 minute before trying to read memory logs
+Start reading the logs
+List of mem used [2, 2, 1, 2, 1, 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2]
+Total memory used for 30 nodes is : 54 MB
+Stopping and Remove Cluster
+Delaying 10 secs before spawning another cluster
+
+Starting Cluster consists of 40 nodes
+Delay about 1 minute before trying to read memory logs
+Start reading the logs
+List of mem used [2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2]
+Total memory used for 40 nodes is : 74 MB
+Stopping and Remove Cluster
+Delaying 10 secs before spawning another cluster
+
+Starting Cluster consists of 50 nodes
+Delay about 1 minute before trying to read memory logs
+Start reading the logs
+List of mem used [2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
+Total memory used for 50 nodes is : 96 MB
+Stopping and Remove Cluster
+Delaying 10 secs before spawning another cluster
+
+Starting Cluster consists of 60 nodes
+Delay about 1 minute before trying to read memory logs
+Start reading the logs
+List of mem used [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2]
+Total memory used for 60 nodes is : 117 MB
+Stopping and Remove Cluster
+Delaying 10 secs before spawning another cluster
+
+Starting Cluster consists of 70 nodes
+Delay about 1 minute before trying to read memory logs
+Start reading the logs
+List of mem used [2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
+Total memory used for 70 nodes is : 136 MB
+Stopping and Remove Cluster
+Delaying 10 secs before spawning another cluster
+
+Starting Cluster consists of 80 nodes
+Delay about 1 minute before trying to read memory logs
+Start reading the logs
+List of mem used [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
+Total memory used for 80 nodes is : 155 MB
+Stopping and Remove Cluster
+Delaying 10 secs before spawning another cluster
+
+Starting Cluster consists of 90 nodes
+Delay about 1 minute before trying to read memory logs
+Start reading the logs
+List of mem used [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
+Total memory used for 90 nodes is : 176 MB
+Stopping and Remove Cluster
+Delaying 10 secs before spawning another cluster
+
+Starting Cluster consists of 100 nodes
+Delay about 1 minute before trying to read memory logs
+Start reading the logs
+List of mem used [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2]
+Total memory used for 100 nodes is : 199 MB
+Stopping and Remove Cluster
+Delaying 10 secs before spawning another cluster
+
diff --git a/cassandra/result.csv b/cassandra/result.csv
new file mode 100644
index 0000000..95a9390
--- /dev/null
+++ b/cassandra/result.csv
@@ -0,0 +1,11 @@
+nodes,mems
+10,10
+20,34
+30,54
+40,74
+50,96
+60,117
+70,136
+80,155
+90,176
+100,199
diff --git a/test.csv b/test.csv
new file mode 100644
index 0000000..289f3bd
--- /dev/null
+++ b/test.csv
@@ -0,0 +1,2 @@
+nodes,mems
+0,1
diff --git a/visualization/README.md b/visualization/README.md
new file mode 100644
index 0000000..0a0df08
--- /dev/null
+++ b/visualization/README.md
@@ -0,0 +1,21 @@
+# Visualization Memory Usage
+
+This project uses matplotlib to plot memory usage of distributed systems
+
+## Distributed Systems
+
+- [x] Cassandra
+- [x] HDFS
+- [ ] HBase
+- [ ] Tensorflow Distributed
+- [ ] ...
+
+## Running
+
+```bash
+jupyter lab
+```
+
+## Results
+
+![mem-usages](plot.png)
diff --git a/visualization/Visualization.ipynb b/visualization/Visualization.ipynb
new file mode 100644
index 0000000..86608f0
--- /dev/null
+++ b/visualization/Visualization.ipynb
@@ -0,0 +1,293 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Populating the interactive namespace from numpy and matplotlib\n"
+ ]
+ }
+ ],
+ "source": [
+ "# This line configures matplotlib to show figures embedded in the notebook, \n",
+ "# instead of poping up a new window. More about that later. \n",
+ "%pylab inline"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%matplotlib inline"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from pylab import *\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "from scipy.interpolate import interp1d\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "distributed_systems = ['cassandra', 'hdfs']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = pd.read_csv('./data.csv')\n",
+ "df = df.set_index('nodes')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " cassandra | \n",
+ " hdfs | \n",
+ "
\n",
+ " \n",
+ " nodes | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 10 | \n",
+ " 10 | \n",
+ " 26 | \n",
+ "
\n",
+ " \n",
+ " 20 | \n",
+ " 34 | \n",
+ " 46 | \n",
+ "
\n",
+ " \n",
+ " 30 | \n",
+ " 54 | \n",
+ " 66 | \n",
+ "
\n",
+ " \n",
+ " 40 | \n",
+ " 74 | \n",
+ " 89 | \n",
+ "
\n",
+ " \n",
+ " 50 | \n",
+ " 96 | \n",
+ " 109 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " cassandra hdfs\n",
+ "nodes \n",
+ "10 10 26\n",
+ "20 34 46\n",
+ "30 54 66\n",
+ "40 74 89\n",
+ "50 96 109"
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Int64Index([10, 20, 30, 40, 50, 60, 70, 80, 90, 100], dtype='int64', name='nodes')"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df.index"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Text(0, 0.5, 'Memory (MB)')"
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "