UNPKG

d3-flame-graph

Version:

A d3.js library to produce flame graphs.

434 lines (433 loc) 16.1 kB
import { select as R } from "d3-selection"; import { format as nt } from "d3-format"; import { ascending as yt } from "d3-array"; import { partition as vt, hierarchy as wt } from "d3-hierarchy"; import { scaleLinear as rt } from "d3-scale"; import { easeCubic as xt } from "d3-ease"; import "d3-transition"; import "d3-dispatch"; import './d3-flamegraph.css';function bt(l) { let o = 0, a = 0, u = 1; const g = 10; if (l) { for (let s = 0; s < l.length && !(s > 6); s++) o += u * (l.charCodeAt(s) % g), a += u * (g - 1), u *= 0.7; a > 0 && (o = o / a); } return o; } function lt(l) { let i = 0; if (l) { const o = l.split("`"); o.length > 1 && (l = o[o.length - 1]), l = l.split("(")[0], i = bt(l); } return i; } function Ht(l, i) { let o, a, u; return l === "red" ? (o = 200 + Math.round(55 * i), a = 50 + Math.round(80 * i), u = a) : l === "orange" ? (o = 190 + Math.round(65 * i), a = 90 + Math.round(65 * i), u = 0) : l === "yellow" ? (o = 175 + Math.round(55 * i), a = o, u = 50 + Math.round(20 * i)) : l === "green" ? (o = 50 + Math.round(60 * i), a = 200 + Math.round(55 * i), u = o) : l === "pastelgreen" ? (o = 163 + Math.round(75 * i), a = 195 + Math.round(49 * i), u = 72 + Math.round(149 * i)) : l === "blue" ? (o = 91 + Math.round(126 * i), a = 156 + Math.round(76 * i), u = 221 + Math.round(26 * i)) : l === "aqua" ? (o = 50 + Math.round(60 * i), a = 165 + Math.round(55 * i), u = a) : l === "cold" ? (o = 0 + Math.round(55 * (1 - i)), a = 0 + Math.round(230 * (1 - i)), u = 200 + Math.round(55 * i)) : (o = 200 + Math.round(55 * i), a = 0 + Math.round(230 * (1 - i)), u = 0 + Math.round(55 * (1 - i))), "rgb(" + o + "," + a + "," + u + ")"; } function it(l) { return l.data.name; } function Ct() { var l = R("body"), i = null, o = it, a = it, u = !1; function g() { i = l.append("div").style("display", "none").style("position", "absolute").style("opacity", 0).style("pointer-events", "none").attr("class", "d3-flame-graph-tip"); } return g.show = function(s, M) { u ? i.html(o(M)) : i.text(a(M)); var y = i.node().offsetWidth, w = i.node().offsetHeight, x = s.pageX + 5, b = s.pageY + 5; return x + y > window.innerWidth && (x = s.pageX - y - 5), x < 0 && (x = 5), b + w > window.innerHeight && (b = s.pageY - w - 5), b < 0 && (b = 5), i.style("display", "block").style("left", x + "px").style("top", b + "px").transition().duration(200).style("opacity", 1).style("pointer-events", "all"), g; }, g.hide = function() { return i.style("display", "none").transition().duration(200).style("opacity", 0).style("pointer-events", "none"), g; }, g.text = function(s) { return arguments.length ? (a = s, u = !1, g) : a; }, g.html = function(s) { return arguments.length ? (o = s, u = !0, g) : o; }, g.destroy = function() { i.remove(); }, g; } const Zt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, defaultFlamegraphTooltip: Ct }, Symbol.toStringTag, { value: "Module" })); function Dt(l, i, o) { const a = o, u = 1 - a; return [ Math.round(l[0] * a + i[0] * u), Math.round(l[1] * a + i[1] * u), Math.round(l[2] * a + i[2] * u) ]; } function Et(l, i) { if (l.highlight) return i; const o = l.data.value, a = l.value; return `rgb(${Dt([0, 255, 40], [196, 245, 233], o / a).join()})`; } function _t(l, i) { if (l.highlight) return i; const o = l.data.n || l.data.name, a = lt(o), u = 0 + Math.round(55 * (1 - a)), g = 0 + Math.round(230 * (1 - a)), s = 200 + Math.round(55 * a); return "rgb(" + u + "," + g + "," + s + ")"; } function kt(l, i) { let o = i; const { v8_jit: a, javascript: u, optimized: g } = l.data.extras || {}; if (a && !u && (o = "#dadada"), u) { let s = (g || 0) / l.value, M = 255, y = 0, w = 0; s < 0.4 ? (s = s * 2.5, M = 240 - s * 200) : s < 0.9 ? (s = (s - 0.4) * 2, M = 0, w = 200 - 200 * s, y = 100 * s) : (s = (s - 0.9) * 10, M = 0, w = 0, y = 100 + 150 * s), o = `rgb(${M} , ${y}, ${w})`; } return o; } function Ot(l, i) { if (l.highlight) return i; let o = 220, a = 220, u = 220; const g = l.delta || l.data.d || l.data.delta, s = Math.abs(g); let M = l.value || l.data.v || l.data.value; M <= s && (M = s); const y = s / M; return g === M ? (o = 255, a = 190, u = 90) : g > 0 ? (u = Math.round(235 * (1 - y)), a = u) : g < 0 && (o = Math.round(235 * (1 - y)), a = o), "rgb(" + o + "," + a + "," + u + ")"; } const Rt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, allocationColorMapper: Et, differentialColorMapper: Ot, nodeJsColorMapper: kt, offCpuColorMapper: _t }, Symbol.toStringTag, { value: "Module" })); function Ft() { let l = 960, i = null, o = 18, a = null, u = null, g = "", s = 750, M = xt, y = !1, w = !1, x = null, b = null, L = 0, D = null, j = null, F = !1, I = !1, X = !1, k = null, $ = !1, T = null, H = function(t) { return t.data.n || t.data.name; }, O = function(t) { return "v" in t ? t.v : t.value; }, W = function(t) { return t.c || t.children; }, q = function(t) { return t.data.l || t.data.libtype; }, J = function(t) { return "d" in t.data ? t.data.d : t.data.delta; }, V = function(t, r, n) { j = () => { D && (D.textContent = "search: " + r + " of " + n + " total samples ( " + nt(".3f")(100 * (r / n), 3) + "%)"); }, j(); }; const at = V; let z = (t, r, n = !1) => { if (!r) return !1; let f = H(t); n && (r = r.toLowerCase(), f = f.toLowerCase()); const c = new RegExp(r); return typeof f < "u" && f && f.match(c); }; const ot = z; let E = function(t) { D && (t ? D.textContent = t : typeof j == "function" ? j() : D.textContent = ""); }; const ut = E; let N = function(t) { return H(t) + " (" + nt(".3f")(100 * (t.x1 - t.x0), 3) + "%, " + O(t) + " samples)"; }, Z = function(t) { return t.highlight ? "#E600E6" : ft(H(t), q(t)); }; const P = Z; function ft(t, r) { let n = T || "warm"; !T && !(typeof r > "u" || r === "") && (n = "red", typeof t < "u" && t && t.match(/::/) && (n = "yellow"), r === "kernel" ? n = "orange" : r === "jit" ? n = "green" : r === "inlined" && (n = "aqua")); const f = lt(t); return Ht(n, f); } function G(t) { t.data.fade = !1, t.data.hide = !1, t.children && t.children.forEach(G); } function st(t) { let r = t, n = r.parent, f, c, d; for (; n; ) { for (f = n.children, c = f.length; c--; ) d = f[c], d !== r && (d.data.hide = !0); r = n, n = r.parent; } } function K(t) { t.parent && (t.parent.data.fade = !0, K(t.parent)); } function Y(t, r) { if (u && u.hide(), st(t), G(t), K(t), S(), X) { const n = r.parentNode.offsetTop, f = (window.innerHeight - n) / o, c = (t.height - f + 10) * o; window.scrollTo({ top: n + c, left: 0, behavior: "smooth" }); } typeof x == "function" && x(t); } function ct(t, r) { const n = []; let f = 0; function c(d, m) { let p = !1; z(d, r) ? (d.highlight = !0, p = !0, m || (f += O(d)), n.push(d)) : d.highlight = !1, d.children && d.children.forEach(function(C) { c(C, m || p); }); } return c(t, !1), [n, f]; } function Q(t, r) { if (t.id === r) return t; { const n = t.children; if (n) for (let f = 0; f < n.length; f++) { const c = Q(n[f], r); if (c) return c; } } } function U(t) { t.highlight = !1, t.children && t.children.forEach(function(r) { U(r); }); } function ht(t, r) { if (typeof y == "function") return y(t, r); if (y) return yt(H(t), H(r)); } const dt = vt(); function gt(t) { let r = t.descendants(); if (L > 0) { const n = l / (t.x1 - t.x0); r = r.filter(function(f) { return (f.x1 - f.x0) * n > L; }); } return r; } function S() { a.each(function(t) { const r = rt().range([0, l]), n = rt().range([0, o]); y && t.sort(ht), et(t), dt(t); const f = l / (t.x1 - t.x0); function c(h) { return (h.x1 - h.x0) * f; } const d = gt(t), m = R(this).select("svg"); m.attr("width", l); let p = m.selectAll("g").data(d, function(h) { return h.id; }); if (!i || I) { let h = 0; for (let v = 0; v < d.length; ++v) d[v].depth > h && (h = d[v].depth); i = (h + 3) * o, i < k && (i = k), m.attr("height", i); } p.transition().duration(s).ease(M).attr("transform", function(h) { return "translate(" + r(h.x0) + "," + (w ? n(h.depth) : i - n(h.depth) - o) + ")"; }), p.select("rect").transition().duration(s).ease(M).attr("width", c); const C = p.enter().append("svg:g").attr("transform", function(h) { return "translate(" + r(h.x0) + "," + (w ? n(h.depth) : i - n(h.depth) - o) + ")"; }); C.append("svg:rect").transition().delay(s / 2).attr("width", c), u || C.append("svg:title"), C.append("foreignObject").append("xhtml:div"), p = m.selectAll("g").data(d, function(h) { return h.id; }), p.attr("width", c).attr("height", function(h) { return o; }).attr("name", function(h) { return H(h); }).attr("class", function(h) { return h.data.fade ? "frame fade" : "frame"; }), p.select("rect").attr("height", function(h) { return o; }).attr("fill", function(h) { return Z(h); }), u || p.select("title").text(N), p.select("foreignObject").attr("width", c).attr("height", function(h) { return o; }).style("pointer-events", "none").select("div").attr("class", "d3-flame-graph-label").style("display", function(h) { return c(h) < 35 ? "none" : "block"; }).transition().delay(s).text(H), p.on("click", function(h, v) { Y(v, this); }), p.exit().remove(), p.on("mouseover", function(h, v) { u && u.show(h, v), E(N(v)), typeof b == "function" && b(v); }).on("mouseout", function() { u && u.hide(), E(null); }); }); } function tt(t, r) { r.forEach(function(n) { const f = t.find(function(c) { return c.name === n.name; }); f ? (f.value += n.value, n.children && (f.children || (f.children = []), tt(f.children, n.children))) : t.push(n); }); } function pt(t, r) { r(t); let n = t.children; if (n) { const f = [n]; let c, d, m; for (; f.length; ) for (n = f.pop(), c = n.length; c--; ) d = n[c], r(d), m = d.children, m && f.push(m); } } function mt(t) { let r = 0; pt(t, function(n) { n.id = r++; }); } function et(t) { let r, n, f, c, d, m, p, C; const h = [], v = [], A = [], Mt = !F; let _ = t.data; for (_.hide ? (t.value = 0, n = t.children, n && A.push(n)) : (t.value = _.fade ? 0 : O(_), h.push(t)); r = h.pop(); ) if (n = r.children, n && (d = n.length)) { for (c = 0; d--; ) { if (p = n[d], _ = p.data, _.hide) { p.value = 0, f = p.children, f && A.push(f); continue; } _.fade ? p.value = 0 : (C = O(_), p.value = C, c += C), h.push(p); } Mt && r.value && (r.value -= c), v.push(n); } for (d = v.length; d--; ) { for (n = v[d], c = 0, m = n.length; m--; ) c += n[m].value; n[0].parent.value += c; } for (; A.length; ) for (n = A.pop(), m = n.length; m--; ) p = n[m], p.value = 0, f = p.children, f && A.push(f); } function B() { a.datum((t) => { if (t.constructor.name !== "Node") { const r = wt(t, W); return mt(r), et(r), r.originalValue = r.value, $ && r.eachAfter((n) => { let f = J(n); const c = n.children; let d = c && c.length; for (; --d >= 0; ) f += c[d].delta; n.delta = f; }), r; } }); } function e(t) { if (!arguments.length) return e; a = t, B(), a.each(function(r) { if (R(this).select("svg").size() === 0) { const n = R(this).append("svg:svg").attr("width", l).attr("class", "partition d3-flame-graph"); i && (i < k && (i = k), n.attr("height", i)), n.append("svg:text").attr("class", "title").attr("text-anchor", "middle").attr("y", "25").attr("x", l / 2).attr("fill", "#808080").text(g), u && n.call(u); } }), S(); } return e.height = function(t) { return arguments.length ? (i = t, e) : i; }, e.minHeight = function(t) { return arguments.length ? (k = t, e) : k; }, e.width = function(t) { return arguments.length ? (l = t, e) : l; }, e.cellHeight = function(t) { return arguments.length ? (o = t, e) : o; }, e.tooltip = function(t) { return arguments.length ? (typeof t == "function" && (u = t), e) : u; }, e.title = function(t) { return arguments.length ? (g = t, e) : g; }, e.transitionDuration = function(t) { return arguments.length ? (s = t, e) : s; }, e.transitionEase = function(t) { return arguments.length ? (M = t, e) : M; }, e.sort = function(t) { return arguments.length ? (y = t, e) : y; }, e.inverted = function(t) { return arguments.length ? (w = t, e) : w; }, e.computeDelta = function(t) { return arguments.length ? ($ = t, e) : $; }, e.setLabelHandler = function(t) { return arguments.length ? (N = t, e) : N; }, e.label = e.setLabelHandler, e.search = function(t) { const r = []; let n = 0, f = 0; a.each(function(c) { const d = ct(c, t); r.push(...d[0]), n += d[1], f += c.originalValue; }), V(r, n, f), S(); }, e.findById = function(t) { if (typeof t > "u" || t === null) return null; let r = null; return a.each(function(n) { r === null && (r = Q(n, t)); }), r; }, e.clear = function() { E(null), a.each(function(t) { U(t), S(); }); }, e.zoomTo = function(t) { Y(t, a.node()); }, e.resetZoom = function() { a.each(function(t) { Y(t, a.node()); }); }, e.onClick = function(t) { return arguments.length ? (x = t, e) : x; }, e.onHover = function(t) { return arguments.length ? (b = t, e) : b; }, e.merge = function(t) { return a && (this.resetZoom(), j = null, E(null), a.datum((r) => (tt([r.data], [t]), r.data)), B(), S()), e; }, e.update = function(t) { return a && (t && (a.datum(t), B()), S()), e; }, e.destroy = function() { return a && (u && (u.hide(), typeof u.destroy == "function" && u.destroy()), a.selectAll("svg").remove()), e; }, e.setColorMapper = function(t) { return arguments.length ? (Z = (r) => { const n = P(r); return t(r, n); }, e) : (Z = P, e); }, e.color = e.setColorMapper, e.setColorHue = function(t) { return arguments.length ? (T = t, e) : (T = null, e); }, e.minFrameSize = function(t) { return arguments.length ? (L = t, e) : L; }, e.setDetailsElement = function(t) { return arguments.length ? (D = t, e) : D; }, e.details = e.setDetailsElement, e.selfValue = function(t) { return arguments.length ? (F = t, e) : F; }, e.resetHeightOnZoom = function(t) { return arguments.length ? (I = t, e) : I; }, e.scrollOnZoom = function(t) { return arguments.length ? (X = t, e) : X; }, e.getName = function(t) { return arguments.length ? (H = t, e) : H; }, e.getValue = function(t) { return arguments.length ? (O = t, e) : O; }, e.getChildren = function(t) { return arguments.length ? (W = t, e) : W; }, e.getLibtype = function(t) { return arguments.length ? (q = t, e) : q; }, e.getDelta = function(t) { return arguments.length ? (J = t, e) : J; }, e.setSearchHandler = function(t) { return arguments.length ? (V = t, e) : (V = at, e); }, e.setDetailsHandler = function(t) { return arguments.length ? (E = t, e) : (E = ut, e); }, e.setSearchMatch = function(t) { return arguments.length ? (z = t, e) : (z = ot, e); }, e; } export { Rt as colorMapper, Ft as default, Zt as tooltip };