提交 77fd80b4 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!158 add web ui

Merge pull request !158 from gaoruoshu/devui
......@@ -63,12 +63,14 @@ libinstall:
mkdir -p $(DESTDIR)/etc/atuned/rules
mkdir -p $(DESTDIR)/etc/atuned/training
mkdir -p $(DESTDIR)/etc/atuned/classification
mkdir -p $(DESTDIR)/etc/atuned/webserver
mkdir -p $(DESTDIR)$(PREFIX)/lib/atuned/modules
mkdir -p $(DESTDIR)$(PREFIX)/lib/atuned/profiles
mkdir -p $(DESTDIR)$(PREFIX)/lib/atuned/training
mkdir -p $(DESTDIR)$(PREFIX)/share/atuned
mkdir -p $(DESTDIR)$(PREFIX)/$(LIBEXEC)/atuned/scripts
mkdir -p $(DESTDIR)$(PREFIX)/$(LIBEXEC)/atuned/analysis
mkdir -p $(DESTDIR)$(PREFIX)/$(LIBEXEC)/atuned/resources
mkdir -p $(DESTDIR)/var/lib/atuned
mkdir -p $(DESTDIR)/var/run/atuned
mkdir -p $(DESTDIR)/var/atuned
......@@ -86,6 +88,8 @@ libinstall:
chmod -R 750 $(DESTDIR)$(PREFIX)/$(LIBEXEC)/atuned/scripts/
\cp -rf analysis/* $(DESTDIR)$(PREFIX)/$(LIBEXEC)/atuned/analysis/
chmod -R 750 $(DESTDIR)$(PREFIX)/$(LIBEXEC)/atuned/analysis/
\cp -rf resources/* $(DESTDIR)$(PREFIX)/$(LIBEXEC)/atuned/resources/
chmod -R 750 $(DESTDIR)$(PREFIX)/$(LIBEXEC)/atuned/resources/
\cp -rf profiles/* $(DESTDIR)$(PREFIX)/lib/atuned/profiles/
chmod -R 640 $(DESTDIR)$(PREFIX)/lib/atuned/profiles/
@echo "END INSTALL A-Tune"
......
......@@ -61,7 +61,7 @@ class Optimizer(Resource):
x_ref = args.get("x_ref")
y_ref = args.get("y_ref")
result = {}
engine = optimizer.Optimizer(task_id, args["knobs"], child_conn, engine=args.get("engine"),
engine = optimizer.Optimizer(task_id, args["knobs"], child_conn, args["prj_name"], engine=args.get("engine"),
max_eval=args.get("max_eval"),
n_random_starts=args.get("random_starts"),
x0=x_ref, y0=y_ref, split_count=args.get("split_count"),
......
......@@ -40,6 +40,8 @@ OPTIMIZER_POST_PARSER.add_argument('sel_feature', type=bool, location='json',
help="enable the feature selection or not")
OPTIMIZER_POST_PARSER.add_argument('noise', type=float, location='json',
help="the noise can not be null")
OPTIMIZER_POST_PARSER.add_argument('prj_name', type=str, location='json',
help="prj_name cannot be null")
OPTIMIZER_PUT_PARSER = reqparse.RequestParser()
OPTIMIZER_PUT_PARSER.add_argument('iterations', type=int, required=True,
......
......@@ -42,3 +42,12 @@ def extract_file(file_path, target_path):
tar.close()
res_path = file_path.rpartition('-')[0]
return res_path
def add_data_to_file(data, mode, filename):
"""write tuning result to file"""
path = "/etc/atuned/webserver/" + filename + ".txt"
file_handle = open(path, mode)
file_handle.write(str(data))
file_handle.write("\n")
file_handle.close()
......@@ -20,6 +20,7 @@ import numbers
import multiprocessing
import collections
import numpy as np
import analysis.engine.utils.utils as utils
from sklearn.linear_model import Lasso
from sklearn.preprocessing import StandardScaler
......@@ -38,11 +39,12 @@ LOGGER = logging.getLogger(__name__)
class Optimizer(multiprocessing.Process):
"""find optimal settings and generate optimized profile"""
def __init__(self, name, params, child_conn, engine="bayes", max_eval=50, sel_feature=False,
def __init__(self, name, params, child_conn, prj_name, engine="bayes", max_eval=50, sel_feature=False,
x0=None, y0=None, n_random_starts=20, split_count=5, noise=0.00001 ** 2):
super(Optimizer, self).__init__(name=name)
self.knobs = params
self.child_conn = child_conn
self.project_name = prj_name
self.engine = engine
self.noise = noise
self.max_eval = int(max_eval)
......@@ -236,6 +238,12 @@ class Optimizer(multiprocessing.Process):
performance = []
labels = []
estimator = None
parameters = ""
for knob in self.knobs:
parameters += knob["name"] + ","
utils.add_data_to_file(parameters[:-1], "w", self.project_name)
try:
if self.engine == 'random' or self.engine == 'forest' or \
self.engine == 'gbrt' or self.engine == 'bayes' or self.engine == 'extraTrees':
......@@ -304,6 +312,15 @@ class Optimizer(multiprocessing.Process):
LOGGER.info("next_y: %s", next_y)
ret = optimizer.tell(next_x, next_y)
LOGGER.info("finish (ref_x, ref_y) tell")
data = ""
for element in next_x:
data += str(element) + ","
data += str(abs(next_y))
utils.add_data_to_file(data, "a", self.project_name)
utils.add_data_to_file("END", "a", self.project_name)
elif self.engine == 'abtest':
abtuning_manager = ABtestTuningManager(self.knobs, self.child_conn,
self.split_count)
......
......@@ -33,6 +33,7 @@ type OptimizerPostBody struct {
SplitCount int32 `json:"split_count"`
Noise float64 `json:"noise"`
SelFeature bool `json:"sel_feature"`
PrjName string `json:"prj_name"`
}
// Knob body store the tuning properties
......
......@@ -135,6 +135,7 @@ func (o *Optimizer) createOptimizerTask(ch chan *PB.TuningMessage, iters int32,
optimizerBody.SplitCount = o.SplitCount
optimizerBody.Noise = config.Noise
optimizerBody.Knobs = make([]models.Knob, 0)
optimizerBody.PrjName = o.Prj.Project
for _, item := range o.Prj.Object {
if item.Info.Skip {
continue
......
/*
Copyright (c) 2019 Huawei Technologies Co., Ltd.
A-Tune is licensed under the Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
PURPOSE.
See the Mulan PSL v2 for more details.
Create: 2020-08-17
*/
/* left side bar */
.sidebar-div {
position: relative;
top: 0;
left: 0;
height: 100vh;
width: 300px;
background: linear-gradient(white, midnightblue);
/* z-index: 200;*/
box-shadow: 3px 0 5px 0 #000;
}
/* logo */
.logo-div {
position: relative;
padding: 3px 5px;
}
.logo-div:before {
content: "";
position: absolute;
left: 15px;
right: 15px;
top: auto;
bottom: 0;
height: 1px;
width: 270px;
background-color: grey;
}
/* side bar wrapper */
.sidebar-wrapper-div {
position: relative;
height: calc(100vh - 200px);
overflow: auto;
width: 300px;
z-index: 4;
}
.nav {
list-style: none;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
padding-left: 0;
margin-bottom: 0;
margin-top: 20px;
display: block;
}
.nav li {
height: 60px;
text-align: center;
font-family: sans-serif;
font-size: 17px;
position: relative;
overflow: hidden;
vertical-align: middle;
}
.nav li:hover {
border-radius: 40px;
background: #f5f5dc;
width: 260px;
margin: auto;
border: none;
opacity: .5;
}
.nav li.active {
border-radius: 40px;
background: #f0f8ff;
width: 260px;
margin: auto;
border: none;
}
.nav a {
color: #000;
height: inherit;
text-decoration: none;
vertical-align: middle;
}
.nav p {
margin: 8px;
height: 40px;
padding: 0;
vertical-align: middle;
}
/* main part */
.main-panel {
position: fixed;
top: 0;
left: 300px;
height: 100vh;
width: -webkit-fill-available;
}
/* top bar */
.nav-bar-div {
margin: 0 auto 60px;
}
.nav-bar {
height: 60px;
width: calc(100% - 300px);
position: fixed;
background: #f0ffff;
z-index: 100;
/* box-shadow: 0 3px 5px 0 black;*/
}
.nav-bar-right {
justify-content: flex-end;
-webkit-box-pack: end;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
}
.nav-bar-right input {
font-size: 14px;
padding: 9px;
border-radius: 25px;
outline: none;
}
.search-bar {
opacity: .5;
font-size: 14px;
-webkit-font-smoothing: antialiased;
padding: 9px;
width: 250px;
}
.search-icon {
height: 22px;
vertical-align: middle;
cursor: pointer;
}
.nav-bar-right ul {
list-style: none;
flex-direction: row;
display: flex;
margin: auto 0;
padding: 3px 0 0 5px;
}
.nav-bar-right li {
padding: 0 20px 0 0;
}
.nav-bar-right a {
color: #000;
text-decoration: none;
}
.nav-bar-right span:hover {
opacity: .3;
}
.nav-bar-right a:hover {
opacity: .3;
}
.nav-dropdown:before {
display: inline-block;
position: absolute;
width: 0;
height: 0;
vertical-align: middle;
content: "";
top: -5px;
left: auto;
right: 20px;
color: #FFF;
border-bottom: .4em solid;
border-right: .4em solid transparent;
border-left: .4em solid transparent;
border-radius: 5px;
}
.dropdown-item {
margin: 5px;
padding: 2px 5px;
}
.open > .dropdown-menu {
display: grid;
}
/* main page */
#tuning-chart {
overflow-y: scroll;
height: calc(100vh - 60px);
}
.performance-chart {
width: 500px;
height: 400px;
float: left;
display: inline;
}
/**
* @file help function for html
*
* Copyright (c) 2019 Huawei Technologies Co., Ltd.
* A-Tune is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v2 for more details.
* Create: 2020-08-17
*/
var socket;
var line;
var projectName;
var intervalId;
var timestamp;
function deleteOld() {
var container = document.getElementById('tuning-chart');
while (container.hasChildNodes()) {
container.removeChild(container.firstChild);
}
}
function initNdiv(list, name) {
list.push('performance');
list.push('best performance');
var container = window.document.getElementById('tuning-chart');
list.forEach(function (item) {
var br = document.createElement('br');
container.appendChild(br);
var div = document.createElement('div');
div.id = 'chart-' + item;
div.className = 'performance-chart';
container.appendChild(div);
var chart = echarts.init(document.getElementById(div.id));
var option = {
title: {
text: item
},
tooltip: {},
xAxis: {
name: 'times',
data: []
},
yAxis: {
name: 'value',
},
series: [{
name: item,
type: 'line',
data: []
}]
};
chart.setOption(option);
});
projectName = name;
}
function updateChart(name, times, value) {
console.log(name, '-', times, '-', value);
var id = 'chart-' + name;
var chart = echarts.init(document.getElementById(id));
var oldData = chart.getOption().series[0].data;
var oldX = chart.getOption().xAxis[0].data;
for (var i in times) {
oldX.push(times[i]);
oldData.push(value[i]);
}
chart.setOption({
xAxis: {data: oldX},
series: [{data: oldData}]
});
}
function appendPrjList(list, timestamp) {
var container = document.getElementById('tuning-chart');
console.log(list);
var h4 = document.createElement('h4');
h4.appendChild(document.createTextNode('Project:'));
container.appendChild(h4);
if (list.length === 0) {
h4 = document.createElement('h4');
h4.appendChild(document.createTextNode('No tuning project'));
container.appendChild(h4);
return;
}
var ul = document.createElement('ul');
container.appendChild(ul);
for (var i in list) {
var li = document.createElement('li');
li.id = 'project-name-' + list[i];
li.appendChild(document.createTextNode(list[i]));
ul.appendChild(li);
li.style.cursor = 'pointer';
li.onclick = function () {
socket.emit('inital_chart', {'prj_name': list[i]}, timestamp, namespace = '/tuning');
};
}
}
function updateChartInit(nameList, lineNum, value) {
var lineList = [];
nameList.push('performance');
console.log(value, value.length);
for (var i in value[0]) {
lineList[i] = parseInt(lineNum, 10) + parseInt(i, 10);
}
for (var i in value) {
updateChart(nameList[i], lineList, value[i]);
}
}
function updateInterval() {
socket.emit('update_chart', projectName, line, timestamp, namespace = '/tuning');
}
function setSocket() {
$(document).ready(function () {
console.log((new Date()).valueOf());
var namespace = '/tuning';
socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + namespace);
timestamp = (new Date()).valueOf();
socket.emit('show_page', timestamp, namespace = '/tuning');
line = 0;
socket.on('get_all_tuning_list', function (res) {
if (res['timestamp'] === timestamp) {
deleteOld();
appendPrjList(res['prj_list'], res['timestamp']);
}
});
socket.on('inital_chart', function (res) {
if (res['timestamp'] === timestamp) {
deleteOld();
initNdiv(res['graph_list'], res['prj_name']);
intervalId = setInterval(updateInterval, 2000);
}
});
socket.on('update_chart', function (res) {
if (res['timestamp'] === timestamp) {
line = res['next_line'];
if (line === -1) {
window.clearInterval(intervalId);
}
updateChartInit(res['name'], res['num'] + 1, res['value']);
}
});
socket.on('file_removed', function (res) {
if (res['timestamp'] === timestamp) {
window.clearInterval(intervalId);
var container = document.getElementById('tuning-chart');
container.appendChild(document.createElement('br'));
var h4 = document.createElement('h4');
h4.appendChild(document.createTextNode('File ' + res['prj_name'] + ' has been delete'));
container.appendChild(h4);
}
});
});
}
<!DOCTYPE html>
<!--
Copyright (c) 2019 Huawei Technologies Co., Ltd.
A-Tune is licensed under the Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
PURPOSE.
See the Mulan PSL v2 for more details.
Create: 2020-08-17
-->
<html>
<head>
<meta charset="UTF-8">
<title>Tuning</title>
<meta http-equiv="Expires" content="0">
<meta http-equiv="Pragma" content="no-cache, must-revalidate">
<meta http-equiv="Cache-control" content="no-cache">
<meta http-equiv="Cache" content="no-cache">
<script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script type="text/javascript" src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript" src="//cdn.bootcss.com/socket.io/1.5.1/socket.io.min.js"></script>
<script type="text/javascript" src="./static/js/temp.js"></script>
<link type="text/css" href="./static/css/style.css" rel="stylesheet">
</head>
<body class="" style="margin:0; height: 100%; width: 100%">
<div class="wrapper" style="height: 100%">
<div class="sidebar-div">
<div class="logo-div">
<img src="A-Tune-logo.png" style="padding: 5px; height:52px; margin: 0 0 0 20px;">
</div>
<div class="sidebar-wrapper-div">
<ul class="nav">
<li class="active" style="">
<a href="#">
<p>Dashboard</p>
</a>
</li>
<li>
<a href="#">
<p>Tuning</p>
</a>
</li>
<li>
<a href="#">
<p>About</p>
</a>
</li>
<li>
<a href="#">
<p>Notifications</p>
</a>
</li>
<li>
<a href="#">
<p>User Profile</p>
</a>
</li>
<li>
<a href="#">
<p>History</p>
</a>
</li>
<li>
<a href="#">
<p>xxxx</p>
</a>
</li>
<li>
<a href="#">
<p>xxxxx</p>
</a>
</li>
</ul>
</div>
</div>
<!---->
<!---->
<div class="main-panel">
<nav class="nav-bar-div">
<div class="nav-bar">
<div class="nav-bar-left">
</div>
<div class="nav-bar-right">
<form style="">
<div class="search-bar">
<input type="text" value="" placeholder="Search...">
<img src="search.png" class="search-icon">
</div>
</form>
<ul class="navbar-nav">
<li>
<a class="nav-lang" href="#">
<p>
<span>LANG</span>
</p>
</a>
</li>
<li class="dropdown">
<a href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<!-- <i class="now-ui-icons location_world"></i>-->
<p>
<span>dropDown</span>
</p>
</a>
<div class="dropdown-menu dropdown-menu-right nav-dropdown" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="#">option 1</a>
<a class="dropdown-item" href="#">option 2</a>
<a class="dropdown-item" href="#">option 3</a>
</div>
</li>
<li>
<a class="nav-user" href="#">
<!-- <i class="now-ui-icons users_single-02"></i>-->
<p>
<span>Account</span>
</p>
</a>
</li>
</ul>
</div>
</div>
</nav>
<div id="tuning-chart"></div>
<script>
setSocket();
</script>
</div>
</div>
</body>
</html>
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Copyright (c) 2019 Huawei Technologies Co., Ltd.
# A-Tune is licensed under the Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
# http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
# PURPOSE.
# See the Mulan PSL v2 for more details.
# Create: 2020-08-17
"""
Web UI initialization
"""
from flask import Flask, render_template
from flask_socketio import SocketIO
import os
import numpy
import logging
APP = Flask(__name__, template_folder='./templates', static_folder='./static')
APP.config['TEMPLATES_AUTO_RELOAD'] = True
APP.jinja_env.auto_reload = True
socketio = SocketIO(APP, async_mode=None)
@APP.route('/tuning')
def index():
"""open tuning page"""
return render_template('tuning.html', async_mode=socketio.async_mode)
@socketio.on('connect', namespace='/tuning')
def init_connect():
"""inital connection"""
return
@socketio.on('show_page', namespace='/tuning')
def show_page(timestamp, _):
"""list all tuning project name on page"""
path = '/etc/atuned/webserver'
filelist = os.listdir(path)
res = []
for each in filelist:
res.append(each.split('.')[0])
socketio.emit('get_all_tuning_list', {'prj_list': res, 'timestamp': timestamp}, namespace='/tuning')
return
@socketio.on('inital_chart', namespace='/tuning')
def inital_tuning_page(message, timestamp, _):
"""inital chart graph for project"""
prj_name = message['prj_name']
path = '/etc/atuned/webserver/' + prj_name + '.txt'
if not os.path.exists(path):
socketio.emit('file_removed', {'prj_name': prj_name, 'timestamp': timestamp}, namespace='/tuning')
return
graph_list = []
with open(path, 'r') as tuning_file:
graph_list = tuning_file.readline()[:-1].split(',')
socketio.emit('inital_chart',
{'graph_list': graph_list, 'prj_name': prj_name, 'timestamp': timestamp},
namespace='/tuning')
@socketio.on('update_chart', namespace='/tuning')
def update_tuning_page(prj_name, num, timestamp, _):
"""get info for chart"""
path = '/etc/atuned/webserver/' + prj_name + '.txt'
if not os.path.exists(path):
socketio.emit('file_removed', {'prj_name': prj_name, 'timestamp': timestamp}, namespace='/tuning')
return
res = []
count = 0
first_line = ''
eof = False
with open(path, 'r') as tuning_file:
first_line = tuning_file.readline()[:-1].split(',')
lines = tuning_file.readlines()
while num + count < len(lines):
if lines[num + count][:-1] == 'END':
eof = True
break
line_list = lines[num + count][:-1].split(',')
res.append(line_list)
count += 1
if count == 5:
break
res = numpy.array(res).T.tolist()
next_line = num + count
if eof:
next_line = -1
socketio.emit('update_chart',
{'name': first_line, 'num': num, 'next_line': next_line, 'value': res, 'timestamp': timestamp},
namespace='/tuning')
if __name__ == '__main__':
socketio.run(APP, host='9.41.51.85', port=10086)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册