openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

96 lines
3.9 KiB

const colors = ["7aa2f7", "ff9e64", "f7768e", "2ac3de", "7dcfff", "1abc9c", "9ece6a", "e0af68", "bb9af7", "9d7cd8", "ff007c"];
const formatTime = (ms) => {
if (ms<=1e3) return `${ms}us`;
if (ms<=1e6) return `${(ms*1e-3).toFixed(2)}ms`;
return `${(ms*1e-6).toFixed(2)}s`;
}
async function main() {
const { traceEvents } = await (await fetch("/get_profile")).json();
const root = createChild("div.root", document.querySelector("body"));
const list = createChild("div.list", root);
const data = [];
const nameColors = {}; // event names get a unique color
const procNames = {};
for (const e of traceEvents) {
if (e.name === "process_name") {
const proc = createChild(`div.proc-${e.pid}`, list);
createChild("p.process-name", proc).textContent = e.args.name;
procNames[e.pid] = e.args.name;
}
else if (e.name === "thread_name") {
const thread = createChild(`div.thread-${e.pid}-${e.tid}`, `proc-${e.pid}`);
createChild("p.thread-name", thread).textContent = e.args.name;
}
else if (e.ph === "X") {
const thread = document.getElementById(`thread-${e.pid}-${e.tid}`);
if (!(e.name in nameColors)) nameColors[e.name] = colors[data.length%(colors.length-1)];
data.push({ ...e, y:rect(thread).y, color:`#${nameColors[e.name]}`, proc:procNames[e.pid] });
}
}
// render graph
const svg = d3.select(root).append("svg").attr("width", "100%");
const { y, width } = rect(svg.node()); // global coordinates
const render = svg.append("g").attr("transform", `translate(0, ${y})`);
const timestamps = data.map(t => t.ts);
const st = Math.min(...timestamps);
const timeScale = d3.scaleLinear().domain([0, Math.max(...timestamps)-st]).range([y, width]);
const timeAxis = render.append("g").call(d3.axisTop(timeScale).tickFormat(formatTime));
list.style = `margin-top: ${rect(timeAxis.node()).bottom}px;`;
// rescale time based coordinates to fit screen
for (e of data) {
e.st = e.ts-st;
e.x = timeScale(e.st);
e.width = timeScale(e.dur);
}
render.selectAll("rect").data(data).join("rect").attr("fill", d => d.color).attr("x", d => d.x).attr("y", d => d.y).attr("width", d => d.width)
.attr("height", 20);
render.call(d3.brush().on("end", (e) => {
if (!e.selection) return renderTable({ data });
const [[x0, y0], [x1, y1]] = e.selection;
const newData = data.filter(d => d.x>=x0 && d.x<=x1 && d.y>=y0 && d.y<=y1);
renderTable({ data: newData });
}));
createChild("div.table-root", root);
renderTable({ data });
}
const rect = (e) => e.getBoundingClientRect();
const createChild = (es, p) => {
const parts = es.split(".", 2);
if (typeof p === "string") p = document.getElementById(p);
const ret = p.appendChild(document.createElement(parts[0]));
if (parts.length !== 1) ret.id = parts[1];
return ret;
}
const columnNames = {"name":"Name", "st":"Start Time", "dur":"Duration", "proc":"Process"};
const tableState = {data:null, sortBy:null, asc:true};
function renderTable(newState) {
const { data, sortBy, asc } = Object.assign(tableState, newState);
const root = document.getElementById("table-root");
root.innerHTML = "";
const table = createChild("table", root);
const thead = createChild("tr", createChild("thead", table));
for (const [k,v] of Object.entries(columnNames)) {
const th = createChild(`th.${k}`, thead);
th.innerText = v;
th.onclick = (e) => renderTable(k === sortBy ? { asc:!asc } : { sortBy:k, asc:true });
}
if (sortBy != null) {
data.sort((a, b) => asc ? a[sortBy]-b[sortBy] : b[sortBy]-a[sortBy]); // inplace sort
document.getElementById(sortBy).className = asc ? "sorted-asc" : "sorted-desc";
}
const tbody = createChild("tbody", table);
for (const d of data) {
const row = createChild("tr", tbody);
for (const k of Object.keys(columnNames)) {
let formatted = typeof d[k] === "string" ? d[k] : formatTime(d[k]);
createChild("td", row).innerText = formatted;
}
}
}
main()