← Volver a artículosDescubrimientoSeptember 19, 202618 min de lecturaCopy article

Kitsune2: Búsquedas 251x Más Rápidas, la Ruta de Actualización 33x, y el Rumor Iniciado 15x Más Temprano

Dentro de una mañana de experimentos sobre la capa de red de Holochain: cómo los nodos encuentran pares, recuperan datos faltantes, y reanudan el rumor, y qué pequeños parches de 6 cambiaron en el camino.

Developed by Robert E. Beckner III (Merlin) | rbeckner.com

He estado despertando alrededor de 4:30 a.m. últimamente, justo antes del amanecer, y disfrutándolo. El 19 de septiembre usé esa mañana para iniciar un laboratorio sobre Kitsune2, la capa de red peer-to-peer bajo Holochain, y busqué dónde estaba gastando tiempo.Para 12:20 p.m., el laboratorio había producido 6 parches. Búsquedas de endpoint: 251× más rápidas en 10,000 identidades retenidas. La ruta de actualización peer que las llama: 33× más rápida. Inicio de rumor después de una recuperación completada: 3,002 ms reducidos a 202 ms. Tráfico de solicitud de ráfaga: 96.9% menos mensajes. 3 de los cambios repararon trabajo que estaba esperando innecesariamente, o esperando algo que nunca sucedería.He estado programando por más de 25 años y construyendo con IA desde GPT-3. Lo uso para aislar algo que me importa o que aún no entiendo, trabajar en ello, y probar lo que creemos haber aprendido. Me encanta esa parte: convertir una pregunta en un experimento y ver qué sostiene. Esta mañana, con agentes de codificación IA, apliqué ese enfoque a la maquinaria que permite a los nodos de Holochain mantenerse actualizados entre sí.Las aplicaciones Holochain comparten datos entre computadoras participantes, o nodos. Cada participante mantiene su propio historial firmado y ayuda a validar y almacenar una porción de los datos compartidos de la aplicación. Esa tienda compartida es la distributed hash table, o DHT. Las copias viven con varios pares, por lo que los datos pueden seguir disponibles cuando su autor se desconecta. Guía de DHT de Holochain explica cómo se distribuyen esas responsabilidades.Kitsune2 maneja la comunicación punto a punto debajo de esto. Imagina un nodo poniéndose al día: aprende dónde se pueden alcanzar los pares, compara lo que tiene con lo que ellos tienen, y solicita las piezas que le faltan. Gossip es el intercambio mediante el cual los pares descubren esas diferencias; fetch recupera las operaciones faltantes, las unidades de datos que Kitsune2 transfiere. El nodo receptor las entrega al almacén de operaciones de su host. Holochain maneja su validación e integración.
Diagram source
graph TD
    A[Aprender las identidades y puntos finales de los pares] --> B[Comparar datos mediante gossip]
    B --> C[Identificar operaciones faltantes]
    C --> D[Recuperar operaciones de los pares]
    D --> E[Entregar las operaciones recibidas al almacén del host]
    E --> F[Señalar que las recuperaciones pendientes han finalizado]
    F e1@--> B
    e1@{ animation: fast }
Copy source
Los parches se sitúan a lo largo de esa secuencia. Algunos reducen el trabajo que un nodo realiza; otros lo dejan avanzar cuando el trabajo ya ha terminado. Las cifras anteriores miden esos pasos particulares en nodos de prueba locales.

Qué movieron realmente cada uno de los cambios de 6#

