Skip to content

Commit 16b423f

Browse files
committed
Enhance performance benchmarks and add base64 encoding for geometry data
1 parent 2994a41 commit 16b423f

3 files changed

Lines changed: 329 additions & 107 deletions

File tree

anyplotlib/figure_esm.js

Lines changed: 97 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,29 @@ function render({ model, el }) {
8282
return arr[lo]+t*(arr[lo+1]-arr[lo]);
8383
}
8484

85+
// ── b64 array decode helpers ─────────────────────────────────────────────
86+
// Convert a base-64 string (little-endian raw bytes) to a JS TypedArray.
87+
// TypedArrays support .length and [i] indexing so they are drop-in
88+
// replacements for plain arrays in all draw / hit-test functions.
89+
function _decodeF64(b64) {
90+
const bin = atob(b64);
91+
const buf = new Uint8Array(bin.length);
92+
for (let i = 0; i < bin.length; i++) buf[i] = bin.charCodeAt(i);
93+
return new Float64Array(buf.buffer);
94+
}
95+
function _decodeF32(b64) {
96+
const bin = atob(b64);
97+
const buf = new Uint8Array(bin.length);
98+
for (let i = 0; i < bin.length; i++) buf[i] = bin.charCodeAt(i);
99+
return new Float32Array(buf.buffer);
100+
}
101+
function _decodeI32(b64) {
102+
const bin = atob(b64);
103+
const buf = new Uint8Array(bin.length);
104+
for (let i = 0; i < bin.length; i++) buf[i] = bin.charCodeAt(i);
105+
return new Int32Array(buf.buffer);
106+
}
107+
85108
// ── per-panel frame timing ────────────────────────────────────────────────
86109
// Called at the entry of every draw function (draw2d / draw1d / draw3d /
87110
// drawBar). Records a high-resolution timestamp in a 60-entry rolling
@@ -1097,9 +1120,38 @@ function render({ model, el }) {
10971120
ctx.fillStyle = theme.bgPlot;
10981121
ctx.fillRect(0, 0, pw, ph);
10991122

1100-
const verts = st.vertices || [];
1101-
const faces = st.faces || [];
1102-
const zVals = st.z_values || [];
1123+
// ── decode + cache b64 geometry (only when state changes) ──────────────
1124+
const vKey = st.vertices_b64 || '';
1125+
const fKey = st.faces_b64 || '';
1126+
const zKey = st.z_values_b64 || '';
1127+
if (p._3dVertsKey !== vKey) {
1128+
p._3dVertsKey = vKey;
1129+
if (vKey) {
1130+
const vf = _decodeF32(vKey);
1131+
const nv = vf.length / 3;
1132+
const arr = new Array(nv);
1133+
for (let i = 0; i < nv; i++) arr[i] = [vf[i*3], vf[i*3+1], vf[i*3+2]];
1134+
p._3dVerts = arr;
1135+
} else { p._3dVerts = st.vertices || []; }
1136+
}
1137+
if (p._3dFacesKey !== fKey) {
1138+
p._3dFacesKey = fKey;
1139+
if (fKey) {
1140+
const ff = _decodeI32(fKey);
1141+
const nf = ff.length / 3;
1142+
const arr = new Array(nf);
1143+
for (let i = 0; i < nf; i++) arr[i] = [ff[i*3], ff[i*3+1], ff[i*3+2]];
1144+
p._3dFaces = arr;
1145+
} else { p._3dFaces = st.faces || []; }
1146+
}
1147+
if (p._3dZKey !== zKey) {
1148+
p._3dZKey = zKey;
1149+
p._3dZVals = zKey ? _decodeF32(zKey) : (st.z_values || []);
1150+
}
1151+
const verts = p._3dVerts || [];
1152+
const faces = p._3dFaces || [];
1153+
const zVals = p._3dZVals || [];
1154+
11031155
const lut = st.colormap_data || [];
11041156
const geom = st.geom_type || 'surface';
11051157
const bnds = st.data_bounds || {};
@@ -1381,7 +1433,22 @@ function render({ model, el }) {
13811433
_recordFrame(p);
13821434
const {pw,ph,plotCtx:ctx} = p;
13831435
const r=_plotRect1d(pw,ph);
1384-
const xArr=st.x_axis||[], x0=st.view_x0||0, x1=st.view_x1||1;
1436+
1437+
// ── decode + cache b64 arrays (keyed by b64 string; free on re-render) ──
1438+
const xKey = st.x_axis_b64 || '';
1439+
const dKey = st.data_b64 || '';
1440+
if (p._1dXKey !== xKey) {
1441+
p._1dXKey = xKey;
1442+
p._1dXArr = xKey ? _decodeF64(xKey) : (st.x_axis || []);
1443+
}
1444+
if (p._1dDKey !== dKey) {
1445+
p._1dDKey = dKey;
1446+
p._1dDArr = dKey ? _decodeF64(dKey) : (st.data || []);
1447+
}
1448+
const xArr = p._1dXArr; // Float64Array (or plain array fallback)
1449+
const yData = p._1dDArr; // Float64Array (or plain array fallback)
1450+
1451+
const x0=st.view_x0||0, x1=st.view_x1||1;
13851452
const dMin=st.data_min, dMax=st.data_max;
13861453
const units=st.units||'', yUnits=st.y_units||'';
13871454

@@ -1522,13 +1589,15 @@ function render({ model, el }) {
15221589
ctx.restore();
15231590
}
15241591

1525-
_drawLine(st.data, xArr,
1592+
_drawLine(yData, xArr,
15261593
st.line_color || '#4fc3f7', st.line_linewidth || 1.5,
15271594
st.line_linestyle || 'solid',
15281595
st.line_alpha != null ? st.line_alpha : 1.0,
15291596
st.line_marker || 'none', st.line_markersize || 4);
15301597
for (const ex of (st.extra_lines || [])) {
1531-
_drawLine(ex.data || [], ex.x_axis || xArr,
1598+
const exY = ex.data_b64 ? _decodeF64(ex.data_b64) : (ex.data || []);
1599+
const exX = ex.x_axis_b64 ? _decodeF64(ex.x_axis_b64) : (ex.x_axis ? ex.x_axis : xArr);
1600+
_drawLine(exY, exX,
15321601
ex.color || (theme.dark ? '#fff' : '#333'), ex.linewidth || 1.5,
15331602
ex.linestyle || 'solid',
15341603
ex.alpha != null ? ex.alpha : 1.0,
@@ -1613,7 +1682,8 @@ function render({ model, el }) {
16131682
const st=p.state; if(!st) return;
16141683
const {pw,ph,ovCtx} = p;
16151684
const r=_plotRect1d(pw,ph);
1616-
const xArr=st.x_axis||[], x0=st.view_x0||0, x1=st.view_x1||1;
1685+
const xArr = p._1dXArr || (st.x_axis_b64 ? _decodeF64(st.x_axis_b64) : (st.x_axis||[]));
1686+
const x0=st.view_x0||0, x1=st.view_x1||1;
16171687
const dMin=st.data_min, dMax=st.data_max;
16181688
ovCtx.clearRect(0,0,pw,ph);
16191689
const widgets=st.overlay_widgets||[];
@@ -1668,9 +1738,10 @@ function render({ model, el }) {
16681738
const st=p.state; if(!st) return;
16691739
const {pw,ph,mkCtx} = p;
16701740
const r=_plotRect1d(pw,ph);
1671-
const xArr=st.x_axis||[], x0=st.view_x0||0, x1=st.view_x1||1;
1672-
const dMin=st.data_min, dMax=st.data_max;
1673-
const yData=st.data||[];
1741+
// Use cached decoded arrays from draw1d; fall back to inline decode if needed.
1742+
const xArr = p._1dXArr || (st.x_axis_b64 ? _decodeF64(st.x_axis_b64) : (st.x_axis||[]));
1743+
const yData = p._1dDArr || (st.data_b64 ? _decodeF64(st.data_b64) : (st.data||[]));
1744+
const x0=st.view_x0||0, x1=st.view_x1||1;
16741745
mkCtx.clearRect(0,0,pw,ph);
16751746
const sets=st.markers||[];
16761747
if(!sets.length) return;
@@ -1745,7 +1816,8 @@ function render({ model, el }) {
17451816
const st = p.state; if (!st) return null;
17461817
const r = _plotRect1d(p.pw, p.ph);
17471818
if (mx < r.x || mx > r.x+r.w || my < r.y || my > r.y+r.h) return null;
1748-
const xArr = st.x_axis||[], x0 = st.view_x0||0, x1 = st.view_x1||1;
1819+
const xArr = p._1dXArr || (st.x_axis_b64 ? _decodeF64(st.x_axis_b64) : (st.x_axis||[]));
1820+
const x0 = st.view_x0||0, x1 = st.view_x1||1;
17491821
const dMin = st.data_min, dMax = st.data_max;
17501822
const HIT = 6;
17511823

@@ -1776,10 +1848,13 @@ function render({ model, el }) {
17761848
// Check extra lines first (drawn on top), then primary
17771849
for (let i = (st.extra_lines||[]).length - 1; i >= 0; i--) {
17781850
const ex = st.extra_lines[i];
1779-
const hit = _nearestOnLine(ex.data, ex.x_axis || xArr, ex.id);
1851+
const exY = ex.data_b64 ? _decodeF64(ex.data_b64) : (ex.data || []);
1852+
const exX = ex.x_axis_b64 ? _decodeF64(ex.x_axis_b64) : (ex.x_axis ? ex.x_axis : xArr);
1853+
const hit = _nearestOnLine(exY, exX, ex.id);
17801854
if (hit) return hit;
17811855
}
1782-
return _nearestOnLine(st.data, xArr, null);
1856+
const primY = p._1dDArr || (st.data_b64 ? _decodeF64(st.data_b64) : (st.data||[]));
1857+
return _nearestOnLine(primY, xArr, null);
17831858
}
17841859

17851860
// ── marker hit-test helpers ────────────────────────────────────────────────
@@ -1858,7 +1933,9 @@ function render({ model, el }) {
18581933
function _markerHitTest1d(mx, my, p) {
18591934
const st=p.state; if(!st) return null;
18601935
const r=_plotRect1d(p.pw,p.ph);
1861-
const xArr=st.x_axis||[], x0=st.view_x0||0, x1=st.view_x1||1;
1936+
// Use cached decoded array from draw1d; fall back to inline decode if needed.
1937+
const xArr = p._1dXArr || (st.x_axis_b64 ? _decodeF64(st.x_axis_b64) : (st.x_axis||[]));
1938+
const x0=st.view_x0||0, x1=st.view_x1||1;
18621939
const dMin=st.data_min, dMax=st.data_max;
18631940
const sets=st.markers||[];
18641941
for(let si=sets.length-1;si>=0;si--){
@@ -2216,7 +2293,7 @@ function render({ model, el }) {
22162293
const regKeys=st.registered_keys||[];
22172294
if(regKeys.includes(e.key)||regKeys.includes('*')){
22182295
const r=_plotRect1d(p.pw,p.ph);
2219-
const xArr=st.x_axis||[];
2296+
const xArr = p._1dXArr || (st.x_axis_b64 ? _decodeF64(st.x_axis_b64) : (st.x_axis||[]));
22202297
const frac=_canvasXToFrac1d(p.mouseX,st.view_x0,st.view_x1,r);
22212298
const physX=xArr.length>=2?_fracToX1d(xArr,frac):frac;
22222299
_emitEvent(p.id,'on_key',null,{
@@ -2241,7 +2318,7 @@ function render({ model, el }) {
22412318
if(p._hoverSi!==-1){p._hoverSi=-1;p._hoverI=-1;drawMarkers1d(p,null);}
22422319
return;
22432320
}
2244-
const xArr=st.x_axis||[];
2321+
const xArr = p._1dXArr || (st.x_axis_b64 ? _decodeF64(st.x_axis_b64) : (st.x_axis||[]));
22452322
const frac=_canvasXToFrac1d(mx,st.view_x0,st.view_x1,r);
22462323
const phys=xArr.length>=2?_fracToX1d(xArr,frac):frac;
22472324
p.statusBar.textContent=`x:${fmtVal(phys)}`;p.statusBar.style.display='block';
@@ -2447,7 +2524,8 @@ function render({ model, el }) {
24472524
function _ovHitTest1d(mx,my,p){
24482525
const st=p.state;if(!st)return null;
24492526
const r=_plotRect1d(p.pw,p.ph);
2450-
const xArr=st.x_axis||[],x0=st.view_x0||0,x1=st.view_x1||1;
2527+
const xArr = p._1dXArr || (st.x_axis_b64 ? _decodeF64(st.x_axis_b64) : (st.x_axis||[]));
2528+
const x0=st.view_x0||0,x1=st.view_x1||1;
24512529
const widgets=st.overlay_widgets||[];
24522530
const HR=7;
24532531
for(let i=widgets.length-1;i>=0;i--){
@@ -2480,7 +2558,8 @@ function render({ model, el }) {
24802558
const st=p.state;if(!st)return;
24812559
const r=_plotRect1d(p.pw,p.ph);
24822560
const {mx,my:py}=_clientPos(e,p.overlayCanvas,p.pw,p.ph);
2483-
const xArr=st.x_axis||[],x0=st.view_x0||0,x1=st.view_x1||1;
2561+
const xArr = p._1dXArr || (st.x_axis_b64 ? _decodeF64(st.x_axis_b64) : (st.x_axis||[]));
2562+
const x0=st.view_x0||0,x1=st.view_x1||1;
24842563
const xUnit=xArr.length>=2?_fracToX1d(xArr,_canvasXToFrac1d(mx,x0,x1,r)):_canvasXToFrac1d(mx,x0,x1,r);
24852564
const widgets=st.overlay_widgets;
24862565
const d=p.ovDrag, s=d.snapW, w=widgets[d.idx];

0 commit comments

Comments
 (0)