Published
Edited
Feb 15, 2020
Fork of Cache
1 fork
Insert cell
md`# Cache mike version`
Insert cell
scatterplot.svg.node()
Insert cell
{
scatterplot.update(median_data)
}
Insert cell
scatterplot.init()
Insert cell
scatterplot = {
return {
init: function init(){
this.svg = d3.create("svg")
.attr("viewBox", [0,0,width,height]);

this.y = d3.scaleLinear()
.domain([0,10]).nice()
.range([height - margin.bottom, margin.top])

// y = d3.scaleLog()
// .base(10)
// .domain([0.1, 100]).nice()
// // .domain(d3.extent(data, d=>d.time)).nice()
// .range([height - margin.bottom, margin.top])
// .clamp(true);

this.x = d3.scaleLinear()
.domain([0,10]).nice()
.range([margin.left, width - margin.right])

this.xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(this.x).ticks(width / 80))
.call(g => g.select(".domain").remove())
.call(g => g.append("text")
.attr("x", width)
.attr("y", margin.bottom - 4)
.attr("fill", "currentColor")
.attr("text-anchor", "end")
.text("Size (MB)"))

this.yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(this.y))
.call(g => g.select(".domain").remove())
.call(g => g.append("text")
.attr("x", -margin.left)
.attr("y", 10)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.text("time (ms)"))


this.svg.append("g")
.attr("class", "y axis")
.call(this.yAxis);

this.svg.append("g")
.attr("class", "x axis")
.call(this.xAxis);
},


update: function (new_data){

this.x.domain(d3.extent(new_data, d=>d.size));
this.y.domain(d3.extent(new_data, d=>d.time));

let circle = this.svg//.append("g")
.selectAll("circle")
.data(new_data, d=>{
let key = d.type+d.size
return d? key:this.id;
});
// circle.exit().remove();

this.svg.select(".x.axis")
// .transition()
.call(this.xAxis);

this.svg.select(".y.axis")
// .transition()
.call(this.yAxis);

circle.join(
enter => enter.append('circle')
.attr("stroke-width", 0.5)
// .attr("fill", "none")
.attr("r", 0)
.attr("cx", d => {
return this.x(d.size)
})
.attr("cy", d => {
return this.y(d.time);
})
.attr("stroke", d => {
if(d.type == "row_major") return "red";
if(d.type == "col_major") return "blue";
})
.attr("fill", d => {
if(d.type == "row_major") return "red";
if(d.type == "col_major") return "blue";
})
.transition()
.attr("r", 1),

update => update.transition()
.attr("cy", d => this.y(d.time))
.attr("cx", d=>this.x(d.size))
,
exit => exit.remove()
)


}

}
}

Insert cell
Insert cell
function make_data(){

function make_matrix(dim){
let mat = [];
for(let y=0; y<dim; y++){
// let row = [];
let row = new Uint32Array(dim);
mat.push(row);
for(let x=0; x<dim; x++){
// row.push(1);
row[x] = 1;
}
}
return mat;
}

function row_major(mat){
let tot = 0;
for (let y=0; y<mat[0].length; y++){
for (let x=0; x<mat.length; x++){
tot += mat[y][x];
}
}
return tot;
}

function col_major(mat){
let tot = 0;
for (let x=0; x<mat.length; x++){
for (let y=0; y<mat[0].length; y++){
tot += mat[y][x];
}
}
return tot;
}

function time_me(wrapped){
return function(){
const start = performance.now();
wrapped.apply(this, arguments);
const end = performance.now();
return end - start;
}
}

let cm_time = time_me(col_major);
let rm_time = time_me(row_major);
let times = [];
//give the jit a chance to work
let mat = make_matrix(1000);
rm_time(mat);
cm_time(mat);
let max = 4000;
let step = 10;
let sizes = [];
for (let i=0; i<10; i++){
let num = Math.ceil(Math.random() * max);
num = num + (step - num%step)
sizes.push(num);
}
// debugger;
for (let d of sizes){
let size = (d * d * 8 + d * 8) / Math.pow(10,6);
let mat = make_matrix(d);
// debugger;
let row_time = rm_time(mat);
let col_time = cm_time(mat);
times.push({
type: 'col_major',
time: col_time,
size: size
});
times.push({
type: 'row_major',
time: row_time,
size: size
});
}
return times;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
median_data = Array.from(
d3.rollup(data,
x=>{
let times = x.map(x=>x.time).sort();
let q_01 = d3.quantileSorted(times, 0.1);
let q_09 = d3.quantileSorted(times, 0.9);
times = times.filter(x=>q_01 < x < q_09);
let time = d3.mean(times);
return {
size: x[0].size,
type: x[0].type,
time: time
};
},
x=>x.type,
x=>x.size)
.values())
.map(x=> Array.from(x.values()))
.flat();
Insert cell
d3.quantile(d3.range(10), 1)
Insert cell
a = [3,6,4,5]
Insert cell
a.sort()
Insert cell
Insert cell
height = 500;
Insert cell
d3 = require("d3", "d3-array@^2.2")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more