2019-08-06 14:03:05 +02:00

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')
}