Ingeniería 10 min de lectura

Un núcleo en Rust para todo el documento

En KapyCAD 2, el documento entero vivirá en un núcleo escrito en Rust, en un solo worker junto al kernel. La interfaz solo preguntará y pintará.

SSergio26 sept 2026
Un núcleo en Rust para todo el documento

Cuarta entrega de la serie «Por dentro de KapyCAD 2», la versión que todavía estamos construyendo. En la anterior explicamos por qué compilamos nuestro propio OpenCascade. En KapyCAD 2, tu documento y todo lo que se decide sobre él estarán en un núcleo escrito en Rust, que será también quien le hable a ese kernel.

Dónde estábamos

La arquitectura con la que nació KapyCAD la describimos en cómo corre un CAD B-Rep en el navegador. El hilo principal, el que pinta la interfaz, guardaba el documento y decidía qué regenerar, en TypeScript. Un worker tenía el kernel de geometría y otro el solver de croquis, cada uno en su WebAssembly. Los tres se hablaban por mensajes, y la lógica del CAD estaba repartida entre TypeScript y esos módulos.

Funcionaba, y sigue funcionando. Pero tenía un problema de fondo que no se arregla a base de remiendos.

El problema de tener la verdad en dos sitios

La «verdad» de una pieza es su documento: los croquis, las operaciones, los parámetros. En el KapyCAD actual, esa verdad está en un sitio y sus consecuencias en otro. El documento vive en el hilo de la interfaz; los sólidos construidos viven dentro del worker del kernel, y el hilo principal solo tiene números que los identifican. Cada edición exige que las partes se pongan de acuerdo.

Cuando no se ponen de acuerdo, aparecen los bugs que más cuesta encontrar:

  • El cuerpo fantasma. Si el hilo principal suelta los sólidos de la regeneración anterior un instante antes de tiempo, lo que ves en pantalla ya no existe en el kernel.
  • Muchas manos escribiendo. La interfaz podía cambiar el documento directamente: había 152 acciones de escritura, y la interfaz llamaba a 51 de ellas desde 129 sitios distintos. Casi cien archivos de interfaz importaban lógica de CAD por su cuenta.
  • Un deshacer que no deshacía de una vez. Al añadir una restricción con varios candidatos en un clic, la entrada de deshacer se cerraba antes de que llegara la respuesta del solver, así que dejaba varias entradas sueltas. Renombrar un parámetro podía romper las fórmulas que lo usaban.
  • Trabajo duplicado. Exportar, analizar o generar una miniatura usaba un segundo kernel, con su propia memoria. Y el servidor y los tests arrancaban los módulos WebAssembly cada uno a su manera, hasta que se distanciaron: una batería en verde podía certificar un kernel con capacidades que el servidor no tenía.

Medimos el transporte entre hilos y costaba unos pocos milisegundos, así que lo que buscábamos era otra cosa: un solo escritor, y que los tests ejecuten lo mismo que ejecutas tú.

Un núcleo, una verdad

En KapyCAD 2, el documento, su evaluación y su historial de deshacer vivirán en un solo worker, el del núcleo. Dentro de ese worker arrancarán los tres módulos WebAssembly: nuestro OpenCascade, el kernel B-Rep; manifold, para las booleanas de malla (por ejemplo, al restar la rosca cosmética de una exportación STL); y kpy-core, nuestro núcleo en Rust, con el documento, la regeneración, el solver de croquis y el intérprete del código de los Smart Objects.

diagram
KapyCAD 2: la interfaz habla con un único núcleo que guarda el documento y los tres módulos WebAssembly; dos ayudantes pequeños no guardan nada

Los tres módulos compartirán hilo con el núcleo porque una regeneración le pregunta al kernel miles de cosas, y un mensaje entre hilos por cada pregunta la haría demasiado lenta. Así, el núcleo llamará al kernel directamente y esperará la respuesta como en cualquier programa normal.

La interfaz y el núcleo se hablarán con un contrato de cuatro canales. En la versión en desarrollo, funcionan así:

  • Comandos, hacia arriba: «inserta esta operación», «cambia este parámetro». La interfaz no espera. Asigna ella misma los identificadores de lo que crea, así puede seguir trabajando, y si el núcleo rechaza el comando, el aviso llega después y se muestra.
  • Parches, hacia abajo: lo que ha cambiado, y nada más. La interfaz tiene una copia de solo lectura del documento que únicamente los parches pueden escribir. Cada parche se confirma al pintarse, para que no se amontonen detrás de una pantalla lenta.
  • Preguntas, en los dos sentidos: «¿cuánto mide esta arista?». Respuestas cortas, sin tocar el documento.
  • Trabajos, a un lado: exportar, preparar una miniatura, calcular una vista previa. Tardan, muestran progreso y se pueden cancelar. Nunca cambian el documento y nunca corren en mitad de una regeneración: esperan su turno.

Dentro del worker quedará algo de TypeScript, pero solo como pegamento: arranca los módulos, mueve bytes de una memoria a otra y encadena los pasos de la regeneración, que es Rust de principio a fin.

Deshacer, sin pelearse

Con el documento en un solo sitio, el historial de deshacer vivirá donde vive el documento, así que será idéntico en el editor, en el servidor y en los tests.

