← Retour aux articlesDécouverteSeptember 19, 202613 min de lectureCopy article

Kitsune2: Recherches 251x Plus Rapides, le Chemin de Mise à Jour 33x, et Gossip Démarré 15x Plus Tôt

Dans une matinée d’expériences sur la couche réseau de Holochain : comment les nœuds trouvent des pairs, récupèrent les données manquantes, et reprennent le gossip, et ce que 6 petits correctifs ont changé en cours de route.

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

Je me suis réveillé autour de 4:30 a.m. ces derniers temps, juste avant le lever du soleil, et l’ai apprécié. Le 19 septembre, j’ai utilisé ce matin pour lancer un laboratoire sur Kitsune2, la couche réseau pair-à-pair sous-jacente à Holochain, et j’ai cherché où il passait son temps.À 12:20 p.m., le laboratoire avait produit 6 correctifs. Recherches de points de terminaison : 251× plus rapides à 10,000 identités conservées. Le chemin de mise à jour pair qui les appelle : 33× plus rapide. Initiation du gossip après une récupération terminée : 3,002 ms à 202 ms. Trafic de requêtes burst : 96.9% moins de messages. 3 des changements réparés le travail qui attendait inutilement, ou attendait quelque chose qui ne se produirait jamais.Je code depuis plus de 25 ans et construis avec l’IA depuis GPT-3. Je l’utilise pour isoler quelque chose qui m’importe ou que je ne comprends pas encore, le traiter, et tester ce que nous pensons avoir appris. J’aime cette partie : transformer une question en expérience et voir ce qui tient. Ce matin, avec des agents de codage IA, j’ai appliqué cette approche à la machinerie qui permet aux nœuds Holochain de rester mutuellement à jour.Les applications Holochain partagent des données entre les ordinateurs participants, ou nœuds. Chaque participant conserve son propre historique signé et aide à valider et stocker une portion des données partagées de l’application. Ce magasin partagé est la distributed hash table, ou DHT. Les copies vivent avec plusieurs pairs, de sorte que les données peuvent rester disponibles lorsque leur auteur se déconnecte. Guide DHT de Holochain explique comment ces responsabilités sont réparties.Kitsune2 gère la communication pair à pair sous ceci. Imaginez un nœud qui se met à jour : il apprend où les pairs peuvent être atteints, compare ce qu’il possède avec ce qu’ils possèdent, et demande les pièces qu’il lui manque. Gossip est l’échange par lequel les pairs découvrent ces différences ; fetch récupère les opérations manquantes, les unités de données que Kitsune2 transfère. Le nœud récepteur les remet à l’opération store de son hôte. Holochain gère leur validation et intégration.
Diagram source
graph TD
    A[Apprendre les identités et points de terminaison des pairs] --> B[Comparer les données via gossip]
    B --> C[Identifier les opérations manquantes]
    C --> D[Récupérer les opérations des pairs]
    D --> E[Remettre les opérations reçues au magasin hôte]
    E --> F[Signaler que les récupérations en attente sont terminées]
    F e1@--> B
    e1@{ animation: fast }
Copy source
Les correctifs se trouvent le long de cette séquence. Certains réduisent le travail qu’un nœud effectue ; d’autres le laissent passer lorsqu’un travail a déjà été terminé. Les chiffres ci‑dessus mesurent ces étapes particulières sur des nœuds de test locaux.

Ce que chaque changement de 6 a réellement déplacé#

