forked from tinygrad/tinygrad
+13
-13
@@ -1,9 +1,15 @@
|
||||
// **** graph renderers
|
||||
// ** graph helpers
|
||||
|
||||
const displayGraph = (cls) => {
|
||||
for (const e of document.getElementsByClassName("view")) e.style.display = e.classList.contains(cls) ? "flex" : "none";
|
||||
}
|
||||
|
||||
const ANSI_COLORS = ["#b3b3b3", "#ff6666", "#66b366", "#ffff66", "#6666ff", "#ff66ff", "#66ffff", "#ffffff"];
|
||||
const parseColors = (name, defaultColor="#ffffff") => Array.from(name.matchAll(/(?:\u001b\[(\d+)m([\s\S]*?)\u001b\[0m)|([^\u001b]+)/g),
|
||||
([_, code, colored_st, st]) => ({ st: colored_st ?? st, color: code != null ? ANSI_COLORS[(parseInt(code)-30+60)%60] : defaultColor }));
|
||||
|
||||
const rect = (s) => (typeof s === "string" ? document.querySelector(s) : s).getBoundingClientRect();
|
||||
|
||||
// ** UOp graph
|
||||
|
||||
function intersectRect(r1, r2) {
|
||||
@@ -16,8 +22,6 @@ function intersectRect(r1, r2) {
|
||||
return {x:r1.x+dx*scale, y:r1.y+dy*scale};
|
||||
}
|
||||
|
||||
const rect = (s) => (typeof s === "string" ? document.querySelector(s) : s).getBoundingClientRect();
|
||||
|
||||
let [workerUrl, worker, timeout] = [null, null, null];
|
||||
async function renderDag(graph, additions, recenter=false) {
|
||||
// start calculating the new layout (non-blocking)
|
||||
@@ -95,10 +99,6 @@ async function renderDag(graph, additions, recenter=false) {
|
||||
|
||||
}
|
||||
|
||||
const ANSI_COLORS = ["#b3b3b3", "#ff6666", "#66b366", "#ffff66", "#6666ff", "#ff66ff", "#66ffff", "#ffffff"];
|
||||
const parseColors = (name, defaultColor="#ffffff") => [...name.matchAll(/(?:\u001b\[(\d+)m([\s\S]*?)\u001b\[0m)|([^\u001b]+)/g)]
|
||||
.map(([_, code, colored_st, st]) => ({ st: colored_st ?? st, color: code != null ? ANSI_COLORS[(parseInt(code)-30+60)%60] : defaultColor }));
|
||||
|
||||
// ** profiler graph
|
||||
|
||||
function formatTime(ts, dur=ts) {
|
||||
@@ -126,8 +126,8 @@ async function renderProfiler() {
|
||||
deviceList.style.paddingTop = `${tickSize+padding}px`;
|
||||
const ctx = canvas.getContext("2d");
|
||||
const { top:canvasTop, height:canvasHeight } = rect(canvas);
|
||||
// color by name
|
||||
const nameMap = new Map();
|
||||
// color by key (name/category/device)
|
||||
const colorMap = new Map();
|
||||
const data = {shapes:[], axes:{}};
|
||||
for (const [k, { timeline, mem }] of Object.entries(layout)) {
|
||||
if (timeline.shapes.length === 0 && mem.shapes.length == 0) continue;
|
||||
@@ -142,14 +142,14 @@ async function renderProfiler() {
|
||||
const levelHeight = baseHeight-padding;
|
||||
const offsetY = baseY-canvasTop+padding/2;
|
||||
for (const [i,e] of timeline.shapes.entries()) {
|
||||
const label = parseColors(e.name).map(({ color, st }) => ({ color, st, width:ctx.measureText(st).width }));
|
||||
const colorKey = e.cat ?? e.name;
|
||||
if (!nameMap.has(colorKey)) {
|
||||
if (!colorMap.has(colorKey)) {
|
||||
const colors = devColors[k] ?? devColors.DEFAULT;
|
||||
nameMap.set(colorKey, { fillColor:colors[i%colors.length] });
|
||||
colorMap.set(colorKey, colors[i%colors.length]);
|
||||
}
|
||||
const label = parseColors(e.name).map(({ color, st }) => ({ color, st, width:ctx.measureText(st).width }));
|
||||
// offset y by depth
|
||||
data.shapes.push({ x:e.st-st, dur:e.dur, name:e.name, height:levelHeight, y:offsetY+levelHeight*e.depth, ref:e.ref, label, ...nameMap.get(colorKey) });
|
||||
data.shapes.push({x:e.st-st, dur:e.dur, height:levelHeight, y:offsetY+levelHeight*e.depth, ref:e.ref, label, fillColor:colorMap.get(colorKey)});
|
||||
}
|
||||
// position shapes on the canvas and scale to fit fixed area
|
||||
const startY = offsetY+(levelHeight*timeline.maxDepth)+padding/2;
|
||||
|
||||
Reference in New Issue
Block a user