Fijamos el punto de partida en el commit ascendente 06555ee, fuente de desarrollo 0.6.0-dev.1. Cada comparación usa esa línea base más la secuencia de parches registrada. Las etiquetas de abajo conectan los hallazgos con nuestros registros de experimentos; todos los parches de 6 ahora están enviados para revisión ascendente.
EtiquetaQué cambióResultado medido
K3aLlamar al helper de drenaje existente cuando una descarga terminaInicio de gossip después de una descarga completada: 3,002 → 202 ms
K3bBloqueo del receptor limitado al dequeueLa concurrencia efectiva fue 1. Los workers configurados ahora se superponen realmente
K3cPropiedad de admisión marcada por generaciónCancelado el strand de los llamadores 0 con claves pendientes. Baseline stranded 8
K3d-P1Limpieza de respuesta basada en conjuntos1.9–6.1× procesamiento de respuesta más rápido en cargas pendientes grandes
K3d-P2Agrupación opt-in de pares iguales (predeterminado 1)Explosiones: 87.5–96.9% menos mensajes de solicitud
K1Revertir URL al índice del agenteEn 10,000 identidades retenidas: actualizaciones 21–33×, búsquedas 118–251× más rápidas, para 3.10× memoria de almacenamiento
La primera reparación reconecta la finalización de la recuperación con la tarea de gossip que la espera. El cambio llama a un asistente existente que informa a los oyentes que el mapa pendiente se ha vaciado. Probamos tanto una recuperación completada como una recuperación mantenida deliberadamente abierta.
Gossip initiation after a fetch completes, with the control that must not move (ms)
Chart datamilliseconds
Upstream 06555eeWith the drain notification restored
Fetch completed3001202
Fetch still pending (control)30023001
Después de la finalización, gossip puede continuar. Mientras la recuperación permanece pendiente, ambas versiones aún alcanzan el temporizador de respaldo. La prueba aislada anterior midió 3,001 → 202 ms; la reproducción combinada posterior midió 3,002 → 202 ms. Ambos usaron un respaldo de 3,000 ms y un retraso inicial de 200 ms. La diferencia aproximada de 15× registra qué ruta tomó la tarea: esperar el respaldo o despertarse en la finalización.

Cada cambio vive en una sola crate, y 5 de las 6 en un solo archivo#

Una crate Rust es un paquete de código. Todos los parches 6 viven en la crate principal, que contiene los registros pares y la maquinaria de obtención. Cambian cómo el gossip obtiene sus datos y señales de finalización sin editar el algoritmo de gossip o el transporte de red subyacente. El batching agrega un campo de configuración core opcional.
EtiquetaArchivoLíneas
K1core/src/factories/core_known_peers.rs+33 / −10
K3acore/src/factories/core_fetch.rs+1
K3bcore/src/factories/core_fetch.rs+11 / −3
K3ccore/src/factories/core_fetch.rs+71 / −53
K3d-P1core/src/factories/core_fetch.rs+6 / −1
K3d-P2core/src/factories/core_fetch.rs, 1 archivo de prueba+89 / −17
5 parches se apilan en un orden grabado en core_fetch.rs, que solicita operaciones faltantes y procesa respuestas. El parche restante se encuentra en core_known_peers.rs, el registro retenido de cuál identidad está asociada con qué punto final de red. Luego aplicamos todos los 6 a un solo árbol fuente y los ejecutamos juntos.

Los datos habían llegado, pero el gossip todavía estaba esperando#

CoreFetch mantiene un mapa de las operaciones que ha pedido y de quién. Cuando llega la respuesta de un peer y las operaciones se almacenan correctamente, el código elimina esos identificadores del mapa. Otras partes del archivo, el send-error path y el peer-cleanup path, llaman a un helper llamado notify_listeners_if_queue_drained justo después de que eliminan las entradas. El success path nunca lo llamó.Un nodo puede expandir la porción del DHT que almacena, llamada su storage arc. Para hacer eso, necesita ponerse al día con los datos dentro del rango mayor. En el arc-growth path que probamos, el gossip espera a que los fetches pendientes terminen antes de iniciar con un peer, con un timer como fallback. Los datos llegaron y el pending map se vació, pero la tarea que esperaba esa señal siguió dormida hasta que expiró el timer.
Diagram source
sequenceDiagram
    participant G as Gossip arc-growth loop
    participant F as CoreFetch
    participant P as Peer
    G->>F: Register a drain waiter
    P->>F: Final response, operations stored
    F->>F: retain() empties the pending map
    Note over F: helper exists, never called
    F--xG: Notification that never arrives
    G->>G: Initiate after the roughly 3-second fallback
