← Zurück zu den ArtikelnEntdeckungSeptember 19, 202611 Min. LesezeitCopy article

Kitsune2: Nachschlagen 251x schneller, der Update-Pfad 33x, und Gossip begann 15x früher

In einem Morgen voller Experimente auf der Netzwerkebene von Holochain: wie Knoten Peers finden, fehlende Daten abrufen und Gossip wieder aufnehmen, und welche 6 kleinen Patches unterwegs geändert haben.

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

Ich bin in letzter Zeit um 4:30 a.m. aufgewacht, kurz vor Sonnenaufgang, und habe es genossen. Am 19. September nutzte ich diesen Morgen, um ein Labor zu Kitsune2, der Peer-to-Peer-Netzwerkebene unter Holochain, zu starten und herauszufinden, wo es Zeit verbrachte.Bis 12:20 p.m. hatte das Labor 6 Patches produziert. Endpunkt-Nachschlagen: 251× schneller bei 10,000 erhaltenen Identitäten. Der Peer-Update-Pfad, der sie aufruft: 33× schneller. Gossip-Initiierung nach einem abgeschlossenen Fetch: 3,002 ms bis 202 ms. Burst-Anfrageverkehr: 96.9% weniger Nachrichten. 3 der Änderungen reparierten Arbeit, die unnötig wartete, oder auf etwas wartete, das niemals passieren würde.Ich programmiere seit mehr als 25 Jahren und baue mit KI seit GPT-3. Ich benutze es, um etwas zu isolieren, das mir wichtig ist oder das ich noch nicht verstehe, es durchzugehen und zu testen, was wir glauben gelernt zu haben. Ich liebe diesen Teil: eine Frage in ein Experiment zu verwandeln und zu sehen, was Bestand hat. Heute Morgen, mit KI-Coding-Agenten, wendete ich diesen Ansatz auf die Mechanik an, die Holochain-Knoten einander aktuell hält.Holochain-Anwendungen teilen Daten über beteiligte Computer, oder nodes. Jeder Teilnehmer hält seine eigene signierte Historie und hilft, einen Teil der gemeinsam genutzten Daten der Anwendung zu validieren und zu speichern. Dieser gemeinsame Speicher ist die distributed hash table, oder DHT. Kopien leben bei mehreren Peers, sodass Daten verfügbar bleiben können, wenn ihr Autor offline geht. Holochain's DHT guide erklärt, wie diese Verantwortlichkeiten verteilt sind.Kitsune2 übernimmt die Peer-to-Peer-Kommunikation darunter. Stell dir vor, ein Knoten holt nach: Er lernt, wo Peers erreichbar sind, vergleicht, was er hält, mit dem, was sie halten, und bittet um die fehlenden Stücke. Gossip ist der Austausch, über den Peers diese Unterschiede entdecken; fetch holt die fehlenden Operationen, die Daten­einheiten, die Kitsune2 überträgt. Der empfangende Knoten übergibt sie dem Operation‑Store seines Hosts. Holochain kümmert sich um deren Validierung und Integration.
Diagram source
graph TD
    A[Peer‑Identitäten und Endpunkte lernen] --> B[Daten über Gossip vergleichen]
    B --> C[Fehlende Operationen identifizieren]
    C --> D[Operationen von Peers abrufen]
    D --> E[Empfangene Operationen dem Host‑Store übergeben]
    E --> F[Signalisieren, dass ausstehende Fetches abgeschlossen sind]
    F e1@--> B
    e1@{ animation: fast }
Copy source
Die Patches liegen entlang dieser Sequenz. Einige reduzieren die Arbeit, die ein Knoten erledigt; andere lassen ihn weitergehen, wenn die Arbeit bereits abgeschlossen ist. Die oben genannten Zahlen messen diese konkreten Schritte auf lokalen Testknoten.

Was jede der 6 Änderungen tatsächlich bewegt hat#

