tawasuyu

tawasuyu/llimphi

Sovereign retained-mode GPU UI framework in Rust (wgpu+vello+taffy+parley), Elm loop, 40+ widgets.

Rust 614Markdown 274TOML 149RON 310606 Definitions

⎇ main widgets/text-input/examples/bench_wrap.rs Rust · 78 lines · 3.2 KB History Who touched what raw

chore: refresco desde el monorepo — vello 0.9 / wgpu 29, 120 miembros d251eb32b · Sergio ·

1//! Mide cuánto tarda el ajuste blando del text-area y el hit-testing del mouse
2//! según el largo del texto. Diagnóstico de T11 (COLA-SHUMA): el input se cuelga
3//! al clickear con mucho texto. Evidencia en TEXTO (Regla 8 del repo), no en
4//! pantalla.
5//!
6//! Tres columnas, tres caminos distintos:
7//! - `wrap` — partir el texto en renglones visuales (`renglones_visuales`).
8//! - `click2d` — click en el text-area: wrap + mapear x→columna dentro del
9//!   renglón (`place_caret_2d`).
10//! - `click1L` — click en el campo de **una línea**, donde el texto llega
11//!   entero al mapeo x→columna (`Press`). No pasa por el wrap. Se mide con el
12//!   caret **al final** —como queda tras tipear o pegar—, que es el caso caro:
13//!   ahí el campo está desplazado (`scroll_x`) y el punto clickeado cae al
14//!   fondo del texto, no en los primeros caracteres.
15//!
16//! Lo que se mira no es el número absoluto (depende de la máquina) sino cómo
17//! crece: duplicar el texto tiene que duplicar el costo, no cuadruplicarlo.
18
19use llimphi_widget_text_input::{MemClipboard, TextInputEvent, TextInputState};
20use std::time::Instant;
21
22fn main() {
23    let mut clip = MemClipboard::new();
24    // Ancho típico del input del cajón, y un texto de palabras normales.
25    const ANCHO: f32 = 900.0;
26    let palabra = "cargo ";
27
28    // Calentar el typesetter: la primera medición de todo el proceso paga la
29    // carga de la fuente (~150 ms) y, sin esto, se la come la primera fila de
30    // la tabla y parece un costo del texto corto.
31    {
32        let mut st = TextInputState::new();
33        st.fijar_ancho_caja(ANCHO);
34        st.set_text("cargo cargo cargo");
35        let _ = st.renglones_visuales();
36        st.pointer_click(100.0, 13.0);
37    }
38
39    println!(
40        "{:>8}  {:>10}  {:>9}  {:>9}  {:>9}",
41        "chars", "renglones", "wrap ms", "click2d ms", "click1L ms"
42    );
43    for n in [200usize, 500, 1_000, 2_000, 4_000, 8_000, 16_000, 32_000] {
44        let texto: String = palabra.repeat(n / palabra.len() + 1);
45        let texto = &texto[..n];
46
47        let mut st = TextInputState::new();
48        st.fijar_ancho_caja(ANCHO);
49        st.set_text(texto);
50
51        let t0 = Instant::now();
52        let filas = st.renglones_visuales();
53        let ms = t0.elapsed().as_secs_f64() * 1000.0;
54
55        // El gesto del bug: un click en una posición puntual del texto.
56        let t1 = Instant::now();
57        st.place_caret_2d(430.0, 40.0);
58        let ms_click = t1.elapsed().as_secs_f64() * 1000.0;
59
60        // El mismo gesto en el campo de una línea: el texto no está envuelto,
61        // así que el mapeo x→columna lo ve entero. Con el caret al final el
62        // campo está desplazado y el click cae al fondo del texto.
63        let mut una = TextInputState::new();
64        una.fijar_ancho_caja(ANCHO);
65        una.set_text(texto);
66        una.editor_mut().set_caret_at(0, n);
67        let t2 = Instant::now();
68        una.handle(TextInputEvent::Press(430.0), &mut clip);
69        let ms_1l = t2.elapsed().as_secs_f64() * 1000.0;
70
71        println!("{n:>8}  {filas:>10}  {ms:>9.1}  {ms_click:>10.1}  {ms_1l:>10.1}");
72
73        if ms > 4_000.0 || ms_1l > 4_000.0 {
74            println!("  (corto acá: ya es inusable)");
75            break;
76        }
77    }
78}