-
Notifications
You must be signed in to change notification settings - Fork 549
Web portal: optimize jobs-table. #691
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,7 +23,6 @@ require('datatables.net/js/jquery.dataTables.js'); | |
require('datatables.net-bs/js/dataTables.bootstrap.js'); | ||
require('datatables.net-bs/css/dataTables.bootstrap.css'); | ||
require('datatables.net-plugins/sorting/natural.js'); | ||
require('datatables.net-plugins/sorting/title-numeric.js'); | ||
require('./job-view.component.scss'); | ||
const url = require('url'); | ||
// const moment = require('moment/moment.js'); | ||
|
@@ -155,72 +154,78 @@ const convertGpu = (gpuAttribute) => { | |
} | ||
}; | ||
|
||
const loadJobs = (limit, specifiedVc) => { | ||
loading.showLoading(); | ||
$.ajax({ | ||
url: `${webportalConfig.restServerUri}/api/v1/jobs`, | ||
type: 'GET', | ||
success: (data) => { | ||
if (data.error) { | ||
alert(data.message); | ||
} else { | ||
let displayDataSet = []; | ||
let rowCount = Math.min(data.length, (limit && (/^\+?[0-9][\d]*$/.test(limit))) ? limit : 2000); | ||
for (let i = 0; i < rowCount; i++) { | ||
let vcName = (data[i].virtualCluster) ? data[i].virtualCluster : 'default'; | ||
if (specifiedVc && vcName !== specifiedVc) { | ||
continue; | ||
const loadJobs = (specifiedVc) => { | ||
$('#view-table').html(jobTableComponent({})); | ||
|
||
const $table = $('#job-table') | ||
.on('preXhr.dt', loading.showLoading) | ||
.on('xhr.dt', loading.hideLoading); | ||
|
||
/* Uncomment following lines for simple profiling: | ||
$table.on('preXhr.dt', function () { | ||
console.time('request'); | ||
}).on('xhr.dt', function () { | ||
console.timeEnd('request'); | ||
console.time('process'); | ||
}).on('preDraw.dt', function () { | ||
console.timeEnd('process'); | ||
console.time('draw'); | ||
}).on('draw.dt', function () { | ||
console.timeEnd('draw') | ||
}); | ||
// */ | ||
|
||
table = $table.dataTable({ | ||
'ajax': { | ||
url: `${webportalConfig.restServerUri}/api/v1/jobs`, | ||
type: 'GET', | ||
dataSrc: (data) => { | ||
if (data.error) { | ||
alert(data.message); | ||
} else { | ||
if (specifiedVc) { | ||
return data.filter((job) => specifiedVc === (job.virtualCluster || 'default')) | ||
} else { | ||
return data | ||
} | ||
let hjss = getHumanizedJobStateString(data[i]); | ||
let stopBtnStyle = | ||
(hjss === 'Waiting' || hjss === 'Running') ? | ||
'<button class="btn btn-default btn-sm" onclick="stopJob(\'' + | ||
data[i].name + '\')">Stop</button>': | ||
'<button class="btn btn-default btn-sm" disabled>Stop</button>'; | ||
displayDataSet.push({ | ||
jobName: '<a href="view.html?jobName=' + data[i].name + '">' + data[i].name + '</a>', | ||
userName: data[i].username, | ||
vcName: '<a href="virtual-clusters.html?vcName=' + vcName + '">' + vcName + '</a>', | ||
startTime: '<span title="' + Math.round(data[i].createdTime / 1000) + '"/>' + | ||
convertTime(false, data[i].createdTime), | ||
duration: '<span title="' + getDurationInSeconds(data[i].createdTime, data[i].completedTime) + '"/>' + | ||
convertTime(true, data[i].createdTime, data[i].completedTime), | ||
retries: data[i].retries, | ||
status: convertState(hjss), | ||
stop: stopBtnStyle, | ||
}); | ||
} | ||
$('#view-table').html(jobTableComponent({})); | ||
table = $('#job-table').dataTable({ | ||
'data': displayDataSet, | ||
'columns': [ | ||
{title: 'Job', data: 'jobName'}, | ||
{title: 'User', data: 'userName'}, | ||
{title: 'Virtual Cluster', data: 'vcName'}, | ||
{title: 'Start Time', data: 'startTime'}, | ||
{title: 'Duration', data: 'duration'}, | ||
{title: 'Retries', data: 'retries'}, | ||
{title: 'Status', data: 'status'}, | ||
{title: 'Stop', data: 'stop'}, | ||
], | ||
'scrollY': (($(window).height() - 265)) + 'px', | ||
'lengthMenu': [[20, 50, 100, -1], [20, 50, 100, 'All']], | ||
'order': [[3, 'desc']], | ||
'columnDefs': [ | ||
{type: 'natural', targets: [0, 1, 2, 5, 6]}, | ||
{type: 'title-numeric', targets: [3, 4]}, | ||
], | ||
'deferRender': true, | ||
}).api(); | ||
} | ||
loading.hideLoading(); | ||
}, | ||
error: (xhr, textStatus, error) => { | ||
const res = JSON.parse(xhr.responseText); | ||
alert(res.message); | ||
loading.hideLoading(); | ||
}, | ||
}); | ||
'columns': [ | ||
{title: 'Job', data: 'name', render(name, type) { | ||
if (type !== 'display') return name; | ||
return '<a href="view.html?jobName=' + name + '">' + name + '</a>'; | ||
} }, | ||
{title: 'User', data: 'username'}, | ||
{title: 'Virtual Cluster', data: 'virtualCluster', defaultContent: 'default'}, | ||
{title: 'Start Time', data: 'createdTime', render(createdTime, type) { | ||
if (type !== 'display') return Math.round(createdTime / 1000); | ||
return convertTime(false, createdTime) | ||
}}, | ||
{title: 'Duration', data: null, render({createdTime, completedTime}, type) { | ||
if (type !== 'display') return getDurationInSeconds(createdTime, completedTime); | ||
return convertTime(true, createdTime, completedTime) | ||
} }, | ||
{title: 'Retries', data: 'retries'}, | ||
{title: 'Status', data: null, render: getHumanizedJobStateString }, | ||
{title: 'Stop', data: null, render(job, type) { | ||
let hjss = getHumanizedJobStateString(job); | ||
return (hjss === 'Waiting' || hjss === 'Running') ? | ||
'<button class="btn btn-default btn-sm" onclick="stopJob(\'' + | ||
job.name + '\')">Stop</button>': | ||
'<button class="btn btn-default btn-sm" disabled>Stop</button>'; | ||
} }, | ||
], | ||
'scrollY': (($(window).height() - 265)) + 'px', | ||
'lengthMenu': [[20, 50, 100, -1], [20, 50, 100, 'All']], | ||
'order': [[3, 'desc']], | ||
'columnDefs': [ | ||
{type: 'natural', targets: [0, 1, 2, 5, 6]}, | ||
{type: 'num', targets: [3, 4]}, | ||
], | ||
'deferRender': true, | ||
'autoWidth': false, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does autoWidth mean and what will happen if it is disabled? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When autoWidth is enabled, DataTables will layout all possible rows (which means 350,000 rows in the benchmarks). collect widths of every cell and calculate the most suitable width of each column. When it is disabled, widths of each column will be decided by the browser, based on data in the current page. So this will cause different page have different column widths (but total will remain 100% of table width, which is set explicitly in CSS) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! Sounds good. |
||
}).api(); | ||
}; | ||
|
||
const stopJob = (jobName) => { | ||
|
@@ -372,7 +377,7 @@ $(document).ready(() => { | |
loadJobDetail(query['jobName']); | ||
$('#content-wrapper').css({'overflow': 'auto'}); | ||
} else { | ||
loadJobs(query['limit'], query['vcName']); | ||
loadJobs(query['vcName']); | ||
$('#content-wrapper').css({'overflow': 'hidden'}); | ||
} | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this ‘render’ function play the trick of lazy calculation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly, render function, especially heavy "display" branch will be calculated only when it is needed to render to the page, which runs pageSize times(as well as "autoWidth" is disabled).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Marked and learnt :)