Wir haben den Ausgangspunkt bei dem Upstream-Commit 06555ee, Entwicklungsquelle 0.6.0-dev.1 festgelegt. Jeder Vergleich verwendet diese Basis plus die aufgezeichnete Patch-Sequenz. Die untenstehenden Labels verbinden die Erkenntnisse mit unseren Experimentaufzeichnungen; alle 6 Patches sind jetzt zur Upstream-Überprüfung eingereicht.
LabelWas sich geändert hatGemessener Ergebnis
K3aRufe den vorhandenen Drain-Helfer auf, wenn ein Abruf abgeschlossen istGossip-Initiierung nach einem abgeschlossenen Abruf: 3,002 → 202 ms
K3bEmpfänger-Sperre auf die Entleerung beschränktEffektive Parallelität war 1. Konfigurierte Worker überschneiden sich jetzt wirklich
K3cGenerationstagge-basierte ZugangsbesitzAbgebrochene Aufrufer-Strand 0 ausstehende Schlüssel. Basis-Strand 8
K3d-P1Set-basierte Antwortbereinigung1.9–6.1× schnellere Antwortverarbeitung bei großen ausstehenden Lasten
K3d-P2Opt-in gleiche Peer-Batching (Standard 1)Burst: 87.5–96.9% weniger Anforderungsnachrichten
K1Umkehren URL zum AgentenindexBei 10,000 erhaltenen Identitäten: Updates 21–33×, Lookups 118–251× schneller, für 3.10× Speicher im Store
Die erste Reparatur verbindet das Abrufabschluss mit der Gossip-Aufgabe, die darauf wartet. Die Änderung ruft einen bestehenden Helfer auf, der den Zuhörern mitteilt, dass die ausstehende Karte geleert wurde. Wir haben sowohl einen abgeschlossenen Abruf als auch einen absichtlich offen gehaltenen Abruf getestet.
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
Nach Abschluss kann Gossip fortfahren. Während der Abruf aussteht, erreichen beide Versionen noch den Fallback-Timer. Der oben isolierte Test maß 3,001 → 202 ms; der spätere kombinierte Replay maß 3,002 → 202 ms. Beide verwendeten einen 3,000 ms Fallback und eine 200 ms Anfangsverzögerung. Der ungefähr 15× Unterschied zeichnet auf, welchen Pfad die Aufgabe genommen hat: Warten auf den Fallback oder Aufwachen bei Abschluss.

Jede Änderung lebt in einem Crate, und 5 der 6 in einer einzigen Datei#

Ein Rust Crate ist ein Paket von Code. Alle 6 Patches leben im Core-Crate, der die Peer-Aufzeichnungen und die Fetch-Maschinen enthält. Sie ändern, wie Gossip seine Daten und Abschlusssignale erhält, ohne den Gossip-Algorithmus oder den zugrunde liegenden Netzwerktransport zu bearbeiten. Batching fügt ein optionales Core-Konfigurationsfeld hinzu.
LabelDateiZeilen
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 Testdatei+89 / −17
5 Patches stapeln in einer aufgezeichneten Reihenfolge auf core_fetch.rs, die fehlende Operationen anfordern und Antworten verarbeiten. Der verbleibende Patch befindet sich in core_known_peers.rs, dem erhaltenen Datensatz, welcher angibt, welche Identität mit welchem Netzwerk-Endpunkt verknüpft ist. Wir haben dann alle 6 auf einen einzigen Quellbaum angewendet und sie zusammen ausgeführt.

Die Daten waren angekommen, aber Gossip wartete noch#

