8000 4.3/2: pyscript works without worker · JayAyAre/PyScript-vs-JavaScript@755fd15 · GitHub
[go: up one dir, main page]

Skip to content

Commit 755fd15

Browse files
committed
4.3/2: pyscript works without worker
1 parent 2374467 commit 755fd15

File tree

2 files changed

+128
-37
lines changed

2 files changed

+128
-37
lines changed

4.3-carga-graficos-complejos/prueba-2/index.html

Lines changed: 111 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,38 @@
2929
document.getElementById("run-button-py").textContent = 'Run in PyScript';
3030
console.log('PyScript fully loaded');
3131
});
32-
let pyTimerInterval = null;
32+
</script>
33+
<script>
34+
let pyTimer = null;
3335
let pyStartTime = 0;
34-
36+
3537
function startPyTimer() {
3638
pyStartTime = performance.now();
3739
const timerElement = document.getElementById("py-timer-display");
38-
39-
clearInterval(pyTimerInterval);
40-
41-
pyTimerInterval = setInterval(() => {
42-
const elapsed = (performance.now() - pyStartTime) / 1000;
43-
timerElement.textContent = `Timer: ${elapsed.toFixed(4)} s`;
44-
}, 100);
40+
41+
// Usar requestAnimationFrame para máxima fluidez
42+
function updateTimer() {
43+
if (!pyTimer) return;
44+
45+
const elapsedMs = performance.now() - pyStartTime;
46+
const elapsed = (elapsedMs / 1000).toFixed(3); // 3 decimales
47+
timerElement.textContent = `PyScript Timer: ${elapsed} s`;
48+
49+
pyTimer = requestAnimationFrame(updateTimer);
50+
}
51+
52+
cancelAnimationFrame(pyTimer);
53+
pyTimer = requestAnimationFrame(updateTimer);
4554
}
46-
55+
4756
function stopPyTimer() {
48-
clearInterval(pyTimerInterval);
49-
pyTimerInterval = null;
57+
cancelAnimationFrame(pyTimer);
58+
pyTimer = null;
59+
60+
// Última actualización para precisión absoluta
61+
const elapsedMs = performance.now() - pyStartTime;
62+
const elapsed = (elapsedMs / 1000).toFixed(3);
63+
document.getElementById("py-timer-display").textContent = `PyScript Timer: ${elapsed} s`;
5064
}
5165
</script>
5266
<script>
@@ -58,12 +72,6 @@
5872
document.getElementById("output").innerText += `PLT: ${loadTime.toFixed(2)} ms`;
5973
});
6074

