viz memory: compute nbytes (#11795)

* viz memory: compute nbytes

* local map
This commit is contained in:
qazal
2025-08-23 17:34:07 +03:00
committed by GitHub
parent 58653b5eae
commit aaea6b97ad
3 changed files with 14 additions and 11 deletions
+1 -1
View File
@@ -139,7 +139,7 @@ class Buffer:
if PROFILE:
self._prof_num = num = len(Buffer.profile_events)
ts = decimal.Decimal(time.perf_counter_ns())/1000
Buffer.profile_events.append(ProfilePointEvent(self.device, "alloc", ts, num, {"dtype":str(self.dtype),"sz":self.size,"nbytes":self.nbytes}))
Buffer.profile_events.append(ProfilePointEvent(self.device, "alloc", ts, num, {"dtype":self.dtype, "sz":self.size}))
return self
def deallocate(self):
assert hasattr(self, '_buf'), "buffer must be allocated to deallocate"
+4 -3
View File
@@ -151,7 +151,7 @@ async function renderProfiler() {
// layout once!
if (data != null) return;
const profiler = d3.select(".profiler").html("");
const { layout, dur, peak } = await (await fetch("/get_profile")).json();
const { layout, dur, peak, dtypes } = await (await fetch("/get_profile")).json();
// place devices on the y axis and set vertical positions
const [tickSize, padding] = [10, 8];
const deviceList = profiler.append("div").attr("id", "device-list").style("padding-top", tickSize+padding+"px");
@@ -196,8 +196,9 @@ async function renderProfiler() {
const shapes = [];
for (const [i,e] of v.shapes.entries()) {
const x = e.x.map(tsIdx => v.timestamps[tsIdx]);
const arg = {tooltipText:`${e.arg.dtype} len:${formatUnit(e.arg.sz)}\n${formatUnit(e.arg.nbytes, "B")}`};
shapes.push({ x, y0:e.y.map(yscale), y1:e.y.map(y => yscale(y+e.arg.nbytes)), arg, fillColor:cycleColors(colorScheme.BUFFER, i) });
const nbytes = dtypes[e.arg.dtype]*e.arg.sz;
const arg = {tooltipText:`${e.arg.dtype} len:${formatUnit(e.arg.sz)}\n${formatUnit(nbytes, "B")}`};
shapes.push({ x, y0:e.y.map(yscale), y1:e.y.map(y => yscale(y+nbytes)), arg, fillColor:cycleColors(colorScheme.BUFFER, i) });
}
data.tracks.set(k, { shapes, offsetY, height, peak:v.peak, scaleFactor:maxheight*4/height });
div.style("height", height+padding+"px").style("cursor", "pointer").on("click", (e) => {
+9 -7
View File
@@ -146,7 +146,7 @@ def timeline_layout(events:list[tuple[int, int, float, DevEvent]], start_ts:int)
shapes.append({"name":name, "ref":ref, "st":st-start_ts, "dur":dur, "depth":depth, "cat":cat, "info":info})
return {"shapes":shapes, "maxDepth":len(levels)}
def mem_layout(events:list[tuple[int, int, float, DevEvent]], start_ts:int, end_ts:int, peaks:list[int]) -> dict:
def mem_layout(events:list[tuple[int, int, float, DevEvent]], start_ts:int, end_ts:int, peaks:list[int], dtypes_map:dict[str, int]) -> dict:
step, peak, mem = 0, 0, 0
shps:dict[int, dict] = {}
temp:dict[int, dict] = {}
@@ -154,21 +154,22 @@ def mem_layout(events:list[tuple[int, int, float, DevEvent]], start_ts:int, end_
for st,_,_,e in events:
if not isinstance(e, ProfilePointEvent): continue
if e.name == "alloc":
shps[e.key] = temp[e.key] = {"x":[step], "y":[mem], "arg":e.arg}
shps[e.key] = temp[e.key] = {"x":[step], "y":[mem], "arg":{"dtype":e.arg["dtype"].name, "sz":e.arg["sz"]}}
dtypes_map.setdefault(e.arg["dtype"].name, e.arg["dtype"].itemsize)
timestamps.append(int(e.ts)-start_ts)
step += 1
mem += e.arg["nbytes"]
mem += e.arg["sz"]*e.arg["dtype"].itemsize
if mem > peak: peak = mem
if e.name == "free":
timestamps.append(int(e.ts)-start_ts)
step += 1
mem -= (removed:=temp.pop(e.key))["arg"]["nbytes"]
mem -= (free_nbytes:=(removed:=temp.pop(e.key))["arg"]["sz"]*dtypes_map[removed["arg"]["dtype"]])
removed["x"].append(step)
removed["y"].append(removed["y"][-1])
for k,v in temp.items():
if k > e.key:
v["x"] += [step, step]
v["y"] += [v["y"][-1], v["y"][-1]-removed["arg"]["nbytes"]]
v["y"] += [v["y"][-1], v["y"][-1]-free_nbytes]
for v in temp.values():
v["x"].append(step)
v["y"].append(v["y"][-1])
@@ -192,11 +193,12 @@ def get_profile(profile:list[ProfileEvent]) -> bytes|None:
# return layout of per device events
layout:dict[str, dict] = {}
peaks:list[int] = []
dtypes_map:dict[str, int] = {}
for k,v in dev_events.items():
v.sort(key=lambda e:e[0])
layout[k] = timeline_layout(v, start_ts)
layout[f"{k} Memory"] = mem_layout(v, start_ts, unwrap(end_ts), peaks)
return json.dumps({"layout":layout, "dur":unwrap(end_ts)-start_ts, "peak":max(peaks, default=0)}).encode("utf-8")
layout[f"{k} Memory"] = mem_layout(v, start_ts, unwrap(end_ts), peaks, dtypes_map)
return json.dumps({"layout":layout, "dur":unwrap(end_ts)-start_ts, "peak":max(peaks, default=0), "dtypes":dtypes_map}).encode("utf-8")
def get_runtime_stats(key) -> list[dict]:
ret:list[dict] = []