Cada cambio irá dentro de una transacción. En la versión en desarrollo, el núcleo guarda cómo estaba el documento antes y cómo queda después, y eso es una entrada de deshacer, con un nombre que pone el propio núcleo. Lo interesante es qué cuenta como «un cambio». Un gesto es una entrada: mientras arrastras un punto del croquis el documento no se toca, y al soltar se escribe todo de una vez, aunque el arrastre haya durado cien fotogramas. Teclear es una entrada por ráfaga, no por tecla. Y cancelar es volver atrás: si pulsas Escape a mitad de un arrastre, o el núcleo rechaza una colocación, la transacción se aborta y el documento vuelve a como estaba, sin dejar nada a medias en el historial.

diagram
Una edición en KapyCAD 2: del clic al píxel, pasando por una transacción del núcleo

En KapyCAD 2, el clic con varios candidatos será una sola entrada de deshacer, y renombrar un parámetro reescribirá las fórmulas que lo citan, también en una sola entrada. Los dos casos quedaron arreglados en la versión en desarrollo sin tocarlos uno a uno: bastó con que hubiera un único sitio que escribe.

Dos ayudantes pequeños

En el dibujo hay dos workers más, pequeños, y los dos tienen algo en común: no guardan ningún documento.

El ayudante de lenguaje contestará las preguntas del panel de código que llega con KapyCAD 2 (lo presentaremos en la última entrega de la serie): autocompletado, errores, qué significa este símbolo. Es un kpy-core a secas, sin kernel ni documento, que no arranca hasta que el panel le pregunta algo por primera vez; si nunca lo usas, no te cuesta nada. Existe porque el núcleo no se detiene a mitad de una regeneración, y durante el desarrollo una pregunta que llegaba en ese momento esperaba a que acabara: en un engranaje helicoidal, hasta 33 segundos. Para contestar no le hace falta el documento, solo el texto que le pasamos, así que podrá responder en paralelo al núcleo.

El ayudante de arrastre contestará los fotogramas cuando arrastres un punto de un croquis. Lleva su propio kpy-core, una copia mínima del núcleo con el solver de croquis y sin kernel. Al empezar el gesto, la interfaz le pasa el croquis una vez; después solo viajan las posiciones del puntero. Así el ratón nunca espera a que el núcleo termine un paso de regeneración. Al soltar, quien escribe el resultado en el documento sigue siendo el núcleo, en una sola transacción. Cómo se comporta el arrastre en sí lo contamos en la sexta entrega.

Ninguno de los dos guarda documento: una segunda copia que se pudiera escribir nos devolvería al problema de tener la verdad en dos sitios. Los ayudantes contestan preguntas sobre lo que se les da y dejan las decisiones al núcleo.

Mover la lógica a Rust

La regla de KapyCAD 2 es corta: la interfaz no calcula CAD. Pregunta y pinta, y toda la lógica del CAD va en Rust.

Para aplicarla miramos qué clase de código queda; contar líneas no basta. Si quedan siete mil líneas de TypeScript y son de interfaz, perfecto. Si son quinientas pero calculan geometría, no hemos terminado.

Un test vigila la regla. Mide el repositorio entero con una lista de reglas: álgebra de geometría escrita a mano, tolerancias numéricas sueltas, expresiones regulares sobre código del lenguaje, cálculos de geometría hechos con la biblioteca de render 3D, cualquier archivo que escriba el documento por su cuenta, valores por defecto del dominio escondidos en constantes. Cada regla tiene su control rojo, como contamos en la primera entrega: un archivo de ejemplo que la rompe, para demostrar que la regla lo ve. Las excepciones existen, pero cada una tiene nombre y motivo, y la lista de deuda solo puede encoger.

El test tampoco lo ve todo. Hicimos cuatro revisiones manuales, archivo a archivo, que encontraron 63, 73, 65 y 27 restos que se le escapaban. Todos se movieron a Rust, y cada pieza movida se comparó bit a bit con lo que hacía el TypeScript antes de borrarlo (el cómo está en cómo probamos un CAD). Solo en el último tramo, el TypeScript del editor bajó de unas 213 600 líneas a 175 400, y el Rust del núcleo subió de 202 500 a 281 600. Lo que queda en TypeScript es interfaz, render y cableado.

Hay otro guardián, más sencillo: el worker del núcleo tiene prohibido incluir la biblioteca de render 3D, React o el sistema de traducciones. Si algo lo intenta, un test lo nombra.

Qué notarás

El aspecto general no cambiará; lo que cambia se notará al usarlo, y habrá algunas piezas nuevas que contamos en las próximas entregas.

El editor irá más fluido, porque ni el arrastre ni el panel de código esperarán a una regeneración. Las regeneraciones serán más ligeras: el kernel recompilado gastó menos de la mitad de CPU en las piezas que medimos (lo contamos en la entrega anterior). KapyCAD 2 también usará menos memoria, porque exportar ya no levantará un segundo kernel: será un trabajo más del mismo núcleo. Y los módulos arrancarán en paralelo: el núcleo en Rust no esperará a que termine de cargarse el kernel.

Fuera del navegador (la cola del servidor que regenera documentos, el corpus y los tests) se ejecutará el mismo núcleo, sin worker, así que el resultado será el mismo que en tu navegador. La vista previa del gestor de archivos abrirá el mismo núcleo sobre el documento que estás previsualizando. Por el camino encontramos que el STL dependía de cómo hubiera triangulado la pieza el visor; en KapyCAD 2 será determinista y saldrá igual se exporte desde donde se exporte.

La quinta entrega se mete dentro de este núcleo, en el solver de croquis propio que vivirá en él.

S

Escrito por

Sergio

Building Kapy CAD — parametric 3D modelling for 3D printing, in the browser.

Sigue leyendo

Discord