Nous avons fixé le point de départ au commit en amont 06555ee, source de développement 0.6.0-dev.1. Chaque comparaison utilise cette base plus la séquence de correctifs enregistrée. Les étiquettes ci-dessous relient les découvertes à nos dossiers d'expérience ; tous les correctifs 6 sont maintenant soumis pour examen en amont.
ÉtiquetteCe qui a changéRésultat mesuré
K3aAppeler l'assistant drain existant lorsqu'une récupération se termineInitiation de gossip après une récupération terminée : 3,002 → 202 ms
K3bVerrouillage du récepteur limité à la défilementLa concurrence effective était 1. Les travailleurs configurés se chevauchent désormais réellement
K3cPropriété d'admission marquée par générationL'appelant en file d'attente 0 en attente de clés annulées. Baseline en file d'attente 8
K3d-P1Nettoyage de réponse basé sur les ensembles1.9–6.1× traitement de réponse plus rapide à de grandes charges en attente
K3d-P2Option de regroupement par pair identique (par défaut 1)Pics : 87.5–96.9% moins de messages de requête
K1Inverser URL vers l’indice de l’agentÀ 10,000 identités conservées : mises à jour 21–33×, recherches 118–251× plus rapides, pour 3.10× mémoire de stockage
La première réparation reconnecte la complétion de récupération à la tâche de gossip en attente de celle‑ci. Le changement appelle un helper existant qui informe les auditeurs que la carte en attente est vide. Nous avons testé à la fois une récupération complétée et une récupération délibérément maintenue ouverte.
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
Après la complétion, le gossip peut se poursuivre. Pendant que la récupération reste en attente, les deux versions atteignent toujours le minuteur de secours. Le test isolé ci‑dessus a mesuré 3,001 → 202 ms ; la reproduction combinée ultérieure a mesuré 3,002 → 202 ms. Les deux ont utilisé un secours de 3,000 ms et un délai initial de 200 ms. La différence d’environ 15× indique quel chemin la tâche a pris : attendre le secours ou se réveiller à la complétion.

Chaque changement vit dans un seul crate, et 5 des 6 dans un seul fichier#

Un crate Rust est un paquet de code. Tous les patchs 6 vivent dans le crate principal, qui contient les enregistrements pairs et la machinerie de récupération. Ils changent la façon dont le gossip obtient ses données et signaux de complétion sans modifier l'algorithme de gossip ou le transport réseau sous-jacent. Le batching ajoute un champ de configuration core optionnel.
ÉtiquetteFichierLignes
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 fichier de test+89 / −17
5 correctifs empilés dans un ordre enregistré sur core_fetch.rs, qui demande les opérations manquantes et traite les réponses. Le correctif restant se trouve dans core_known_peers.rs, l’enregistrement conservé indiquant quelle identité est associée à quel point de terminaison réseau. Nous avons ensuite appliqué tous les 6 à un seul arbre source et les avons exécutés ensemble.

Les données étaient arrivées, mais le gossip attendait toujours#

CoreFetch garde une carte des opérations qu'il a demandées et de qui. Lorsqu'une réponse d'un peer arrive et que les opérations sont stockées avec succès, le code retire ces identifiants de la carte. D'autres parties du fichier, le chemin send-error et le chemin peer-cleanup, appellent un helper nommé notify_listeners_if_queue_drained juste après avoir retiré les entrées. Le chemin de succès ne l'appelle jamais.Un nœud peut étendre la portion du DHT qu'il stocke, appelée son storage arc. Pour ce faire, il doit rattraper les données dans la plage plus large. Dans le chemin arc-growth que nous avons testé, le gossip attend que les fetchs en attente se terminent avant d'initier avec un peer, avec un timer comme secours. Les données sont arrivées et la carte en attente a été vidée, mais la tâche attendant ce signal est restée endormie jusqu'à ce que le timer expire.
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
Vérifier après la complétion masque la différence : un nouvel attendant enregistré voit la carte vide et retourne immédiatement. Nous avons enregistré le nôtre avant la finalisation. Une fois les données stockées, ce serveur n’avait toujours pas de notification sur le code original ; avec le correctif, il en a reçu une. Cela répare le passage entre la réception des données et le démarrage du prochain échange de gossip.Nous avons également vérifié les réponses partielles, les erreurs de stockage, plusieurs auditeurs, et les auditeurs s’inscrivant comme requêtes terminées ou de nouveaux travaux arrivés. Une réponse partielle doit laisser le serveur en attente ; seule la complétion de la dernière récupération en suspens doit le réveiller.

5 travailleurs étaient configurés, et 1 envoyait réellement#

