172 lines
4.8 KiB
JavaScript
172 lines
4.8 KiB
JavaScript
import React from 'react'
|
|
import { Line, Bar } from 'react-chartjs-2'
|
|
import debounceRender from 'react-debounce-render'
|
|
|
|
import { downloadAsJson } from '../../../lib/json-download/index.js'
|
|
import { datasetTemplates, genOptions, beautifyLabels } from './chartOptions.js'
|
|
|
|
export class Chart extends React.Component {
|
|
render() {
|
|
let { formState, stats, nodeData } = this.props
|
|
let { tolRange, chart } = formState
|
|
tolRange = tolRange || []
|
|
|
|
let labels = beautifyLabels(tolRange)
|
|
// let labels = tolRange.map(x => Math.round(x * 1000) / 1000)
|
|
let datasets = Object.keys(stats).map(name => ({
|
|
...datasetTemplates[name],
|
|
data: stats[name]
|
|
}))
|
|
datasets.push({ ...datasetTemplates.numberOfNodes, data: nodeData })
|
|
let data = { datasets, labels }
|
|
return (
|
|
<div className="component">
|
|
<h2>Chart</h2>
|
|
{chart === 'wasmVsJs' && <WasmVsJsChart data={data} />}
|
|
{chart === 'wasmStack' && <WasmStackChart data={data} />}
|
|
{chart === 'simplifyJSStack' && <JsStackChart data={data} />}
|
|
</div>
|
|
)
|
|
}
|
|
}
|
|
|
|
class WasmVsJsChart extends React.Component {
|
|
constructor(props) {
|
|
super(props)
|
|
this.state = {
|
|
scaleY: 'linear',
|
|
values: 'mean'
|
|
}
|
|
}
|
|
convertDataToHz(data) {
|
|
let datasets = data.datasets
|
|
for (let dataset of datasets.filter(d => d.label !== 'numberOfNodes')) {
|
|
dataset.data = dataset.data.map(mean => 1000 / mean)
|
|
}
|
|
}
|
|
|
|
render() {
|
|
let data = JSON.parse(JSON.stringify(this.props.data)) // deep copy
|
|
let options = genOptions('Wasm vs. JavaScript', false, this.state.scaleY)
|
|
if (this.state.values === 'hz') this.convertDataToHz(data)
|
|
return (
|
|
<>
|
|
<Line
|
|
ref={ref => (this.ref = ref)}
|
|
height={400}
|
|
width={400}
|
|
data={data}
|
|
options={options}
|
|
/>
|
|
<label>Scale Y-Axis</label>
|
|
<select
|
|
name="scaleY"
|
|
value={this.state.scaleY}
|
|
onChange={e => this.setState({ scaleY: e.target.value })}
|
|
>
|
|
<option value="linear">Linear</option>
|
|
<option value="logarithmic">Logarithmic</option>
|
|
</select>
|
|
|
|
<label>Values: </label>
|
|
<select
|
|
name="values"
|
|
value={this.state.values}
|
|
onChange={e => this.setState({ values: e.target.value })}
|
|
>
|
|
<option value="mean">ms per operation (mean)</option>
|
|
<option value="hz">Operations per second (hz)</option>
|
|
</select>
|
|
<button onClick={() => saveChart(this.ref)}>Save chart</button>
|
|
</>
|
|
)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the dataset specified by label
|
|
*/
|
|
function getDataset(data, label) {
|
|
return data.datasets.filter(d => d.label === label)[0]
|
|
}
|
|
|
|
/**
|
|
* Takes three data arrays. Subtracts the values of arr1 and arr2 from whole.
|
|
* This is used for calculating the time of execution in cases where the data
|
|
* transformation is part of the whole operation.
|
|
* Example: subtract storeCoords and loadResult from the whole simplifyWASM
|
|
* operation to get execution time of wasm code.
|
|
*/
|
|
function calculateTimeDelta(whole, arr1, arr2) {
|
|
const safeGet = (arr, idx) => (idx < arr.length ? arr[idx] : 0)
|
|
return whole.map((val, i) => val - (safeGet(arr1, i) + safeGet(arr2, i)))
|
|
}
|
|
|
|
function modifyDataArrays(data, exec, pre, after) {
|
|
if (getDataset(data, exec)) {
|
|
getDataset(data, exec).data = calculateTimeDelta(
|
|
getDataset(data, exec).data,
|
|
getDataset(data, pre).data,
|
|
getDataset(data, after).data
|
|
)
|
|
}
|
|
}
|
|
|
|
class WasmStackChart extends React.Component {
|
|
render() {
|
|
const data = this.props.data
|
|
modifyDataArrays(data, 'simplifyWASM', 'storeCoords', 'loadResult')
|
|
const options = genOptions('Wasm execution', true)
|
|
return (
|
|
<>
|
|
<Bar
|
|
ref={ref => (this.ref = ref)}
|
|
height={400}
|
|
width={400}
|
|
data={data}
|
|
options={options}
|
|
/>
|
|
<button onClick={() => saveChart(this.ref)}>Save chart</button>
|
|
</>
|
|
)
|
|
}
|
|
}
|
|
|
|
class JsStackChart extends React.Component {
|
|
render() {
|
|
const data = this.props.data
|
|
const options = genOptions('SimplifyJS execution', true)
|
|
modifyDataArrays(
|
|
data,
|
|
'origSimplifyWithTransformCase',
|
|
'transformToObjectFormCase',
|
|
'transformToArrayFormCase'
|
|
)
|
|
return (
|
|
<>
|
|
<Bar
|
|
ref={ref => (this.ref = ref)}
|
|
height={400}
|
|
width={400}
|
|
data={data}
|
|
options={options}
|
|
/>
|
|
<button onClick={() => saveChart(this.ref)}>Save chart</button>
|
|
</>
|
|
)
|
|
}
|
|
}
|
|
|
|
export const DebouncedChart = debounceRender(Chart, 300)
|
|
|
|
/**
|
|
* Downloads the chart config as json
|
|
*/
|
|
function saveChart(chartRef) {
|
|
let myChart = chartRef.chartInstance.config
|
|
let config = JSON.stringify(myChart, (key, val) =>
|
|
key === '_meta' ? undefined : val
|
|
)
|
|
downloadAsJson(config, 'config.json')
|
|
}
|