demo html/css/js modifications, web service and worker web service
This commit is contained in:
parent
4ce5751c11
commit
7f45cf12bc
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,3 +10,4 @@ memgraph
|
|||||||
*~
|
*~
|
||||||
*.pyc
|
*.pyc
|
||||||
*.breakpoint
|
*.breakpoint
|
||||||
|
*.session.yaml
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
|
font-family: GillSans, Calibri, Trebuchet, sans-serif;
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.w100 {
|
.w100 {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
width: 90%;
|
||||||
|
color: #007FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror {
|
.CodeMirror {
|
||||||
@ -15,3 +21,15 @@ body {
|
|||||||
svg, text {
|
svg, text {
|
||||||
font-size: 28;
|
font-size: 28;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
background-color: #007FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:hover {
|
||||||
|
background-color: #007FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:focus {
|
||||||
|
background-color: #007FFF;
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
<link rel="stylesheet" href="demo.css">
|
<link rel="stylesheet" href="demo.css">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
|
||||||
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="cypher/codemirror.css">
|
<link rel="stylesheet" href="cypher/codemirror.css">
|
||||||
<link rel="stylesheet" href="cypher/neo.css">
|
<link rel="stylesheet" href="cypher/neo.css">
|
||||||
|
|
||||||
@ -14,17 +15,28 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
<!-- title row -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="valign-wrapper">
|
<div class="valign-wrapper">
|
||||||
<h1 class="valign center w100">Memgraph Benchmark</h1>
|
<h1 class="valign center title">Memgraph Benchmark</h1>
|
||||||
|
<span>
|
||||||
|
<button id="running-button"
|
||||||
|
class="btn waves-effect waves-light"
|
||||||
|
type="submit" name="action">
|
||||||
|
Start
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- neo4j cards -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s2">
|
<div class="col s2">
|
||||||
<div id="q1" class="card">
|
<div id="q-0-0" class="card">
|
||||||
<div class="qps valign-wrapper">
|
<div class="qps valign-wrapper">
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<h3 id="text" class="valign center w100">25734</h3>
|
<h3 id="text" class="valign center w100">0</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<canvas id="gauge" width="150" height="60"
|
<canvas id="gauge" width="150" height="60"
|
||||||
@ -33,10 +45,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
||||||
</div>
|
</div>
|
||||||
<div id="q2" class="card">
|
<div id="q-0-1" class="card">
|
||||||
<div class="qps valign-wrapper">
|
<div class="qps valign-wrapper">
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<h3 id="text" class="valign center w100">25734</h3>
|
<h3 id="text" class="valign center w100">0</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<canvas id="gauge" width="150" height="60"
|
<canvas id="gauge" width="150" height="60"
|
||||||
@ -45,10 +57,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
||||||
</div>
|
</div>
|
||||||
<div id="q3" class="card">
|
<div id="q-0-2" class="card">
|
||||||
<div class="qps valign-wrapper">
|
<div class="qps valign-wrapper">
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<h3 id="text" class="valign center w100">25734</h3>
|
<h3 id="text" class="valign center w100">0</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<canvas id="gauge" width="150" height="60"
|
<canvas id="gauge" width="150" height="60"
|
||||||
@ -57,10 +69,22 @@
|
|||||||
</div>
|
</div>
|
||||||
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
||||||
</div>
|
</div>
|
||||||
<div id="q4" class="card">
|
<div id="q-0-3" class="card">
|
||||||
<div class="qps valign-wrapper">
|
<div class="qps valign-wrapper">
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<h3 id="text" class="valign center w100">25734</h3>
|
<h3 id="text" class="valign center w100">0</h3>
|
||||||
|
</div>
|
||||||
|
<div class="col s6">
|
||||||
|
<canvas id="gauge" width="150" height="60"
|
||||||
|
class="valign center"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
||||||
|
</div>
|
||||||
|
<div id="q-0-4" class="card">
|
||||||
|
<div class="qps valign-wrapper">
|
||||||
|
<div class="col s6">
|
||||||
|
<h3 id="text" class="valign center w100">0</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<canvas id="gauge" width="150" height="60"
|
<canvas id="gauge" width="150" height="60"
|
||||||
@ -70,20 +94,24 @@
|
|||||||
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- the graph -->
|
||||||
<div class="col s8">
|
<div class="col s8">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div id="chart" style="height: 600px;">
|
<div id="chart" style="height: 750px;">
|
||||||
<svg></svg>
|
<svg></svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- memgraph cards -->
|
||||||
<div class="col s2">
|
<div class="col s2">
|
||||||
<div id="q5" class="card">
|
<div id="q-1-0" class="card">
|
||||||
<div class="qps valign-wrapper">
|
<div class="qps valign-wrapper">
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<h3 id="text" class="valign center w100">25734</h3>
|
<h3 id="text" class="valign center w100">0</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<canvas id="gauge" width="150" height="60"
|
<canvas id="gauge" width="150" height="60"
|
||||||
@ -92,10 +120,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
||||||
</div>
|
</div>
|
||||||
<div id="q6" class="card">
|
<div id="q-1-1" class="card">
|
||||||
<div class="qps valign-wrapper">
|
<div class="qps valign-wrapper">
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<h3 id="text" class="valign center w100">25734</h3>
|
<h3 id="text" class="valign center w100">0</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<canvas id="gauge" width="150" height="60"
|
<canvas id="gauge" width="150" height="60"
|
||||||
@ -104,10 +132,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
||||||
</div>
|
</div>
|
||||||
<div id="q7" class="card">
|
<div id="q-1-2" class="card">
|
||||||
<div class="qps valign-wrapper">
|
<div class="qps valign-wrapper">
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<h3 id="text" class="valign center w100">25734</h3>
|
<h3 id="text" class="valign center w100">0</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<canvas id="gauge" width="150" height="60"
|
<canvas id="gauge" width="150" height="60"
|
||||||
@ -116,10 +144,22 @@
|
|||||||
</div>
|
</div>
|
||||||
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
||||||
</div>
|
</div>
|
||||||
<div id="q8" class="card">
|
<div id="q-1-3" class="card">
|
||||||
<div class="qps valign-wrapper">
|
<div class="qps valign-wrapper">
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<h3 id="text" class="valign center w100">25734</h3>
|
<h3 id="text" class="valign center w100">0</h3>
|
||||||
|
</div>
|
||||||
|
<div class="col s6">
|
||||||
|
<canvas id="gauge" width="150" height="60"
|
||||||
|
class="valign center"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<textarea id="query">MATCH (n:Person) RETURN n</textarea>
|
||||||
|
</div>
|
||||||
|
<div id="q-1-4" class="card">
|
||||||
|
<div class="qps valign-wrapper">
|
||||||
|
<div class="col s6">
|
||||||
|
<h3 id="text" class="valign center w100">0</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="col s6">
|
<div class="col s6">
|
||||||
<canvas id="gauge" width="150" height="60"
|
<canvas id="gauge" width="150" height="60"
|
||||||
|
@ -90,46 +90,81 @@
|
|||||||
this.gauge.set(value);
|
this.gauge.set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
set(value) {
|
set_value(value) {
|
||||||
this.text.set(value);
|
this.text.set(value);
|
||||||
this.gauge.set(value);
|
this.gauge.set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_query(query) {
|
||||||
|
this.query.set(query);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var put_new_line_mod_2 = function(array) {
|
||||||
|
let join_array = array.map(function(o, i) {
|
||||||
|
if (i % 2 == 0)
|
||||||
|
return ' ';
|
||||||
|
else
|
||||||
|
return '\n';
|
||||||
|
});
|
||||||
|
join_array.pop();
|
||||||
|
return array.map(function(v,i) {
|
||||||
|
return [v, join_array[i]];
|
||||||
|
}).reduce(function(a,b) {
|
||||||
|
return a.concat(b);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var queries = [
|
||||||
|
"CREATE (n{id:@}) RETURN n",
|
||||||
|
"MATCH (n{id:#}),(m{id:#}) CREATE (n)-[r:test]->(m) RETURN r",
|
||||||
|
"MATCH (n{id:#}) SET n.prop=^ RETURN n",
|
||||||
|
"MATCH (n{id:#}) RETURN n",
|
||||||
|
"MATCH (n{id:#})-[r]->(m) RETURN count(r)"
|
||||||
|
];
|
||||||
|
|
||||||
|
$("#running-button").click(function() {
|
||||||
|
running = !running;
|
||||||
|
if (running) {
|
||||||
|
$(this).text('STOP');
|
||||||
|
run();
|
||||||
|
updateGraph();
|
||||||
|
}
|
||||||
|
if (!running)
|
||||||
|
$(this).text('START');
|
||||||
|
});
|
||||||
|
|
||||||
// counters init
|
// counters init
|
||||||
|
let running = false;
|
||||||
let value = 0;
|
let value = 0;
|
||||||
let maxQps = 15000;
|
let maxQps = 15000;
|
||||||
|
|
||||||
let card1 = new QueryCard($('#q1')[0], maxQps);
|
// cards init
|
||||||
let card2 = new QueryCard($('#q2')[0], maxQps);
|
let neo4jCards = [];
|
||||||
let card3 = new QueryCard($('#q3')[0], maxQps);
|
let memgraphCards = [];
|
||||||
let card4 = new QueryCard($('#q4')[0], maxQps);
|
queries.forEach(function(query, i) {
|
||||||
let card5 = new QueryCard($('#q5')[0], maxQps);
|
query = put_new_line_mod_2(query.split(" ")).join('');
|
||||||
let card6 = new QueryCard($('#q6')[0], maxQps);
|
neo4jCards.push(new QueryCard($('#q-0-' + i.toString())[0], maxQps));
|
||||||
let card7 = new QueryCard($('#q7')[0], maxQps);
|
neo4jCards[i].set_query(query);
|
||||||
let card8 = new QueryCard($('#q8')[0], maxQps);
|
memgraphCards.push(new QueryCard($('#q-1-' + i.toString())[0], maxQps));
|
||||||
|
memgraphCards[i].set_query(query);
|
||||||
|
});
|
||||||
|
|
||||||
// counters update
|
// cards update
|
||||||
function run() {
|
function run() {
|
||||||
|
if (!running)
|
||||||
|
return;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
value += 10;
|
value += 10;
|
||||||
|
|
||||||
if(value >= maxQps)
|
if(value >= maxQps)
|
||||||
value = 0;
|
value = 0;
|
||||||
|
queries.forEach(function(query, i) {
|
||||||
card1.set(value);
|
neo4jCards[i].set_value(Math.round(1000 + Math.random() * 3000));
|
||||||
card2.set(value);
|
memgraphCards[i].set_value(Math.round(7000 + Math.random() * 7000));
|
||||||
card3.set(value);
|
});
|
||||||
card4.set(value);
|
|
||||||
card5.set(value);
|
|
||||||
card6.set(value);
|
|
||||||
card7.set(value);
|
|
||||||
card8.set(value);
|
|
||||||
|
|
||||||
run();
|
run();
|
||||||
}, 20);
|
}, 1000);
|
||||||
}
|
}
|
||||||
run();
|
|
||||||
|
|
||||||
// graph init
|
// graph init
|
||||||
var data = [];
|
var data = [];
|
||||||
@ -148,7 +183,7 @@
|
|||||||
|
|
||||||
chart.yAxis
|
chart.yAxis
|
||||||
.axisLabel('QPS')
|
.axisLabel('QPS')
|
||||||
.tickFormat(d3.format(',r'));
|
.tickFormat(d3.format('f'));
|
||||||
|
|
||||||
chartData = d3.select('#chart svg')
|
chartData = d3.select('#chart svg')
|
||||||
.datum(data);
|
.datum(data);
|
||||||
@ -162,6 +197,8 @@
|
|||||||
// graph update
|
// graph update
|
||||||
let x = 0;
|
let x = 0;
|
||||||
function updateGraph() {
|
function updateGraph() {
|
||||||
|
if (!running)
|
||||||
|
return;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
x += 1;
|
x += 1;
|
||||||
if (x > 100)
|
if (x > 100)
|
||||||
@ -185,6 +222,5 @@
|
|||||||
updateGraph();
|
updateGraph();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
updateGraph();
|
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
34
demo/web_service.py
Normal file
34
demo/web_service.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from flask import Flask
|
||||||
|
|
||||||
|
|
||||||
|
class WebService(Flask):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
self.server = Flask(__name__)
|
||||||
|
|
||||||
|
def add_route(self, route, code_method, http_method):
|
||||||
|
'''
|
||||||
|
Registers URL rule
|
||||||
|
|
||||||
|
:param route: str, route string
|
||||||
|
:param object_method: object method responsible for the
|
||||||
|
request handling
|
||||||
|
:param http_method: name of http method
|
||||||
|
'''
|
||||||
|
self.server.add_url_rule(route, '%s_%s' % (route, http_method),
|
||||||
|
code_method, methods=[http_method])
|
||||||
|
|
||||||
|
def setup_routes(self):
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
self.add_route('/ping', self.ping, 'GET')
|
||||||
|
|
||||||
|
def ping(self):
|
||||||
|
'''
|
||||||
|
Ping endpoint. Returns 204 HTTP status code.
|
||||||
|
'''
|
||||||
|
return ('', 204)
|
91
demo/worker/worker_web_service.py
Normal file
91
demo/worker/worker_web_service.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import threading
|
||||||
|
from flask import request, jsonify
|
||||||
|
|
||||||
|
from .. import WebService
|
||||||
|
from . import wrapped_client
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class WorkerWebServer(WebService):
|
||||||
|
'''
|
||||||
|
Memgraph worker web server. For now it wraps the flask server.
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
'''
|
||||||
|
Instantiates the flask web server.
|
||||||
|
'''
|
||||||
|
super().__init__()
|
||||||
|
self.params_data = None
|
||||||
|
self.is_simulation_running = False
|
||||||
|
self.stats_data = None
|
||||||
|
self.setup_routes()
|
||||||
|
|
||||||
|
def setup_routes(self):
|
||||||
|
'''
|
||||||
|
Setup all routes.
|
||||||
|
'''
|
||||||
|
super().__init__()
|
||||||
|
self.add_route('/start', self.start, 'POST')
|
||||||
|
self.add_route('/stop', self.stop, 'POST')
|
||||||
|
self.add_route('/stats', self.stats, 'GET')
|
||||||
|
self.add_route('/params', self.params_get, 'GET')
|
||||||
|
self.add_route('/params', self.params_set, 'POST')
|
||||||
|
|
||||||
|
def run_simulation(self):
|
||||||
|
'''
|
||||||
|
If flag is_simulation_running flag is up (True) the executor
|
||||||
|
epoch will be executed. Epochs will be executed until somebody
|
||||||
|
set is_simulation_running flag to Flase.
|
||||||
|
'''
|
||||||
|
log.info('new simulation run')
|
||||||
|
|
||||||
|
while self.is_simulation_running:
|
||||||
|
self.stats_data = wrapped_client(*self.params_data)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
self.is_simulation_running = True
|
||||||
|
t = threading.Thread(target=self.run_simulation, daemon=True)
|
||||||
|
t.start()
|
||||||
|
return ('', 204)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
self.is_simulation_running = False
|
||||||
|
return ('', 204)
|
||||||
|
|
||||||
|
def stats(self):
|
||||||
|
'''
|
||||||
|
Returns the simulation stats. Queries per second.
|
||||||
|
'''
|
||||||
|
if not self.stats_data:
|
||||||
|
return ('', 204)
|
||||||
|
|
||||||
|
return jsonify(self.stats_data)
|
||||||
|
|
||||||
|
def params_get(self):
|
||||||
|
'''
|
||||||
|
Returns simulation parameters.
|
||||||
|
'''
|
||||||
|
return jsonify(self.simulation_params.json_data())
|
||||||
|
|
||||||
|
def params_set(self):
|
||||||
|
'''
|
||||||
|
Sets simulation parameters.
|
||||||
|
'''
|
||||||
|
data = request.get_json()
|
||||||
|
|
||||||
|
param_names = ['host', 'port', 'connections', 'duration', 'queries']
|
||||||
|
|
||||||
|
for param in param_names:
|
||||||
|
if param in data:
|
||||||
|
setattr(self.params_data, param, data[param])
|
||||||
|
|
||||||
|
return self.params_get()
|
Loading…
Reference in New Issue
Block a user