Le côté sortant de CoreFetch exécute un nombre configuré de tâches de travail tirant d'un seul canal partagé. La boucle a été écrite ainsi :rustCopy source
while let Some(..) = outgoing_request_rx.lock().await.recv().await {    // send the request}
Le verrou permet à 1 travailleur de prendre la prochaine requête de la file partagée. Mais Rust maintient ce verrou temporaire vivant tout au long du corps de ce while let, y compris l'attente pour l'envoi réseau. Pendant que 1 travailleur envoyait, l'autre 4 ne pouvait même pas collecter sa prochaine requête. Toutes les requêtes pouvaient encore arriver finalement, donc un test de livraison pouvait réussir alors que la concurrence configurée restait inutilisée.Nous avons déplacé la réception dans un bloc court afin que le verrou soit libéré avant le début de l'envoi. Les travailleurs continuent de prendre des tours pour collecter les requêtes, puis les envoient simultanément. Un envoi lent ne retient plus le verrou de la file pendant que d'autres travailleurs ont des requêtes prêtes.
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 mesure maintient chaque envoi ouvert avec une horloge en pause et compte combien ont été entrés avant qu'aucun ne soit libéré, puis confirme qu'aucun n'entre jamais au-delà de la limite configurée.

Annuler un appelant laissait le nœud en attente des opérations non envoyées de 8#

Une requête de récupération passe par les enregistrements 2 : la carte en attente indique ce que le nœud attend, et la queue sortante contient le travail pour les travailleurs d'envoi. request_ops, la méthode qui demande des opérations, ajoutait un lot complet à la carte en attente avant d'attendre de la place dans cette queue.Si l'appelant était annulé en attendant la capacité, certaines opérations avaient déjà été marquées en attente même si aucun travailleur ne les avait reçues. Nous avons rempli la queue, annulé un appelant bloqué, et laissé toutes les requêtes 16,385 admises terminer. 8 opérations restaient en attente. Elles n'avaient jamais entré dans la queue sortante, donc il n'y avait aucune réponse en cours pour les effacer.Cela se connecte directement à la première réparation : une notification de complétion ne peut pas se déclencher tant que la carte contient encore du travail non terminé. Ici, la comptabilité propre du nœud le faisait attendre.Le correctif réserve d'abord la capacité de la queue, puis enregistre et met en file d'attente l'opération sans autre attente entre ces étapes. Chaque entrée porte également une balise de génération, donc le nettoyage d'un envoi échoué plus ancien ne peut pas effacer une requête plus récente pour la même opération. Le travail déjà admis survit à l'annulation de l'appelant ; le travail toujours en attente d'admission ne laisse aucune entrée en attente derrière.Cela répare la propriété des requêtes. Les limites de mémoire totale restent une question de conception distincte, puisque l'appelant peut encore fournir un gros lot.

Moins de messages de requête, avec une limite sur la taille maximale de chacun#

Un nœud de mise à jour peut avoir besoin de nombreuses opérations du même pair. Le format de requête de Kitsune2 prend déjà en charge une liste d’identifiants, mais le code sortant envoie 1 par message. Avant de combiner ces requêtes, nous avons vérifié comment les réponses plus grandes seraient gérées.Pour chaque opération en attente, le nettoyage de la réponse parcourait la liste des identifiants retournés pour voir s’il pouvait supprimer cette entrée. Avec 8,192 entrées en attente et 1,024 identifiants retournés, cela répète une grande quantité de recherche. Construire un HashSet des identifiants retournés rend chaque vérification d’appartenance peu coûteuse ; le traitement de la réponse mesurait 6.1× plus rapide dans ce cas. Avec seulement 16 identifiants retournés, le stockage des données dominait et le changement apportait peu.Ensuite nous avons combiné les requêtes prêtes pour le même pair. Dans un pic de 64 petites opérations, les tailles de lot de 8 et 32 ont réduit les messages de requête de 87.5% et 96.9%, respectivement.
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
Le pic s’est terminé environ 27–32% plus tôt. Les mêmes opérations devaient toujours être transférées et stockées ; l’économie provenait du nombre de requêtes qui les transportaient. Le contrôle batch-1 mesurait 105.4% du temps écoulé de référence, montrant un dérive de timing d’environ 5% même avec le batching désactivé.Un worker combine uniquement les requêtes déjà prêtes, donc une requête isolée n’attend jamais un lot pour se remplir. La division de lot utilise à la fois une limite d’identifiant configurée et un seuil de requête encodé en 4,096-bytes. Compter les éléments seul ne contraint pas leur taille totale ; le test avec 200 identifiants les divise en plusieurs messages plafonnés. Un seul identifiant est toujours envoyé s’il dépasse seul ce seuil, donc ce n’est pas une limite universelle de taille de fil. Les réponses portent les données réelles et nécessiteraient une limite de taille séparée sur le nœud répondant.Le candidat conserve la taille de lot 1 comme valeur par défaut et accepte les configurations existantes sans modification. Nous avons laissé l'option des lots plus grands car le test séparé pour une requête isolée a produit des résultats de latence finale incohérents, détaillés ci‑dessous.

Retirer le scan du chemin de mise à jour valait 33×, et 251× sur la recherche elle‑même#

CoreKnownPeers se souvient des identités et des points de terminaison réseau associés à celles‑ci. Plusieurs identités peuvent partager un point de terminaison, et une identité bloquée doit toujours être identifiable après avoir été retirée du magasin de pairs actif. 10,000 identités conservées signifie donc un historique d’identités dans ce magasin, pas 10,000 ordinateurs connectés simultanément.Lors d’une mise à jour du magasin de pairs, le contrôle d’accès demande quelles identités appartiennent au point de terminaison. La recherche, get_by_url, parcourait toute la carte conservée sous un verrou à chaque fois. À mesure que cet historique grandissait, la mise à jour des informations actuelles du pair devenait plus coûteuse.Nous avons ajouté un index du point de terminaison URL vers les identités associées : HashMap<Url, HashSet<AgentId>>`. Les enregistrements originaux restent autoritaires. Lorsqu’une identité change de point de terminaison, l’index la déplace vers l’ensemble correspondant ; la recherche peut alors aller directement à cet ensemble. Les deux versions ont passé les vérifications de résultat 19,422 couvrant les mises à jour, les publicités obsolètes, les suppressions et les points de terminaison partagés.
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
Chaque appel temporel ci‑dessus insère 16 publicités et exécute les auditeurs de contrôle d’accès. À 10,000 identités conservées, la baisse est passée d’environ 155 µs à 4.72 µs, un gain apparié de 33×. La version indexée reste presque plate à travers ces tailles parce que ces auditeurs ne parcourent plus l’historique croissant.Mesuré à la API au lieu de passer par l’appelant, la recherche elle‑même passe d’un scan à un hachage. Un échec à 10,000 identités conservées est passé de 11,423 ns à 45 ns, un gain apparié de 251×, et un seul succès de 9,309 ns à 79 ns, 118×. Une requête qui renvoie de nombreuses identités continue de se mettre à l’échelle avec ce qu’elle renvoie, donc le cas partagé-URL gagne 4.4× plutôt que 2 ordres de grandeur. Le 251× est le résultat de recherche isolé. Le 33× mesure l’appel de mise à jour plus important qui l’utilise ; ces gains ne peuvent pas être ajoutés ou multipliés.
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× sur un magasin mixte, un extra 2.51 MB à 10,000 identités. Quand chaque identité partage un point de terminaison, la carte dérivée est petite et le coût tombe à 1.45×. Quand aucune identité n’a un URL il n’y a rien à dériver et le coût est zéro. Ces nombres sont des octets demandés par l’allocation pour le magasin conservé, pas la mémoire totale du nœud.

Avec tous les correctifs 6 réunis, le nœud pouvait terminer et continuer#

La relecture combinée utilisait les composants réels de gossip, fetch, peer‑access et memory‑store de Kitsune2, communiquant via son transport de test en mémoire. Nous avons exécuté une séquence en 5 étapes sur les arbres source originaux et corrigés :
  1. Mettre à jour les informations du pair. Une identité change de point de terminaison. Les informations obsolètes arrivant plus tard laissent l’enregistrement plus récent intact, et une identité bloquée reste résoluble pour le contrôle d’accès. Les deux versions passent ; l’index préserve les décisions existantes.
  2. Démarrer le gossip après qu’un fetch soit terminé. Le nœud corrigé initie après 202 ms. L’original prend le chemin de secours à 3,002 ms.
  3. Recevoir des données hors séquence. Les opérations demandées 3 arrivent comme des réponses 4, y compris un duplicata. Les deux versions les stockent de façon cohérente et associent les comptes de bytes à l’opération correcte.
  4. Terminer le fetch. Les opérations stockées peuvent être récupérées. Le nœud corrigé réveille également l’écouteur qui s’est enregistré pendant que ces opérations étaient en attente.
  5. Continuer après un pair échoué. Une erreur d’envoi contrôlée efface l’état de requête de ce pair. Un autre pair fournit l’opération, la carte en attente se vide, et un fetch subséquent réussit. Sur l’original, les vérifications de notification de complétion échouent.
Les tests d’interaction séparés combinent l’annulation avec les envois concurrents et le regroupement combiné avec la notification de complétion. Les réparations se sont maintenues : le travail admis terminé, les admissions annulées n’ont laissé aucune entrée orpheline, et les écouteurs se réveillent après la réponse finale.Cela nous amène jusqu’à ce que les données soient reçues dans le magasin hôte et que l’étape réseau suivante puisse se poursuivre. La validation et l’intégration de Holochain suivent toujours des processus externes à ce laboratoire. Nous n’avons pas encore mesuré dans quelle mesure ces changements raccourcissent le temps total de synchronisation d’un nœud réel.

Le coût de chaque gain#

L'index coûte de la mémoire et rend les changements d'endpoint plus coûteux. Dans le test de petite‑stockage original, la mise à jour d'un ensemble fixe d'identités vers de nouvelles URLs s'exécutait à 0.946× la vitesse de référence avec 100 identités conservées. À 10,000, un écrit isolé de changement d'endpoint coûtait 3.68× autant. Maintenir l'index supplémentaire a un prix ; les économies de recherche doivent le rembourser.Parce que ce compromis est réel, nous avons cherché la charge de travail où l'index perd. 36 configurations ont été prédéclarées avant la mesure, 432 exécutions en paires effectuées, et les transcriptions de résultats ont été hachées identiquement entre les 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

Chaque charge de travail dans cette matrice plus large avait une médiane au-dessus de la parité, y compris le mélange où chaque mise à jour acceptée changeait un endpoint : 1.47× à 100 identités et 36.42× à 10,000. Ces mises à jour déclenchent également des recherches de contrôle d'accès, et leurs économies l'emportaient sur les écritures supplémentaires. Cette charge de travail plus large diffère du test à ensemble fixe précédent ; son résultat positif laisse cette régression de petite‑stockage sur le registre.Le cas de 100 identités, majoritairement URL‑less reste inconclusive : sa médiane 1.09× incluait un résultat apparié en dessous de la parité. Nous avons encore besoin de traces de nœuds réels montrant les comptes d'identités conservées, les changements d'endpoint et la fréquence de recherche avant de recommander l'index pour une charge de travail particulière.Les envois concurrents ont exposé une interaction de nettoyage. Une fois que les travailleurs pouvaient se chevaucher, le nettoyage d'un envoi échoué pouvait s'exécuter pendant qu'une autre requête vers le même pair était en vol. Cela rendait le nettoyage global du pair plus large que le travail qui avait échoué. Le correctif de propriété a limité la suppression aux entrées appartenant encore à cette génération de requête. Tester les correctifs ensemble a compté ici.La latence d'unique requête du batch reste inconclusive. Nous avons mesuré p95, le temps dans lequel 95% des requêtes se terminent. Pour une requête envoyée seule, la dernière exécution du travailleur a montré 1.01–1.08× la référence p95 ; la réexécution indépendante a montré 1.44–1.58×. Ces fixtures prennent des dizaines de microsecondes, et leurs contrôles ont également dérivé. L'amélioration par rafale a été reproduite, mais le résultat de la requête unique ne s'est pas stabilisé, donc les lots plus importants restent opt-in.

Les comparaisons répétées et les envois bloqués restent ouverts#

Nous avons également examiné 2 d'autres parties de la même séquence de synchronisation. Aucun n'a produit un correctif accepté.Comparer ce que les pairs détiennent déjà (K4). Gossip utilise des résumés compacts des données stockées pour trouver les différences. Dans le plus grand test, produire et comparer un instantané inchangé a matérialisé 262,144 hachages ; le répéter 10 fois a produit la même sortie à chaque fois. Réutiliser un résumé précédent semble attractif, mais le magasin hôte peut changer sans un signal fiable pour invalider ce résultat sauvegardé. Un résumé mis en cache pourrait alors masquer une différence entre les pairs. Les alternatives que nous avons évaluées ont également échoué à atteindre l'économie de temps requise 20% sur le magasin en mémoire. Les mesures d'un vrai magasin Holochain sont la prochaine pièce manquante.Se rétablir lorsqu'un envoi gossip se bloque (K2). Lire la source a soulevé une question sur un envoi tenant un verrou que la tâche de temporisation doit également utiliser. Nous avons également dû établir ce qui arrive au flux de transport Iroh sous-jacent si cet envoi est annulé en cours de route. Le fournisseur d'agent a bloqué le travail sur le pilote de reproduction, donc le test d'exécution n'a jamais été terminé. Cela reste une préoccupation non testée, sans correctif ni résultat de fiabilité.

Ce que nous avons mesuré, et ce qui reste à mesurer#

Ces expériences ont été menées sur le code source de développement 0.6.0-dev.1, sur 1 Apple M4 Max partagé avec 16 cœurs logiques. Nous avons utilisé des nœuds de test locaux et des transports en mémoire, sans fixation de cœur ni hôte physique supplémentaire. Les résultats couvrent les composants nommés et leurs interactions. Le débit réseau, la convergence de tout le réseau, la mémoire totale du nœud et la latence de l’application Holochain restent non mesurés.La méthode suit mon travail sur le développement piloté par les benchmarks. Nous avons enregistré chaque question et seuil d’acceptation, maintenu la source et les fixtures fixes dans chaque comparaison, et conservé commandes, échantillons et échecs dans des reçus en mode append-only.Pour les 3 réparations, les mêmes tests ont échoué sur le code original aux assertions attendues et ont réussi avec le correctif. Pour les optimisations, les deux versions devaient préserver le comportement, puis les mesures devaient atteindre le seuil indiqué. Les exécutions de timing alternaient l’ordre et maintenaient la compilation hors de la fenêtre mesurée. Un agent superviseur a relancé les commandes d’acceptation sur la source figée avant d’accepter chaque résultat ; le désaccord sur la latence de requête unique est resté dans le rapport final.Le paquet complet contient 204 répertoires de reçus. Les tests combinés ont été acceptés à 12:17 p.m., et les résultats finaux ont été enregistrés à 12:20 p.m. Une vérification finale de clôture a été conservée à 2:38 p.m. Les 6 correctifs sont maintenant ouverts pour examen en amont : notification de complétion, concurrence des travailleurs, propriété d’admission, nettoyage des réponses, groupement des requêtes, et indexation des points de terminaison.

Attributions clés#

Par moi. Le laboratoire lui‑même : ma méthode benchmark-driven, ciblée sur Kitsune2 pour trouver où il passait son temps.Par GPT-6 Astra. Les réparations de notification de complétion et de prise de possession d’admission : le diagnostic, le correctif et les tests qui échouent sur le code original. Il a également affiné cet article à partir des dossiers du laboratoire.Par GLM-5.3. La réparation de concurrence des travailleurs, le nettoyage et le regroupement des réponses, la matrice de charge de configuration 36 pour l’index, le profilage de résumé DHT derrière la question ouverte K4 et la reproduction combinée de tous les patchs 6.Par IA. L’index de point de terminaison et ses mesures, un agent superviseur qui relance chaque acceptation sur le code source figé avant que le résultat ne soit comptabilisé, et le premier brouillon de cet article.Critiques qui ont tenu.Arrivé ensemble. La séquence de rattrapage que l’article suit : un nœud apprend ses pairs, compare ce qu’il possède, récupère ce qu’il lui manque, le stocke, et continue, chaque patch placé à l’étape qu’il modifie.Construit sur. Les usines de composants remplaçables de l’équipe centrale Holochain et le transport en mémoire, qui permettent au laboratoire de tester ces comportements dans de vrais composants Kitsune2.#benchmarking#distributed-systems#rust#performance#AI#agents#open-source#experiential#insights—Robert E. Beckner III (Merlin)Continuer la lecturePrécédentL'intelligence ne peut pas obéir : Jugement, Autorité, et ce qu'un refus révèleSuivantLes erreurs de mise en cache des invites peuvent coûter à votre organisation près de 6x plus à chaque tour d’IAQwen 3.8-27B sur un M1 Ultra : De 12.1 à 20.3 tok/s en Mesurant ToutDécouverteAugust 14, 202610 min de lectureMTPLX sur un M1 Ultra : Le 25 tok/s Tune That Served 16.5DécouverteAugust 15, 20269 min de lectureLe Dernier CLI: Reconstruire la Base 51 sur laquelle mes outils ont été construitsDécouverteAugust 19, 202613 min de lectureProjets connexes175-Page manuscrit chinoisInnovation IAAIA - Conseiller en IAInnovation AI