CoreFetch behält eine Karte der Operationen, die es angefordert hat, und von wem. Wenn die Antwort eines Peers eintrifft und die Operationen erfolgreich gespeichert werden, entfernt der Code diese Identifikatoren aus der Karte. Andere Teile der Datei, der Send‑Error‑Pfad und der Peer‑Cleanup‑Pfad, rufen einen Helfer namens notify_listeners_if_queue_drained sofort nach dem Entfernen der Einträge auf. Der Erfolgspfad hat ihn nie aufgerufen.Ein Knoten kann den Teil des DHT, den er speichert, erweitern, genannt sein Storage Arc. Dafür muss er die Daten im größeren Bereich nachholen. Im getesteten Arc‑Growth‑Pfad wartet Gossip, bis ausstehende Fetches abgeschlossen sind, bevor es mit einem Peer initiiert, mit einem Timer als Fallback. Die Daten kamen an und die wartende Karte wurde geleert, aber die Aufgabe, die auf dieses Signal wartete, blieb bis der Timer abgelaufen schlummern.
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
Das Prüfen nach Abschluss verbirgt den Unterschied: ein neu registrierter Wartender sieht die leere Karte und gibt sofort zurück. Wir registrierten unsere vor Abschluss. Sobald die Daten gespeichert wurden, hatte dieser Warten noch keine Benachrichtigung im Originalcode; mit dem Patch erhielt er eine. Dies repariert die Übergabe zwischen dem Empfangen von Daten und dem Starten des nächsten Gossip-Austauschs.Wir haben auch teilweise Antworten, Speicherfehler, mehrere Listener und Listener, die sich als abgeschlossene Anfragen registrierten oder neue Arbeit ankamen, überprüft. Eine teilweise Antwort muss den Warten im Status „pending“ lassen; nur das Abschließen des letzten ausstehenden Abrufs sollte ihn wecken.

5 Arbeiter wurden konfiguriert, und 1 hat tatsächlich gesendet#

