8000 FrontEnd 4.6/2: Finished · JayAyAre/PyScript-vs-JavaScript@c47b60c · GitHub
[go: up one dir, main page]

Skip to content

Commit c47b60c

Browse files
committed
FrontEnd 4.6/2: Finished
1 parent c7b84e6 commit c47b60c

File tree

8 files changed

+149
-152
lines changed

8 files changed

+149
-152
lines changed
Lines changed: 66 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,81 @@
1-
(() => {
2-
let worker = null;
3-
let jsTimer = null;
4-
let jsStartTime = 0;
1+
// main.js
2+
let worker = null;
3+
let worker_time = 0;
54

6-
function startJsTimer() {
7-
jsStartTime = performance.now();
8-
const timerElement = document.getElementById("js-timer-display");
9-
function updateTimer() {
10-
if (!jsTimer) return;
11-
const elapsed = ((performance.now() - jsStartTime) / 1000).toFixed(
12-
3
13-
);
14-
timerElement &&
15-
(timerElement.textContent = `JS Timer: ${elapsed} s`);
16-
jsTimer = requestAnimationFrame(updateTimer);
17-
}
18-
cancelAnimationFrame(jsTimer);
19-
jsTimer = requestAnimationFrame(updateTimer);
20-
}
5+
async function javascriptBenchmark() {
6+
try {
7+
window.clearCell("javascript-output");
8+
window.showExecutionLoader();
219

22-
function stopJsTimer() {
23-
cancelAnimationFrame(jsTimer);
24-
jsTimer = null;
25-
const elapsed = ((performance.now() - jsStartTime) / 1000).toFixed(3);
26-
const timerElement = document.getElementById("js-timer-display");
27-
timerElement && (timerElement.textContent = `JS Timer: ${elapsed} s`);
28-
}
10+
const startWorkerTime = performance.now();
11+
await initializeWorker();
12+
const workerTime = performance.now() - startWorkerTime;
2913

30-
function setText(id, text) {
31-
const el = document.getElementById(id);
32-
if (el) el.textContent = text;
33-
else console.warn(`Element with id \"${id}\" not found`);
34-
}
14+
const repetitions = parseInt(
15+
document.getElementById("num-repetitions-javascript").value,
16+
10
17+
);
3518

36-
function clearMetrics(prefix) {
37-
[
38-
"worker",
39-
"training",
40-
"inference",
41-
"accuracy",
42-
"memory",
43-
"total",
44-
].forEach((id) => {
45-
setText(`${prefix}-${id}`, "");
19+
const id = `js-${Date.now()}`;
20+
21+
const resultJson = await new Promise((resolve, reject) => {
22+
function onMessage(e) {
23+
if (e.data.id !== id) return;
24+
worker.removeEventListener("message", onMessage);
25+
if (e.data.error) {
26+
reject(new Error(e.data.error));
27+
} else {
28+
resolve(e.data.json);
29+
}
30+
}
31+
worker.addEventListener("message", onMessage);
32+
worker.postMessage({
33+
id,
34+
type: "js_run_js_benchmark",
35+
repetitions,
36+
});
4637
});
38+
39+
const r = JSON.parse(resultJson);
40+
displayResult(r);
41+
} catch (err) {
42+
console.error("Benchmark error:", err);
43+
document.getElementById(
44+
"javascript-output"
45+
).textContent = `Error: ${err.message}`;
46+
} finally {
47+
window.hideExecutionLoader();
4748
}
49+
}
4850

49-
async function javascriptBenchmark() {
50-
const outputEl = document.getElementById("javascript-output");
51-
try {
52-
outputEl && (outputEl.textContent = "");
53-
startJsTimer();
54-
clearMetrics("javascript");
5551

56-
const startWorkerTime = performance.now();
57-
if (!worker) {
58-
worker = new Worker(new URL("worker.js", import.meta.url), {
59-
type: "module",
60-
});
61-
}
62-
const workerTime = performance.now() - startWorkerTime;
63-
setText("javascript-worker", `${workerTime.toFixed(2)} ms`);
52+
function displayResult(r) {
53+
const out = document.getElementById("javascript-output");
6454

65-
const repetitions = parseInt(
66-
document.getElementById("num-repetitions-js")?.value || "1",
67-
10
68-
);
69-
const id = `js-${Date.now()}`;
55+
out.innerHTML = `
56+
<div>Worker init time: ${worker_time.toFixed(2)} ms</div>
57+
<div>Training time: ${r.training_time_ms.toFixed(2)} ms
58+
<div>Inference time: ${r.inference_time_ms.toFixed(2)} ms</div>
59+
<div>Accuracy: ${r.accuracy.toFixed(2)} %</div>
60+
<div>Model size: ${r.model_size_mb.toFixed(2)} MB</div>
61+
<div>Overall time: ${r.overall_time_ms.toFixed(2)} ms</div>
62+
`
63+
}
7064

71-
const resultJson = await new Promise((resolve, reject) => {
72-
function onMessage(e) {
73-
if (e.data.id !== id) return;
74-
worker.removeEventListener("message", onMessage);
75-
if (e.data.error) reject(new Error(e.data.error));
76-
else {
77-
console.log("Mensaje recibido del worker:", e.data);
78-
resolve(e.data.json);
79-
}
80-
}
81-
worker.addEventListener("message", onMessage);
82-
worker.postMessage({
83-
id,
84-
type: "js_run_js_benchmark",
85-
repetitions,
86-
});
87-
});
88-
89-
const r = JSON.parse(resultJson);
90-
displayResult(r);
91-
} catch (err) {
92-
console.error("Benchmark error:", err);
93-
outputEl && (outputEl.textContent = `Error: ${err.message}`);
94-
} finally {
95-
stopJsTimer();
65+
function initializeWorker() {
66+
return new Promise((resolve) => {
67+
if (worker) {
68+
resolve();
69+
return;
9670
}
97-
}
9871

99-
function displayResult(r) {
100-
setText("javascript-training", `${r.training_time_ms.toFixed(2)} ms`);
101-
setText("javascript-inference", `${r.inference_time_ms.toFixed(2)} ms`);
102-
setText("javascript-accuracy", `${r.accuracy.toFixed(2)} %`);
103-
setText("javascript-memory", `${r.model_size_mb.toFixed(2)} MB`);
104-
setText("javascript-total", `${r.overall_time_ms.toFixed(2)} ms`);
105-
}
72+
const workerPath = window.location.origin +
73+
window.document.body.dataset.jsPath +
74+
"worker.js";
10675

107-
document.addEventListener("DOMContentLoaded", () => {
108-
const btn = document.getElementById("run-button-js");
109-
if (btn) btn.addEventListener("click", javascriptBenchmark);
76+
worker = new Worker(workerPath, { type: "module" });
77+
resolve();
11078
});
79+
}
11180

112-
window.javascriptBenchmark = javascriptBenchmark;
113-
})();
81+
window.runJSBenchmark = javascriptBenchmark;

Astro-TFG/public/scripts/4.6-patrones/prueba-2/version-1/javascript/worker.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import KNN from "https://cdn.skypack.dev/ml-knn";
22

33
self.addEventListener("message", async (e) => {
4-
const { id, type, workerTime, repetitions } = e.data;
4+
const { id, type, repetitions } = e.data;
55
if (type !== "js_run_js_benchmark") return;
66

7-
const DIGITS_URL = "/json/digits.json";
7+
const DIGITS_URL = "../json/digits.json";
88
const resp = await fetch(DIGITS_URL);
99
const { data, target } = await resp.json();
1010

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"files": {
3-
"/python/worker.py": "worker.py"
3+
"../python/worker.py": "worker.py"
44
}
5-
}
5+
}
Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,56 @@
11
import time
22
import json
3-
from pyscript import PyWorker, display, document
3+
from pyscript import PyWorker, display
44
import js # type: ignore
5+
import asyncio
56

67
worker = None
8+
worker_time = 0
79

810

911
async def launch_worker(event):
10-
global worker
11-
js.clearMetrics("pyscript")
12-
js.startPyTimer()
12+
try:
13+
global worker, worker_time
14+
start_worker_time = time.perf_counter()
1315

14-
start_w = time.perf_counter()
15-
if worker is None:
16-
worker = PyWorker(
17-
"./python/worker.py",
18-
type="pyodide",
19-
config="./json/pyscript-worker.json"
20-
)
21-
await worker.ready
22-
worker_time = (time.perf_counter() - start_w) * 1000
23-
display(f"{worker_time:.2f} ms", target="pyscript-worker")
16+
if worker is None:
17+
base = js.window.location.origin + js.window.document.body.dataset.pyPath
18+
worker = PyWorker(
19+
f"{base}worker.py",
20+
type="pyodide",
21+
config=f"{base.replace('python', 'json')}pyscript-worker.json"
22+
)
23+
await worker.ready
2424

25-
result_json = await worker.sync.js_run_py_benchmark(worker_time)
26-
result = json.loads(result_json)
25+
worker_time = (time.perf_counter() - start_worker_time) * 1000
26+
json_str = await worker.sync.do_analisis()
27+
result = json.loads(json_str)
2728

28-
display_result(result)
29-
js.stopPyTimer()
29+
display_result(result)
30+
js.window.hideExecutionLoader()
31+
except Exception as e:
32+
display(f"Error: {e}", target="pyscript-output")
3033

3134

3235
def display_result(r):
33-
display(f"{r['training_time_ms']:.2f} ms", target="pyscript-training")
34-
display(f"{r['inference_time_ms']:.2f} ms", target="pyscript-inference")
35-
display(f"{r['accuracy']:.2f} %", target="pyscript-accuracy")
36-
display(f"{r['model_size_mb']:.2f} MB", target="pyscript-memory")
37-
display(f"{r['overall_time_ms']:.2f} ms", target="pyscript-total")
36+
global worker_time
37+
display(f"Worker init time: {worker_time:.2f} ms",
38+
target="pyscript-output")
39+
display(
40+
f"Training time: {r['training_time_ms']:.2f} ms", target="pyscript-output")
41+
display(
42+
f"Inference time: {r['inference_time_ms']:.2f} ms", target="pyscript-output")
43+
display(
44+
f"Accuracy: {r['accuracy']:.2f} %", target="pyscript-output")
45+
display(
46+
f"Model size: {r['model_size_mb']:.2f} MB", target="pyscript-output")
47+
display(
48+
f"Overall time: {r['overall_time_ms']:.2f} ms", target="pyscript-output")
49+
50+
51+
def js_run_py_benchmark(event):
52+
js.clearCell('pyscript-output')
53+
asyncio.ensure_future(launch_worker(None))
54+
55+
56+
js.window.run_py_benchmark = js_run_py_benchmark

Astro-TFG/public/scripts/4.6-patrones/prueba-2/version-1/python/worker.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
from sklearn.neighbors import KNeighborsClassifier
1010

1111

12-
async def js_run_py_benchmark(worker_time):
12+
async def do_analisis():
1313
await asyncio.sleep(0.1)
1414
start_overall = time.perf_counter()
15-
reps = int(document.getElementById("num-repetitions-py").value)
15+
reps = int(document.getElementById("num-repetitions-pyscript").value)
1616

1717
data = load_digits()
1818
X, y = data.data, data.target
@@ -57,4 +57,4 @@ async def js_run_py_benchmark(worker_time):
5757
}
5858
return json.dumps(result)
5959

60-
sync.js_run_py_benchmark = js_run_py_benchmark
60+
sync.do_analisis = do_analisis

Astro-TFG/src/components/schedule/BenchmarkHeader.astro

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ import NavegationButton from '../schedule/NavegationButton.astro';
4646
</NavegationButton>
4747
<div class="group relative w-full sm:w-auto">
4848
<button
49+
id="menu-button"
50+
type="button"
4951
class="ease-in-out group-hover:bg-slate-700 flex w-full items-center justify-center gap-2 rounded-lg px-5 py-2 text-white opacity-70 transition-all duration-200 group-hover:text-purple-400 group-hover:opacity-100 hover:shadow-lg"
5052
>
5153
<svg
@@ -60,7 +62,8 @@ import NavegationButton from '../schedule/NavegationButton.astro';
6062
<slot name="menu">Menú</slot>
6163
</button>
6264
<ul
63-
class="absolute right-0 z-10 hidden max-h-80 w-90 grid-cols-1 gap-2 rounded-lg bg-gray-800 p-2 shadow-xl group-hover:grid sm:grid-cols-2 lg:grid-cols-3"
65+
id="menu-list"
66+
class="absolute inset-x-0 z-10 whitespace-normal break-words hidden max-h-80 w-full sm:w-[26rem] grid grid-cols-1 gap-2 overflow-auto rounded-lg bg-gray-800 p-2 shadow-xl group-hover:grid sm:grid-cols-2 lg:grid-cols-3"
6467
>
6568
{
6669
benchmarks.map((benchmark, index) => {
@@ -72,7 +75,7 @@ import NavegationButton from '../schedule/NavegationButton.astro';
7275
<li class="rounded-lg">
7376
<a
7477
href={link}
75-
class="flex items-center gap-2 px-4 py-2 opacity-70 transition-all duration-200 ease-in-out hover:cursor-pointer hover:rounded-lg hover:bg-slate-700 hover:text-purple-400 hover:opacity-100 hover:shadow-lg focus:ring focus:ring-purple-400"
78+
class="block items-center px-4 py-2 opacity-70 transition-all duration-200 ease-in-out hover:cursor-pointer hover:rounded-lg hover:bg-slate-700 hover:text-purple-400 hover:opacity-100 hover:shadow-lg focus:ring focus:ring-purple-400"
7679
>
7780
{index + 1}. {benchmark[0]}
7881
</a>
@@ -84,4 +87,28 @@ import NavegationButton from '../schedule/NavegationButton.astro';
8487
</div>
8588
</div>
8689
</div>
90+
<script type="module">
91+
const button = document.getElementById('menu-button');
92+
const menu = document.getElementById('menu-list');
93+
94+
let isOpen = false;
95+
96+
button.addEventListener('click', () => {
97+
isOpen = !isOpen;
98+
menu.classList.toggle('hidden', !isOpen);
99+
menu.classList.toggle('grid', isOpen); // para mostrar el grid si está abierto
100+
});
101+
102+
// Opcional: cerrar al hacer clic fuera
103+
document.addEventListener('click', (event) => {
104+
if (
105+
!button.contains(event.target) &&
106+
!menu.contains(event.target)
107+
) {
108+
isOpen = false;
109+
menu.classList.add('hidden');
110+
menu.classList.remove('grid');
111+
}
112+
});
113+
</script>
87114
</header>

Astro-TFG/src/data/tests.js

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -336,17 +336,7 @@ export const tests = [
336336
title: 'Version optimizada',
337337
description:
338338
'Esta prueba implementa una única versión optimizada que simula un escenario de entrenamiento y evaluación de un modelo de Machine Learning del mundo real. Utiliza el dataset Iris para entrenar un clasificador Random Forest durante múltiples repeticiones configurables. En cada repetición se mide el tiempo de entrenamiento, el tiempo de inferencia, y la precisión obtenida. Al finalizar, se calcula el promedio de estas métricas y se estima el tamaño del modelo resultante en memoria.',
339-
jsLibs:
340-
[
341-
{
342-
type: 'importmap',
343-
content: `{
344-
"imports": {
345-
"ml-random-forest": "https://cdn.jsdelivr.net/npm/ml-random-forest@2.1.0/dist/random-forest.js"
346-
}
347-
}`
348-
}
349-
],
339+
jsLibs: null,
350340
pyConfig: "pyscript-main.json",
351341
useNode: false,
352342
useBackend: false,
@@ -365,10 +355,10 @@ export const tests = [
365355
description:
366356
'Esta prueba contiene una única versión optimizada que simula un escenario de clasificación real utilizando el dataset Digits. En cada repetición configurable, se entrena un modelo de vecinos más cercanos (KNN) con los datos de entrenamiento, se realiza interferencia sobre el conjunto de prueba y se calcula la precisión obtenida. Se miden y promedian los tiempos de entrenamiento, interferencia y precisión. Además, se estima el tamaño en memoria del modelo final para reflejar su impacto computacional.',
367357
jsLibs: null,
368-
pyConfig: null,
358+
pyConfig: "pyscript-main.json",
369359
useNode: false,
370360
useBackend: false,
371-
inputs: null,
361+
inputs: ["num-repetitions"],
372362
graph: false,
373363
},
374364
],

0 commit comments

Comments
 (0)
0