Copy source
Revisar después de la finalización oculta la diferencia: un waiter recién registrado ve el mapa vacío y devuelve inmediatamente. Registramos el nuestro antes de la finalización. Una vez que los datos se almacenaron, ese waiter todavía no tenía notificación en el código original; con el parche, recibió una. Esto repara la transición entre recibir datos y comenzar el siguiente intercambio de gossip.También revisamos respuestas parciales, errores de store, varios listeners, y listeners registrándose como requests completados o nuevo trabajo llegó. Una respuesta parcial debe dejar el waiter pendiente; solo completar la última fetch pendiente debe despertarlo.

5 trabajadores fueron configurados, y 1 estaba enviando realmente#

El lado saliente de CoreFetch ejecuta un número configurado de tareas de trabajador que extraen de un canal compartido. El bucle se escribió así:rustCopy source
while let Some(..) = outgoing_request_rx.lock().await.recv().await {    // send the request}
El bloqueo permite que el trabajador 1 tome la siguiente solicitud del cuadro compartido. Pero Rust mantiene ese guardián de bloqueo temporal vivo a través del cuerpo de este while let, incluida la espera por el envío de red. Mientras el trabajador 1 enviaba, el otro 4 ni siquiera podía recoger su siguiente solicitud. Todas las solicitudes aún podían llegar eventualmente, así que una prueba de entrega podría pasar mientras la concurrencia configurada quedaba sin usar.Movimos la recepción a un bloque corto para que el bloqueo se libere antes de que comience el envío. Los trabajadores aún se turnan para recoger solicitudes, luego las envían concurrentemente. Un envío lento ya no mantiene el bloqueo de la cola mientras otros trabajadores tienen solicitudes listas.
Outgoing sends in flight at the same moment, by configured worker count
Chart dataconcurrent sends observed
Upstream 06555eeDequeue-scoped guard
1 worker11
2 workers12
5 workers15
La medición mantiene cada envío abierto con un reloj pausado y cuenta cuántos han entrado antes de que se libere cualquiera, luego confirma que nada entra más allá del límite configurado.

Cancelar un llamante dejó el nodo esperando operaciones no enviadas de 8#

Una solicitud de búsqueda pasa por los registros de 2: el mapa pendiente indica lo que el nodo está esperando, y la cola saliente contiene trabajo para los trabajadores de envío. request_ops, el método que solicita operaciones, añadió todo un lote al mapa pendiente antes de esperar espacio en esa cola.Si el llamante fue cancelado mientras esperaba capacidad, algunas operaciones ya habían sido marcadas como pendientes aunque ningún trabajador las hubiera recibido. Llenamos la cola, cancelamos un llamante bloqueado, y dejamos que todas las solicitudes admitidas de 16,385 terminaran. Las operaciones de 8 permanecieron pendientes. Nunca entraron en la cola saliente, por lo que no hubo respuesta en su camino para limpiarlas.Eso se conecta directamente a la primera reparación: una notificación de finalización no puede dispararse mientras el mapa todavía contiene trabajo sin terminar. Aquí, la propia contabilidad del nodo lo mantenía esperando.El parche reserva primero la capacidad de la cola, luego registra y encola la operación sin otra espera entre esos pasos. Cada entrada también lleva una etiqueta de generación, así que la limpieza de un envío fallido anterior no puede borrar una solicitud más nueva para la misma operación. El trabajo ya admitido sobrevive a la cancelación del llamante; el trabajo que aún espera admisión no deja ninguna entrada pendiente atrás.Esto repara la propiedad de las solicitudes. Los límites de memoria totales siguen siendo una pregunta de diseño separada, ya que un llamante aún puede suministrar un lote grande.

Menos mensajes de solicitud, con un límite sobre cuán grande puede crecer cada uno#

Un nodo que se pone al día puede necesitar muchas operaciones del mismo par. El formato de solicitud de Kitsune2 ya admite una lista de identificadores, pero el código saliente envía 1 por mensaje. Antes de combinar esas solicitudes, verificamos cómo se manejarían las respuestas más grandes.Para cada operación pendiente, la limpieza de respuesta escaneó la lista de identificadores devueltos para ver si podía eliminar esa entrada. Con 8,192 entradas pendientes y 1,024 identificadores devueltos, eso repite una gran cantidad de búsquedas. Construir un HashSet de los identificadores devueltos hace que cada verificación de membresía sea barata; el procesamiento de la respuesta midió 6.1× más rápido en ese caso. Con solo 16 identificadores devueltos, almacenar los datos dominaba y el cambio aportó poco.Luego combinamos las solicitudes listas para el mismo par. En un estallido de 64 pequeñas operaciones, los tamaños de lote de 8 y 32 redujeron los mensajes de solicitud en 87.5% y 96.9%, respectivamente.
Burst behaviour relative to the default batch size of 1 (percent of control)
Chart datapercent of control
Request messagesElapsed time
Batch 1 (control)100105.4
Batch 812.572.6
Batch 323.167.7
El estallido terminó aproximadamente 27–32% antes. Las mismas operaciones todavía tenían que transferirse y almacenarse; el ahorro estaba en cuántas solicitudes las transportaban. El control batch-1 midió 105.4% del tiempo transcurrido base, mostrando aproximadamente 5% deriva de tiempo incluso con el batching inactivo.Un trabajador combina solo solicitudes que ya están listas, así que una solicitud solitaria nunca espera que un lote se llene. La división de lotes usa tanto un límite de identificador configurado como un umbral de solicitud codificado en 4,096-bytes. Contar ítems por sí solo no restringe su tamaño total; la prueba con 200 identificadores los divide en varios mensajes con límite. Un solo identificador todavía se envía si por sí solo excede ese umbral, así que esto no es una restricción universal de tamaño de cable. Las respuestas llevan los datos reales y necesitarían un límite de tamaño separado en el nodo que responde.El candidato mantiene el tamaño de lote 1 como su valor predeterminado y acepta las configuraciones existentes sin cambios. Dejamos la opción de lotes más grandes porque la prueba separada para una sola solicitud produjo resultados inconsistentes de latencia final, cubiertos a continuación.

Quitar el escaneo del camino de actualización valió 33×, y 251× en la propia búsqueda#

CoreKnownPeers recuerda identidades y los puntos finales de red asociados con ellas. Varias identidades pueden compartir un punto final, y una identidad bloqueada aún necesita ser identificable después de haber sido eliminada del almacén de pares activo. 10,000 identidades retenidas por lo tanto significa un historial de identidades en este almacén, no 10,000 computadoras conectadas a la vez.En una actualización del almacén de pares, el control de acceso pregunta qué identidades pertenecen al punto final. La búsqueda, get_by_url, escaneó todo el mapa retenido bajo un bloqueo cada vez. A medida que ese historial crecía, actualizar la información actual del par se volvía más costoso.Añadimos un índice desde el punto final URL a las identidades asociadas con él: HashMap<Url, HashSet<AgentId>>. Los registros originales siguen siendo autoritativos. Cuando una identidad cambia de punto final, el índice la mueve al conjunto correspondiente; la búsqueda puede entonces ir directamente a ese conjunto. Ambas versiones pasaron las verificaciones de resultados 19,422 cubriendo actualizaciones, anuncios obsoletos, eliminaciones y puntos finales compartidos.
Microseconds per 16-advertisement update call (log scale)
Chart datamicroseconds per update call
retained identitiesUpstream linear scanDerived URL index
1006.8574.911
1,00018.1034.774
10,000154.8494.72
Cada llamada programada arriba inserta 16 anuncios y ejecuta los oyentes de control de acceso. En 10,000 identidades retenidas, cayó de aproximadamente 155 µs a 4.72 µs, una ganancia pareada 33×. La versión indexada permanece casi plana en estos tamaños porque esos oyentes ya no escanean el historial creciente.Medido en el API en lugar de a través del llamador, la propia búsqueda pasa de un escaneo a un hash. Un fallo en 10,000 identidades retenidas cayó de 11,423 ns a 45 ns, una ganancia pareada 251×, y un solo acierto de 9,309 ns a 79 ns, 118×. Una consulta que devuelve muchas identidades sigue escalando con lo que devuelve, por lo que el caso de URL compartido gana 4.4× en lugar de 2 órdenes de magnitud. El 251× es el resultado de búsqueda aislado. El 33× mide la llamada de actualización más grande que lo usa; estas ganancias no pueden sumarse ni multiplicarse.
Requested store memory at 10,000 retained identities, by endpoint shape
Chart datamegabytes
UpstreamWith the index
Mixed endpoints1.23.71
All shared1.21.74
All URL-less1.21.2
3.10× en una tienda mixta, un extra 2.51 MB en 10,000 identidades. Cuando cada identidad comparte un punto final, el mapa derivado es pequeño y el costo cae a 1.45×. Cuando ninguna identidad tiene un URL no hay nada que derivar y el costo es cero. Esos números son bytes solicitados por el asignador para la tienda retenida, no la memoria total del nodo.

Con todas las correcciones 6 juntas, el nodo podría terminar y continuar#

La reproducción combinada usó los componentes reales de chisme, búsqueda, acceso a pares y almacén de memoria de Kitsune2, comunicándose a través de su transporte de prueba en memoria. Ejecutamos una secuencia de 5 pasos en los árboles de origen y parcheados:
  1. Actualizar información del par. Una identidad cambia punto final. La información obsoleta que llega después deja el registro más reciente intacto, y una identidad bloqueada sigue siendo resoluble para el control de acceso. Ambas versiones pasan; el índice preserva las decisiones existentes.
  2. Iniciar chisme después de que una búsqueda termine. El nodo parcheado inicia después de 202 ms. El original toma el camino de respaldo a 3,002 ms.
  3. Recibir datos fuera de orden. Las operaciones solicitadas por 3 llegan como respuestas 4, incluida una duplicada. Ambas versiones las almacenan de manera consistente y asocian los recuentos de bytes con la operación correcta.
  4. Terminar la búsqueda. Las operaciones almacenadas pueden recuperarse. El nodo parcheado también despierta al oyente que se registró mientras esas operaciones estaban pendientes.
  5. Continuar después de un par fallido. Un fallo controlado de envío borra el estado de solicitud de ese par. Otro par suministra la operación, el mapa pendiente se vacía, y una búsqueda subsiguiente tiene éxito. En el original, las comprobaciones de notificación de finalización fallan.
Las pruebas de interacción separadas combinaron cancelación con envíos concurrentes y agrupación combinada con notificación de finalización. Las reparaciones se mantuvieron juntas: el trabajo admitido completado, las admisiones canceladas no dejaron entradas huérfanas, y los oyentes despertaron después de la respuesta final.Esto nos lleva tan lejos como los datos recibidos en el almacén del host y el siguiente paso de red puede proceder. La validación e integración de Holochain todavía siguen fuera de este laboratorio. Aún no hemos medido cuánto acortan estos cambios el tiempo total de actualización de un nodo real.

Lo que cada ganancia cuesta#

El índice cuesta memoria y hace que los cambios de endpoint sean más caros. En la prueba de pequeño almacén original, actualizar un conjunto fijo de identidades a nuevas URLs se ejecutó a 0.946× la velocidad base con identidades 100 retenidas. A 10,000, un escrito aislado de cambio de endpoint costó 3.68× tanto. Mantener el índice extra tiene un precio; los ahorros de búsqueda deben reembolsarlo.Debido a que ese compromiso es real, buscamos la carga de trabajo donde el índice pierde. 36 configuraciones fueron predeclaradas antes de medir, 432 ejecuciones emparejadas ejecutadas, y las transcripciones de resultados se han hasheado idénticamente entre variantes.
Paired speedup across the 36-config workload envelope, by mix (log scale)
Chart datapaired speedup
retained identitiesSteady, no rebind100% rebindShared endpointsURL-less heavy
1001.611.471.421.09
1,0007.26.264.122.13
10,00055.5636.425.5512.16

Reference line, parity: 1

Cada carga de trabajo en esta matriz más amplia tuvo una mediana por encima de la paridad, incluida la mezcla donde cada actualización aceptada cambiaba un endpoint: 1.47× a 100 identidades y 36.42× a 10,000. Esas actualizaciones también disparan búsquedas de control de acceso, y sus ahorros superaron los escrituras adicionales. Esta carga de trabajo más amplia difiere de la prueba de conjunto fijo anterior; su resultado positivo deja esa regresión de pequeño almacén en el registro.El caso de 100 identidades, mayormente URL-menos sigue inconcluso: su mediana 1.09× incluyó un resultado pareado por debajo de la paridad. Todavía necesitamos trazas de nodos reales que muestren conteos de identidad retenida, cambios de endpoint y frecuencia de búsqueda antes de recomendar el índice para una carga de trabajo particular.Los envíos concurrentes expusieron una interacción de limpieza. Una vez que los trabajadores podían superponerse, la limpieza de un envío fallido podría ejecutarse mientras otra solicitud al mismo par estaba en vuelo. Eso hizo que la limpieza existente a nivel de par fuera más amplia que el trabajo que había fallado. El parche de propiedad redujo la eliminación a entradas que todavía pertenecían a esa generación de solicitud. Probar los parches juntos importó aquí.La latencia de solicitud única de la agrupación sigue inconclusa. Medimos p95, el tiempo dentro del cual 95% de solicitudes terminan. Para una solicitud enviada sola, la ejecución final del trabajador mostró 1.01–1.08× la base p95; la reejecución independiente mostró 1.44–1.58×. Estos accesorios tardan decenas de microsegundos, y sus controles también se desviaron. La mejora de ráfaga se reprodujo, pero el resultado de la solicitud única no se estabilizó, por lo que los lotes más grandes siguen siendo opt-in.

Las comparaciones repetidas y los envíos detenidos siguen abiertos#

También examinamos 2 otras partes de la misma secuencia de sincronización. Ninguna produjo un parche aceptado.Comparando lo que ya tienen los pares (K4). Gossip usa resúmenes compactos de datos almacenados para encontrar diferencias. En la prueba más grande, producir y comparar una instantánea sin cambios materializó 262,144 hashes; repetirlo 10 veces produjo la misma salida cada vez. Reutilizar un resumen previo parece atractivo, pero la tienda host puede cambiar sin una señal fiable para invalidar ese resultado guardado. Un resumen en caché podría entonces ocultar una diferencia entre pares. Las alternativas que evaluamos también quedaron por debajo del ahorro de tiempo requerido 20% en la tienda en memoria. Las mediciones de una tienda Holochain real son la siguiente pieza faltante.Recuperándose cuando un envío de gossip se detiene (K2). Leer la fuente planteó una pregunta sobre un envío que mantiene un bloqueo que la tarea de tiempo de espera también necesita. También necesitábamos establecer qué sucede con el flujo de transporte Iroh subyacente si ese envío se cancela a mitad de camino. El proveedor de agentes bloqueó el trabajo en el controlador de reproducción, por lo que la prueba de tiempo de ejecución nunca se completó. Esto sigue siendo una preocupación no probada, sin parche ni resultado de fiabilidad.

Lo que medimos, y lo que queda por medir#

Estos experimentos se ejecutaron en el código fuente de desarrollo 0.6.0-dev.1, en un M4 Max compartido Apple con 16 núcleos lógicos. Usamos nodos de prueba locales y transportes en memoria, sin fijación de núcleo ni un segundo host físico. Los resultados cubren componentes nombrados y sus interacciones. El rendimiento de la red, la convergencia de toda la red, la memoria total del nodo y la latencia de la aplicación Holochain siguen sin medirse.El método sigue mi trabajo sobre desarrollo impulsado por benchmarks. Registramos cada pregunta y umbral de aceptación, mantuvimos el código fuente y los fixtures fijos dentro de cada comparación, y guardamos comandos, muestras y fallos en recibos de solo anexado.Para las reparaciones 3, las mismas pruebas fallaron en el código original en las aserciones esperadas y pasaron con el parche. Para las optimizaciones, ambas versiones tuvieron que preservar el comportamiento, luego las mediciones tuvieron que cumplir el umbral declarado. Las ejecuciones de tiempo alternaron el orden y mantuvieron la compilación fuera de la ventana medida. Un agente supervisor volvió a ejecutar los comandos de aceptación sobre el código congelado antes de aceptar cada resultado; el desacuerdo sobre la latencia de solicitud única permaneció en el informe final.El paquete completado contiene 204 directorios de recibos. Las pruebas combinadas fueron aceptadas a las 12:17 p.m., y los resultados terminales se registraron a las 12:20 p.m. Se mantuvo una verificación de cierre final a las 2:38 p.m. Los 6 parches están ahora abiertos para revisión ascendente: notificación de finalización, concurrencia de trabajadores, propiedad de admisión, limpieza de respuesta, agrupación de solicitudes, y indexación de puntos finales.

Atribuciones clave#

Por mí. El propio laboratorio: mi método basado en benchmarks, apuntado a Kitsune2 para encontrar dónde estaba gastando tiempo.Por GPT-6 Astra. Las reparaciones de notificación de finalización y de propiedad de admisión: el diagnóstico, el parche y las pruebas que fallan en el código original. También afinó este artículo a partir de los registros del laboratorio.Por GLM-5.3. La reparación de concurrencia de trabajadores, la limpieza y agrupación de respuestas, la matriz de carga de configuración 36 para el índice, el perfilado de resumen DHT detrás de la pregunta abierta K4 y la reproducción combinada de todos los parches 6.Por IA. El índice de punto final y sus mediciones, un agente supervisor que volvió a ejecutar cada aceptación sobre el código fuente congelado antes de que el resultado se contabilizara, y el primer borrador de este artículo.Críticas que se mantuvieron.Llegado juntos. La secuencia de recuperación que sigue el artículo: un nodo aprende a sus pares, compara lo que posee, recupera lo que le falta, lo almacena y continúa, con cada parche colocado en el paso que cambia.Construido sobre. Las fábricas de componentes reemplazables del equipo central de Holochain y el transporte en memoria, que permiten al laboratorio probar estos comportamientos en componentes reales de Kitsune2.#benchmarking#distributed-systems#rust#performance#AI#agents#open-source#experiential#insights—Robert E. Beckner III (Merlin)Continuar leyendoAnteriorLa Inteligencia No Puede Obedecer: Juicio, Autoridad y lo que Muestra una RefusalSiguienteLos errores de almacenamiento en caché de prompts pueden costar a su organización casi 6x más en cada turno de IAQwen 3.8-27B en un M1 Ultra: De 12.1 a 20.3 tok/s por Medir TodoDescubrimientoAugust 14, 202610 min de lecturaMTPLX en un M1 Ultra: El 25 tok/s Ajusta Eso Sirvió 16.5DescubrimientoAugust 15, 20269 min de lecturaEl Último CLI: Reconstruyendo la Base 51 de las Herramientas que Fui Construido ContraDescubrimientoAugust 19, 202612 min de lecturaProyectos relacionados175-Página manuscrita chinaAI InnovationAIA - Asesor de IAAI Innovation