Die ausgehende Seite von CoreFetch führt eine konfigurierte Anzahl von Arbeiteraufgaben aus, die von einem gemeinsamen Kanal ziehen. Die Schleife wurde so geschrieben:rustCopy source
while let Some(..) = outgoing_request_rx.lock().await.recv().await {    // send the request}
Das Schloss lässt 1 Arbeiter die nächste Anfrage aus der gemeinsamen Warteschlange nehmen. Aber Rust hält diesen temporären Schloss‑Guard während des gesamten Körpers dieses while let lebendig, einschließlich des Wartens auf den Netzwerksendvorgang. Während 1 Arbeiter sendete, konnte der andere 4 nicht einmal seine nächste Anfrage sammeln. Alle Anfragen konnten schließlich noch eintreffen, sodass ein Zustellungstest bestehen konnte, während die konfigurierte Parallelität ungenutzt blieb.Wir haben das Empfangen in einen kurzen Block verschoben, sodass das Schloss freigegeben wird, bevor das Senden beginnt. Arbeiter nehmen immer noch abwechselnd Anfragen entgegen, dann senden sie sie gleichzeitig. Ein langsames Senden hält die Warteschlangen‑Schloss nicht mehr, während andere Arbeiter Anfragen bereit haben.
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
Die Messung hält jedes Senden offen mit einer pausierten Uhr und zählt, wie viele eingetreten sind, bevor einer freigegeben wird, und bestätigt dann, dass nichts über die konfigurierte Grenze hinaus eintritt.

Das Abbrechen eines Aufrufers ließ den Knoten auf 8 ungesendete Operationen warten#

Eine Abrufanfrage durchläuft 2 Datensätze: die ausstehende Karte sagt, worauf der Knoten wartet, und die ausgehende Warteschlange hält Arbeit für die Sendewerkzeuge. request_ops, die Methode, die nach Operationen fragt, fügte eine ganze Charge zur ausstehenden Karte hinzu, bevor sie auf Platz in dieser Warteschlange wartete.Wenn der Aufrufer während des Wartens auf Kapazität abgebrochen wurde, waren einige Operationen bereits als ausstehend markiert, obwohl kein Arbeiter sie erhalten hatte. Wir füllten die Warteschlange, brachen einen blockierten Aufrufer ab und ließen alle 16,385 zugelassenen Anfragen abschließen. 8 Operationen blieben ausstehend. Sie sind nie in die ausgehende Warteschlange eingetreten, daher gab es keine Antwort auf dem Weg, sie zu löschen.Das verbindet sich direkt mit der ersten Reparatur: eine Abschlussbenachrichtigung kann nicht feuern, während die Karte noch unvollendete Arbeit enthält. Hier hielt die eigene Buchhaltung des Knotens ihn in Warteschleife.Das Patch reserviert zuerst die Warteschlangenkapazität, dann zeichnet die Operation auf und legt sie ohne ein weiteres await zwischen diesen Schritten ein. Jeder Eintrag trägt auch ein Generationstag, sodass die Bereinigung einer älteren fehlgeschlagenen Sendung eine neuere Anfrage für dieselbe Operation nicht löschen kann. Bereits zugelassene Arbeit überlebt die Abbruch des Aufrufers; Arbeit, die noch auf Zulassung wartet, hinterlässt keinen ausstehenden Eintrag.Dies repariert das Eigentum der Anfragen. Gesamte Speichergrenzen bleiben eine separate Designfrage, da ein Aufrufer immer noch eine große Charge liefern kann.

Weniger Anforderungsnachrichten, mit einer Begrenzung, wie groß jede wachsen kann#

Ein nachholender Knoten kann viele Operationen vom selben Peer benötigen. Kitsune2's Anforderungsformat unterstützt bereits eine Liste von Identifikatoren, aber der ausgehende Code sendet 1 pro Nachricht. Bevor wir diese Anfragen zusammenfügten, haben wir geprüft, wie größere Antworten gehandhabt würden.Für jede wartende Operation scannte die Antwortbereinigung die Liste der zurückgegebenen Identifikatoren, um zu sehen, ob sie diesen Eintrag entfernen konnte. Mit 8,192 wartenden Einträgen und 1,024 zurückgegebenen Identifikatoren wiederholt sich das große Maß an Suche. Das Erstellen eines HashSet der zurückgegebenen Identifikatoren macht jeden Mitgliedschaftstest billig; die Antwortverarbeitung wurde in diesem Fall 6.1× schneller gemessen. Mit nur 16 zurückgegebenen Identifikatoren dominierte das Speichern der Daten und die Änderung brachte wenig.Dann kombinierten wir bereitgestellte Anfragen für denselben Peer. In einem Burst von 64 kleinen Operationen reduzierten Chargengrößen von 8 und 32 die Anforderungsnachrichten um 87.5% und 96.9%, jeweils.
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
Der Burst endete etwa 27–32% früher. Die gleichen Operationen mussten immer noch übertragen und gespeichert werden; die Einsparung lag darin, wie viele Anfragen sie trugen. Die Batch-1-Kontrolle zeigte 105.4% des Basiszeitraums, was ungefähr 5% Timing-Drift zeigte, selbst bei inaktiver Batching.Ein Worker kombiniert nur Anfragen, die bereits bereit sind, sodass eine einzelne Anfrage nie auf ein Batch wartet, um sich zu füllen. Das Aufteilen von Chargen verwendet sowohl ein konfiguriertes Identifikatorlimit als auch einen 4,096-Byte-kodierten Anforderungsgrenzwert. Das Zählen von Elementen allein begrenzt ihre Gesamtgröße nicht; der Test mit 200 Identifikatoren teilt sie in mehrere begrenzte Nachrichten auf. Ein einzelner Identifikator wird immer noch gesendet, wenn er allein diesen Grenzwert überschreitet, daher ist dies keine universelle Drahtgrößenbegrenzung. Antworten tragen die tatsächlichen Daten und würden ein separates Größenlimit für den antwortenden Knoten benötigen.Der Kandidat behält die Batchgröße 1 als Standard bei und akzeptiert bestehende Konfigurationen unverändert. Wir haben größere Batches als Opt-in belassen, weil der separate Test für eine einzelne Anfrage inkonsistente Endverzögerungsresultate erzeugte, wie unten erläutert.

Das Entfernen der Suche aus dem Aktualisierungspfad war 33× wert, und 251× auf die Suche selbst#

CoreKnownPeers merkt sich Identitäten und die mit ihnen verbundenen Netzwerkendpunkte. Mehrere Identitäten können einen Endpunkt teilen, und eine blockierte Identität muss immer noch identifizierbar sein, nachdem sie aus dem aktiven Peer-Store entfernt wurde. 10,000 behaltenen Identitäten bedeutet daher eine Historie von Identitäten in diesem Store, nicht 10,000 gleichzeitig verbundene Computer.Bei einer Peer-Store-Aktualisierung fragt die Zugriffskontrolle, welche Identitäten zum Endpunkt gehören. Die Suche, get_by_url, scannte die gesamte behaltenen Karte unter einem Lock jedes Mal. Als diese Historie wuchs, wurde das Aktualisieren aktueller Peer-Informationen teurer.Wir fügten einen Index von Endpunkt URL zu den damit verbundenen Identitäten hinzu: HashMap<Url, HashSet<AgentId>>`. Die ursprünglichen Datensätze bleiben autoritativ. Wenn sich eine Identität den Endpunkt ändert, verschiebt der Index sie in die entsprechende Menge; die Suche kann dann direkt zu dieser Menge gehen. Beide Versionen bestanden 19,422 Ergebnisprüfungen, die Aktualisierungen, veraltete Anzeigen, Löschungen und gemeinsame Endpunkte abdeckten.
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
Jeder zeitlich gesteuerte Aufruf oben fügt 16 Anzeigen hinzu und führt die Zugriffskontroll-Listener aus. Bei 10,000 behaltenen Identitäten sank es von etwa 155 µs auf 4.72 µs, ein gepaarter 33× Gewinn. Die indizierte Version bleibt nahezu flach über diese Größen, weil diese Listener die wachsende Historie nicht mehr durchsuchen.Messung am API statt über den Aufrufer hinweg, geht die Suche selbst von einer Scan- zu einer Hash-Operation. Ein Fehlschlag bei 10,000 behaltenen Identitäten sank von 11,423 ns auf 45 ns, ein gepaarter 251×, und ein einziger Treffer von 9,309 ns auf 79 ns, 118×. Eine Abfrage, die viele Identitäten zurückgibt, skaliert immer noch mit dem, was sie zurückgibt, sodass der gemeinsame-URL-Fall 4.4× statt 2 Größenordnungen gewinnt. Das 251× ist das isolierte Suchergebnis. Das 33× misst den größeren Aktualisierungsaufruf, der es verwendet; diese Gewinne können nicht addiert oder multipliziert werden.
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× in einem gemischten Speicher, ein zusätzliches 2.51 MB bei 10,000 Identitäten. Wo jede Identität einen Endpunkt teilt, ist die abgeleitete Karte klein und die Kosten fallen auf 1.45×. Wo keine Identität ein URL hat, gibt es nichts zu ermitteln und die Kosten sind null. Diese Zahlen sind vom Allokator angeforderte Bytes für den erhaltenen Speicher, nicht die gesamte Knotenspeicher.

Mit allen 6 Patches zusammen konnte der Knoten fertigstellen und fortfahren#

Die kombinierte Wiedergabe nutzte Kitsune2's echten Gossip, Fetch, Peer-Access und Memory-Store-Komponenten, kommunizierend über seinen in‑Memory-Test-Transport. Wir führten eine 5‑Schritt‑Sequenz auf den ursprünglichen und gepatchten Quellbäumen durch:
  1. Peer‑Informationen aktualisieren. Eine Identität ändert den Endpunkt. Veraltete Informationen, die später ankommen, lassen das neuere Datensatz unverändert, und eine blockierte Identität bleibt für die Zugriffskontrolle auflösbar. Beide Versionen bestehen; der Index bewahrt bestehende Entscheidungen.
  2. Gossip starten, nachdem ein Fetch abgeschlossen ist. Der gepatchte Knoten initiiert nach 202 ms. Der ursprüngliche nimmt den Fallback-Pfad bei 3,002 ms.
  3. Daten in falscher Reihenfolge empfangen. 3 angeforderte Operationen kommen als 4 Antworten an, einschließlich einer Duplikat. Beide Versionen speichern sie konsistent und verknüpfen Byte‑Zählungen mit der korrekten Operation.
  4. Fetch abschließen. Die gespeicherten Operationen können abgerufen werden. Der gepatchte Knoten weckt auch den Listener, der registriert wurde, während diese Operationen ausstanden.
  5. Nach einem fehlgeschlagenen Peer fortfahren. Ein kontrollierter Sendefehler löscht den Request‑Status dieses Peers. Ein anderer Peer liefert die Operation, die ausstehende Map leert sich, und ein nachfolgender Fetch gelingt. Beim ursprünglichen Knoten schlagen die Completion‑Notification‑Checks fehl.
Separate Interaktionstests kombinierten Cancellation mit gleichzeitigen Sends und kombinierte Batch‑Verarbeitung mit Completion‑Notification. Die Reparaturen hielten zusammen: angenommene Arbeit wurde abgeschlossen, abgebrochene Zulassungen hinterließen keine verwaisten Einträge, und Listener wurden nach der letzten Antwort geweckt.Das bringt uns so weit, dass Daten in den Host‑Store empfangen wurden und der nächste Netzwerk‑Schritt fortgesetzt werden kann. Die Validierung und Integration von Holochain folgen immer noch außerhalb dieses Labors. Wir haben noch nicht gemessen, wie sehr diese Änderungen die vollständige Aufholzeit eines realen Knotens verkürzen.

Was jeder Gewinn kostet#

Der Index kostet Speicher und macht Endpunktänderungen teurer. Im ursprünglichen Small‑Store‑Test, bei dem ein festes Set von Identitäten auf neue URLs aktualisiert wurde, lief es bei 0.946× Basisschnelle mit 100 erhaltenen Identitäten. Bei 10,000, kostete ein isolierter Endpunkt‑Änderungs‑Write 3.68× so viel. Die Aufrechterhaltung des zusätzlichen Index hat einen Preis; die Einsparungen bei der Suche müssen ihn zurückzahlen.Da dieser Kompromiss real ist, suchten wir nach der Arbeitslast, bei der der Index verliert. 36‑Konfigurationen wurden vor der Messung vorab deklariert, 432 gekoppelte Läufe wurden ausgeführt, und die Ergebnis‑Transkripte wurden identisch zwischen Varianten gehasht.
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

Jede Arbeitslast in dieser breiteren Matrix hatte ein Median über Parität, einschließlich der Mischung, bei der jede akzeptierte Aktualisierung einen Endpunkt änderte: 1.47× bei 100 Identitäten und 36.42× bei 10,000. Diese Aktualisierungen lösten auch Zugriffskontroll‑Suchen aus, und ihre Einsparungen überstiegen die zusätzlichen Schreibvorgänge. Diese breitere Arbeitslast unterscheidet sich von dem früheren festen Set‑Test; ihr positives Ergebnis lässt die Small‑Store‑Regression im Protokoll zurück.Der 100‑Identitäts‑Fall, überwiegend URL‑los, bleibt unentschieden: sein 1.09× Median beinhaltete ein gepaartes Ergebnis unter Parität. Wir benötigen immer noch Spuren von realen Knoten, die die erhaltenen Identitätszahlen, Endpunktänderungen und Suchhäufigkeit zeigen, bevor wir den Index für eine bestimmte Arbeitslast empfehlen.Gleichzeitige Sendungen enthüllten eine Bereinigungsinteraktion. Sobald Arbeiter überlappen konnten, konnte die Bereinigung eines fehlgeschlagenen Sendens laufen, während eine andere Anfrage an denselben Peer im Flug war. Das machte die vorhandene Peer‑weite Bereinigung breiter als die Arbeit, die fehlgeschlagen war. Der Eigentümer‑Patch schränkte die Entfernung auf Einträge ein, die noch zu jener Anforderungs‑Generierung gehörten. Das Testen der Patches zusammen war hier entscheidend.Die Latenz des einzelnen Batch‑Requests bleibt unentschieden. Wir haben p95, die Zeit, innerhalb derer 95% der Anfragen fertig werden, gemessen. Für eine allein gesendete Anfrage zeigte der letzte Lauf des Arbeiters 1.01–1.08× Basisschnelle p95; der unabhängige Rerun zeigte 1.44–1.58×. Diese Vorrichtungen benötigen zehn Mikrosekunden, und ihre Steuerungen drifteten ebenfalls. Die Burst-Verbesserung wurde reproduziert, aber das Ergebnis der Einzelanfrage ließ sich nicht stabilisieren, sodass größere Chargen weiterhin opt-in bleiben.

Wiederholte Vergleiche und gestoppte Sendungen bleiben offen#

Wir untersuchten auch 2 andere Teile derselben Aufholsequenz. Keines führte zu einem akzeptierten Patch.Vergleich dessen, was Peers bereits besitzen (K4). Gossip verwendet kompakte Zusammenfassungen gespeicherter Daten, um Unterschiede zu finden. Im größten Test wurden bei der Erstellung und dem Vergleich eines unveränderten Snapshots 262,144 Hashes materialisiert; die Wiederholung 10 mal produzierte jedes Mal identische Ausgabe. Die Wiederverwendung einer vorherigen Zusammenfassung wirkt verlockend, aber der Host-Store kann sich ändern, ohne ein zuverlässiges Signal, um dieses gespeicherte Ergebnis zu invalidieren. Eine zwischengespeicherte Zusammenfassung könnte dann einen Unterschied zwischen Peers verbergen. Die von uns bewerteten Alternativen unterschieden sich ebenfalls von der erforderlichen 20% Zeitersparnis im In-Memory-Store. Messungen aus einem realen Holochain-Store sind das nächste fehlende Stück.Wiederherstellung, wenn ein Gossip-Send gestoppt wird (K2). Das Lesen der Quelle stellte die Frage, ob ein Send-Thread einen Lock hält, den die Timeout-Aufgabe ebenfalls benötigt. Wir mussten auch feststellen, was mit dem zugrunde liegenden Iroh-Transport-Stream passiert, wenn dieser Send-Thread teilweise abgebrochen wird. Der Agent-Provider blockierte die Arbeit am Reproduktionsdriver, sodass der Laufzeittest nie abgeschlossen wurde. Dies bleibt ein ungeprüftes Anliegen, ohne Patch oder Zuverlässigkeitsnachweis.

Was wir gemessen haben, und was noch gemessen werden muss#

Diese Experimente wurden auf der Entwicklungsquelle 0.6.0-dev.1 ausgeführt, auf 1 gemeinsam genutztem Apple M4 Max mit 16 logischen Kernen. Wir nutzten lokale Testknoten und In-Memory-Transport, ohne Kern-Pinning oder einen zweiten physischen Host. Die Ergebnisse umfassen benannte Komponenten und ihre Interaktionen. Netzwerkdurchsatz, gesamtes Netzwerk-Kongruenz, Gesamtspeicher des Knotens und Holochain-Anwendungs-Latenz bleiben ungemessen.Die Methode folgt meiner Arbeit zu benchmark-driven development. Wir haben jede Frage und Schwellenwert für die Akzeptanz aufgezeichnet, die Quelle und Fixtures innerhalb jedes Vergleichs festgehalten und Befehle, Stichproben und Fehler in append-only-Belegen festgehalten.Für die 3 Reparaturen schlugen die gleichen Tests im Originalcode bei den erwarteten Assertions fehl und bestanden mit dem Patch. Für die Optimierungen mussten beide Versionen das Verhalten erhalten, dann mussten die Messungen die festgelegte Schwelle erfüllen. Timing-Läufe wechselten die Reihenfolge und hielten die Kompilierung außerhalb des gemessenen Fensters. Ein überwachender Agent führte die Akzeptanzbefehle erneut auf der eingefrorenen Quelle aus, bevor er jedes Ergebnis akzeptierte; die Meinungsverschiedenheit über die Latenz bei Einzelanfragen blieb im Endbericht.Das fertige Paket enthält 204 Belegverzeichnisse. Die kombinierten Tests wurden um 12:17 p.m. akzeptiert, und die Endergebnisse wurden um 12:20 p.m. aufgezeichnet. Eine endgültige Abschlussprüfung wurde um 2:38 p.m. durchgeführt. Alle 6 Patches sind jetzt für die Überprüfung durch die Aufsichtsseite offen: completion notification, worker concurrency, admission ownership, response cleanup, request batching, und endpoint indexing.

Schlüsselzuweisungen#

Von mir. Das Labor selbst: meine benchmark-driven Methode, ausgerichtet auf Kitsune2 um herauszufinden, wo es Zeit verbrachte.Von GPT-6 Astra. Die Abschlussbenachrichtigung und die Reparatur der Eigentumsübernahme: die Diagnose, das Patch und die Tests, die im Originalcode fehlschlagen. Es hat auch diesen Artikel aus den Laboraufzeichnungen verfeinert.Von GLM-5.3. Die Reparatur der Arbeitsknoten-Konkurrenz, die Aufräumung und das Batchen der Antworten, die 36-Konfigurationsarbeitslastmatrix für den Index, die DHT-Zusammenfassungsprofilierung hinter der offenen K4 Frage und die kombinierte Wiedergabe aller 6 Patches.Von KI. Der Endpunktindex und seine Messungen, ein überwachender Agent, der jede Annahme auf dem eingefrorenen Quellcode erneut ausführt, bevor das Ergebnis gezählt wird, und der erste Entwurf dieses Artikels.Kritiken, die bestanden.Gemeinsam erreicht. Die Aufholsequenz, der Artikel folgt: ein Knoten lernt seine Peers, vergleicht, was er hat, holt, was er fehlt, speichert es und fährt fort, wobei jeder Patch an der Stelle platziert wird, die er ändert.Aufgebaut auf. Die ersetzbaren Komponentenfabriken des Holochain-Core-Teams und der In-Memory-Transport, die es dem Labor ermöglichen, diese Verhaltensweisen in echten Kitsune2 Komponenten zu testen.#benchmarking#distributed-systems#rust#performance#AI#agents#open-source#experiential#insights—Robert E. Beckner III (Merlin)WeiterlesenZurückIntelligenz kann nicht gehorchen: Urteil, Autorität und was ein Ablehnen zeigtWeiterFehler beim Prompt-Caching können Ihrer Organisation fast 6x mehr pro AI-Runde kostenQwen 3.8-27B auf einem M1 Ultra: Von 12.1 bis 20.3 tok/s durch Messen AllesEntdeckungAugust 14, 20269 Min. LesezeitMTPLX auf einem M1 Ultra: Die 25 tok/s Tune, die 16.5 bedienteEntdeckungAugust 15, 20268 Min. LesezeitDer letzte CLI: Der Wiederaufbau der Basis 51, gegen die meine Werkzeuge gebaut wurdenEntdeckungAugust 19, 202611 Min. LesezeitVerwandte Projekte175-Seite Chinesisches ManuskriptKI-InnovationAIA - KI-BeraterKI-Innovation