Skip to content

Commit

Permalink
Merge pull request #55 from chanzuckerberg/bkmartinjr-perf3
Browse files Browse the repository at this point in the history
performance - improve caching in histogram and graph
  • Loading branch information
colinmegill authored May 15, 2018
2 parents e739179 + 87958af commit 82a5bae
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 36 deletions.
65 changes: 45 additions & 20 deletions src/components/continuous/histogramBrush.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class HistogramBrush extends React.Component {
this.width = 300;
this.height = 100;
this.marginBottom = 20;
this.histogramCache = {};

this.state = {
svg: null,
Expand All @@ -47,6 +48,44 @@ class HistogramBrush extends React.Component {
}
componentDidMount() {}
componentDidUpdate() {}

calcHistogramCache(nextProps) {
// recalculate expensive stuff
const allValuesForContinuousFieldAsArray = _.map(
nextProps.currentCellSelection,
nextProps.metadataField
);

this.histogramCache.x = d3
.scaleLinear()
.domain([nextProps.ranges.min, nextProps.ranges.max])
.range([0, this.width]);

this.histogramCache.y = d3
.scaleLinear()
.range([this.height - this.marginBottom, 0]);
// .range([height - margin.bottom, margin.top]);

this.histogramCache.bins = d3
.histogram()
.domain(this.histogramCache.x.domain())
.thresholds(40)(allValuesForContinuousFieldAsArray);

this.histogramCache.numValues = allValuesForContinuousFieldAsArray.length;
}

componentWillMount() {
this.calcHistogramCache(this.props);
}
componentWillReceiveProps(nextProps) {
if (
this.props.metadataField !== nextProps.metadataField ||
!this.histogramCache.x
) {
this.calcHistogramCache(nextProps);
}
}

onBrush(selection, x) {
return () => {
if (d3.event.selection) {
Expand All @@ -65,24 +104,10 @@ class HistogramBrush extends React.Component {
};
}
drawHistogram(svgRef) {
const allValuesForContinuousFieldAsArray = _.map(
this.props.currentCellSelection,
this.props.metadataField
);

var x = d3
.scaleLinear()
.domain(d3.extent(allValuesForContinuousFieldAsArray, d => +d))
.range([0, this.width]);
// .range([margin.left, width - margin.right]);

var y = d3.scaleLinear().range([this.height - this.marginBottom, 0]);
// .range([height - margin.bottom, margin.top]);

const bins = d3
.histogram()
.domain(x.domain())
.thresholds(40)(allValuesForContinuousFieldAsArray);
const x = this.histogramCache.x;
const y = this.histogramCache.y;
const bins = this.histogramCache.bins;
const numValues = this.histogramCache.numValues;

d3
.select(svgRef)
Expand All @@ -96,13 +121,13 @@ class HistogramBrush extends React.Component {
return x(d.x0) + 1;
})
.attr("y", function(d) {
return y(d.length / allValuesForContinuousFieldAsArray.length);
return y(d.length / numValues);
})
.attr("width", function(d) {
return Math.abs(x(d.x1) - x(d.x0) - 1);
})
.attr("height", function(d) {
return y(0) - y(d.length / allValuesForContinuousFieldAsArray.length);
return y(0) - y(d.length / numValues);
});

if (!this.state.brush && !this.state.axis) {
Expand Down
38 changes: 23 additions & 15 deletions src/components/graph/graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,35 +113,43 @@ class Graph extends React.Component {
if (this.state.regl && nextProps.vertices) {
const vertices = nextProps.currentCellSelection;
const vertexCount = vertices.length;
const positions = new Float32Array(2 * vertexCount);
const colors = new Float32Array(3 * vertexCount);
const sizes = new Float32Array(vertexCount);

// d3.scaleLinear().domain([0,1]).range([-1,1])
const glScaleX = scaleLinear([0, 1], [-1, 1]);
// d3.scaleLinear().domain([0,1]).range([1,-1])
const glScaleY = scaleLinear([0, 1], [1, -1]);
// Cache a scaled graph
if (!this.scaledGraphVec || this.props.graphVec !== nextProps.graphVec) {
const positions = new Float32Array(2 * vertexCount);

// d3.scaleLinear().domain([0,1]).range([-1,1])
const glScaleX = scaleLinear([0, 1], [-1, 1]);
// d3.scaleLinear().domain([0,1]).range([1,-1])
const glScaleY = scaleLinear([0, 1], [1, -1]);

const graphVec = nextProps.graphVec;
for (var i = 0; i < vertexCount; i++) {
const cell = vertices[i];
const cellIdx = cell.__cellIndex__;

const x = glScaleX(graphVec[2 * cellIdx]);
const y = glScaleY(graphVec[2 * cellIdx + 1]);
positions[2 * i] = x;
positions[2 * i + 1] = y;
}
this.scaledGraphVec = positions;
}

/*
Construct Vectors
Construct Size & Color Vectors
*/
const graphVec = nextProps.graphVec;
for (var i = 0; i < vertexCount; i++) {
const cell = vertices[i];
const cellIdx = cell.__cellIndex__;
const x = glScaleX(graphVec[2 * cellIdx]);
const y = glScaleY(graphVec[2 * cellIdx + 1]);
positions[2 * i] = x;
positions[2 * i + 1] = y;

colors.set(cell.__colorRGB__, 3 * i);

sizes[i] = cell.__selected__
? 4
: 0.2; /* make this a function of the number of total cells, including regraph */
}

this.state.pointBuffer({ data: positions, dimension: 2 });
this.state.pointBuffer({ data: this.scaledGraphVec, dimension: 2 });
this.state.colorBuffer({ data: colors, dimension: 3 });
this.state.sizeBuffer({ data: sizes, dimension: 1 });
this.count = vertexCount;
Expand Down
5 changes: 4 additions & 1 deletion src/middleware/updateCellSelectionMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ const updateCellSelectionMiddleware = store => {
- metadata has cellname and index, and that's all we ever need to reference cell info
*/
let newSelection = s.controls.currentCellSelection.slice(0);
_.forEach(newSelection, cell => (cell.__selected__ = true));
// _.forEach(newSelection, cell => (cell.__selected__ = true));
for (let i = 0; i < newSelection.length; i++) {
newSelection[i].__selected__ = true;
}

/*
in plain language...
Expand Down

0 comments on commit 82a5bae

Please sign in to comment.