61-
var startTimerWebAssembly;
62-
63-
function runPyBenchmark() {
64-
startTimerWebAssembly = performance.now();
65-
}
66-
6775
function clearCell(elementId) {
6876
const operations = ['output', 'exact'];
6977
operations.forEach(op => {
@@ -75,33 +83,111 @@
7583
}
7684
</script>
7785
<script>
86+
let memoryMeasurements = {};
87+
88+
function measureMemory(phase) {
89+
if (performance.memory) {
90+
memoryMeasurements[phase] = {
91+
usedJSHeapSize: performance.memory.usedJSHeapSize,
92+
totalJSHeapSize: performance.memory.totalJSHeapSize,
93+
jsHeapSizeLimit: performance.memory.jsHeapSizeLimit,
94+
timestamp: performance.now()
95+
};
96+
97+
if (Object.keys(memoryMeasurements).length > 1) {
98+
const phases = Object.keys(memoryMeasurements);
99+
const prevPhase = phases[phases.length - 2];
100+
const diff = memoryMeasurements[phase].usedJSHeapSize -
101+
memoryMeasurements[prevPhase].usedJSHeapSize;
102+
103+
if (phase === 'final') {
104+
const outputDiv = document.getElementById("pyscript-output");
105+
const memoryInMB = Math.round((diff / 1024) / 1024);
106+
outputDiv.innerHTML += `<div>Memory: ~${memoryInMB} MB</div>`;
107+
}
108+
}
109+
} else {
110+
console.warn("performance.memory API not available");
111+
}
112+
}
113+
</script>
114+
115+
<script>
116+
// Variables de medición interactividad
117+
let relayoutEvents = 0;
118+
let fpsMeasurements = [];
119+
let fpsInterval = null;
120+
121+
function startFPSMeasurement(duration = 3000) {
122+
let start = performance.now();
123+
let frames = 0;
124+
fpsMeasurements = [];
125+
126+
function measure() {
127+
frames++;
128+
let now = performance.now();
129+
fpsMeasurements.push(1000 / (now - start));
130+
start = now;
131+
if (now - pyStartTime < duration) {
132+
requestAnimationFrame(measure);
133+
} else {
134+
const avgFPS = fpsMeasurements.reduce((a, b) => a + b, 0) / fpsMeasurements.length;
135+
console.log("Average FPS during interaction:", avgFPS.toFixed(2));
136+
document.getElementById("pyscript-output").innerHTML += `<div>Average FPS: ${avgFPS.toFixed(2)}</div>`;
137+
}
138+
}
139+
requestAnimationFrame(measure);
140+
}
141+
142+
function attachRelayoutListener(container) {
143+
container.on('plotly_relayout', function() {
144+
startFPSMeasurement(3000);
145+
relayoutEvents++;
146+
console.log("plotly_relayout event count:", relayoutEvents);
147+
});
148+
}
149+
78150
function clearGraphContainer(id) {
79151
const container = document.getElementById(id);
152+
// Limpieza más agresiva para Plotly
153+
if (container.data) Plotly.purge(container);
80154
container.innerHTML = "";
81155
}
82156

83157
function displayPlotPy(graph_json) {
84158
const container = document.getElementById("graph-container-py");
85-
container.innerHTML = "";
159+
160+
// Limpiar completamente antes de renderizar
161+
clearGraphContainer("graph-container-py");
162+
163+
// Resetear mediciones
164+
fpsMeasurements = [];
165+
relayoutEvents = 0;
166+
86167
const parsed = JSON.parse(graph_json);
87-
Plotly.newPlot(container, parsed.data, parsed.layout);
168+
Plotly.newPlot(container, parsed.data, parsed.layout).then(() => {
169+
attachRelayoutListener(container);
170+
});
88171
}
89172
</script>
90173
<body>
91174
<script type="py" src="python/main.py" config="json/pyscript-main.json"></script>
92-
<h1>Graph Rendering Benchmark (Matplotlib/Canva)</h1>
175+
<h1>Generation of time series graphs (Plotly.py/Canva)</h1>
93176

94177
<h2 id="js-timer-display">JS Timer: 0.00 s</h2>
95-
<h2 id="py-timer-display">Timer: 0.00 s</h2>
178+
<h2 id="py-timer-display">PyScriptTimer: 0.00 s</h2>
96179

97180
<label for="num-executions">Repeticiones:</label>
98181
<input type="number" id="num-executions-javascript" value="1" min="1">
99182
<button id="run-button-js" onclick="runJSBenchmark()">Run in JavaScript</button>
100183

101184

102-
<label for="num-executions">Repeticiones:</label>
103-
<input type="number" id="num-executions-pyscript" value="1" min="1">
104-
<button id="run-button-py" onclick="runPyBenchmark()" py-click="js_run_py_benchmark">Run in PyScript (Loading...)</button>
185+
<label for="num-series">N° Series:</label>
186+
<input type="number" id="num-series-py" value="5" min="1" max="100">
187+
<label for="num-points">N° Puntos:</label>
188+
<input type="number" id="num-points-py" value="10000" min="1000" step="1000">
189+
<button id="run-button-py" onclick="startPyTimer()" py-click="js_run_py_benchmark">
190+
Run in PyScript (Loading...)</button>
105191

106192
<pre id="output"></pre>
107193
<div id="graph-containers" style="display: flex; flex-direction: row;">

4.3-carga-graficos-complejos/prueba-2/python/main.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,36 @@
1-
import asyncio
21
import time
3-
import json
42
import numpy as np
53
from pyscript import display
64
import js # type: ignore
75
from plotly.graph_objects import Figure
86
from plotly.io import to_json
7+
import asyncio
98

109

1110
async def js_run_py_benchmark(event):
1211
try:
13-
# Limpieza y preparación
12+
await asyncio.sleep(0.1)
13+
1414
js.clearCell("pyscript")
1515
js.clearGraphContainer("graph-container-py")
16-
js.startPyTimer()
16+
17+
js.measureMemory('before')
18+
19+
# Obtener valores desde inputs HTML
20+
num_series = int(js.document.getElementById("num-series-py").value)
21+
num_points = int(js.document.getElementById("num-points-py").value)
1722

1823
# 1. Generación de datos
1924
start_time = time.perf_counter()
20-
num_series = 5
21-
num_points = 10_000
2225
x = np.linspace(0, 10, num_points)
2326
rng = np.random.default_rng()
2427
ys = [np.sin(x + i) + rng.normal(0, 0.1, num_points)
2528
for i in range(num_series)]
2629
data_gen_time = (time.perf_counter() - start_time) * 1000
2730

28-
# 2. Renderizado
31+
js.measureMemory('after_data_gen')
32+
33+
# 2. Renderizado del gráfico
2934
render_start = time.perf_counter()
3035
fig = Figure()
3136
for i, y in enumerate(ys):
@@ -36,29 +41,29 @@ async def js_run_py_benchmark(event):
3641
name=f"Serie {i+1}",
3742
line=dict(width=1)
3843
)
39-
4044
fig.update_layout(
4145
title="Series Temporales (PyScript)",
4246
width=700,
4347
height=500
4448
)
45-
4649
render_time = (time.perf_counter() - render_start) * 1000
4750

48-
# 3. Exportar la figura a JSON
51+
js.measureMemory('after_render')
52+
4953
graph_json = to_json(fig)
5054

51-
# 4. Mostrar resultados: Enviar el JSON al JS
5255
js.displayPlotPy(graph_json)
5356
update_ui({
5457
"data_gen_time": data_gen_time,
5558
"render_time": render_time,
5659
"total_time": (time.perf_counter() - start_time) * 1000
5760
})
58-
js.stopPyTimer()
5961

62+
js.measureMemory('final')
6063
except Exception as e:
6164
display(f"Error: {e}", target="pyscript-output")
65+
finally:
66+
js.stopPyTimer()
6267

6368

6469
def update_ui(metrics):

0 commit comments

Comments
 (0)
0