<feed xmlns='http://www.w3.org/2005/Atom'>
<title>pure/research/experiments/019-idle-links/transport.c, branch master</title>
<subtitle>Verified execution runtime unifying state, persistence, and replication.
</subtitle>
<id>http://git.yeowoo.org/pure/atom?h=master</id>
<link rel='self' href='http://git.yeowoo.org/pure/atom?h=master'/>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/'/>
<updated>2026-10-01T07:52:43Z</updated>
<entry>
<title>Push a turn's sends to a link at once, and round only the links that want one (017, 2b-1)</title>
<updated>2026-10-01T07:52:43Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-10-01T07:52:43Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=94e7bb87bce6821e91734f1fcbb6cfd61a008049'/>
<id>urn:sha1:94e7bb87bce6821e91734f1fcbb6cfd61a008049</id>
<content type='text'>
The sending loop was woken by every record queued while it slept: the
owner queues one by one, the loop caught up and slept between them, and
every link took a round on every wake. Four links sent 64k packets of
12 records where threads sent 40k of 20, and ran at 257k sends/s
against 581k. The owner now queues a turn's sends and pushes each link
once; the loop rounds a link only when its socket has answers, it was
pushed, or its time came.
</content>
</entry>
<entry>
<title>Queue only the way to the receivers behind M6's bottleneck</title>
<updated>2026-09-29T07:30:30Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-09-29T07:30:30Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=fb573903562695af47b63f91a9e96f55d0661d94'/>
<id>urn:sha1:fb573903562695af47b63f91a9e96f55d0661d94</id>
<content type='text'>
tbf with netem under it lost tbf's queue (netem became it), and the
answers queued behind the data. Now each way has its netem, the way to
the receivers' ports then a tbf whose queue holds a round trip; the way
back does not queue. transport.c takes its listener's port
(TRANSPORT_PORT).
</content>
</entry>
<entry>
<title>Apply a link's records in transport.c as a host does</title>
<updated>2026-09-29T06:47:00Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-09-29T06:47:00Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=d3328ebe3bb7133ad615f78d9800fe7e0d830bf2'/>
<id>urn:sha1:d3328ebe3bb7133ad615f78d9800fe7e0d830bf2</id>
<content type='text'>
From the one after the last heard, letting be the ones heard before and
stopping at a gap: the listener's first delivery may begin past it when
packets reorder, which the harness counted as wrong.
</content>
</entry>
<entry>
<title>Measure a link on a path of loss, reordering and a bottleneck (M6 harness)</title>
<updated>2026-09-29T06:44:50Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-09-29T06:44:50Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=6a72b5c8164ceb73994ab231a075cfb0ad1d7192'/>
<id>urn:sha1:6a72b5c8164ceb73994ab231a075cfb0ad1d7192</id>
<content type='text'>
020-lossy-paths/run.py runs each case in an unprivileged namespace: a
50 Mbit/s tbf bottleneck under netem's delay, jitter and loss, both
ways. A link may send without UDP GSO (pure_link_gso), as netem takes a
burst as one packet; quinn the same (QUIC_GSO=0). transport.c and the
quinn harness give the records handed over in each 100 ms, and at a
steady rate the time each took; TCP CUBIC flows run beside them.
</content>
</entry>
<entry>
<title>Keep a link's two sides as state alone, the sockets and threads apart</title>
<updated>2026-09-29T06:17:36Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-09-29T06:17:36Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=7c6595c8a9229a2208ed5bd75b2dee249187923d'/>
<id>urn:sha1:7c6595c8a9229a2208ed5bd75b2dee249187923d</id>
<content type='text'>
link/link-protocol.h is the protocol with no socket, thread or clock of
its own: packets and time in, packets out. link/link.h carries it over
UDP as before. A sender starts small (8 flights, 16 records, a 4 KiB
ring) so one thread can hold many. The transport's CPU a record is the
same within 2% (five rounds each way, 61 B to 16 KiB).

test-link runs both sides through a network of its own: loss, packets
held back and doubled, failed saves, an idle sweep, and both sides
starting again, every record applied once as sent.
</content>
</entry>
<entry>
<title>Let links know nothing of the core: the host names inputs and shapes</title>
<updated>2026-09-29T06:11:32Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-09-29T06:11:32Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=fcf7cdbe0a971825da0bb087383c60e714ab2be0'/>
<id>urn:sha1:fcf7cdbe0a971825da0bb087383c60e714ab2be0</id>
<content type='text'>
A sender takes its messages' shape, and a listener asks its host which
input a stream goes to. The core gives the shape (pure_module_shape);
link/ now builds without the core's headers.
</content>
</entry>
<entry>
<title>Send a record whole when it fits a packet, however many pieces it has</title>
<updated>2026-09-29T04:11:01Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-09-29T04:11:01Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=41cbb5631fd12dc223738de65246af1a69761bea'/>
<id>urn:sha1:41cbb5631fd12dc223738de65246af1a69761bea</id>
<content type='text'>
A record over a piece (1,000 bytes) went in pieces even when it fit the
packet whole: a record of 1,013 bytes went as two RECORD frames, and the
receiver gathered it the slow way (an allocation, pieces, then onto the
line). A record none of whose pieces went yet now goes whole in a RECORDS
frame whenever it fits what is left of the packet; its pieces are marked
sent together. A record too large for a packet, or one resent after
some of its pieces were lost, still goes in pieces, and a receiver takes
a record whole or in pieces alike.

The transport alone takes 2.85 us a record of 1,013 bytes, not 3.18
(quinn: 3.90). transport.c now checks every record delivered: in order,
once each, its bytes as sent. None was wrong in a network namespace with
1 ms of delay, 3 % loss and 10 % reordering, with records of 61, 1,013
and 16,013 bytes.
</content>
</entry>
<entry>
<title>Wake a link's thread only when it sleeps, once</title>
<updated>2026-09-28T19:10:49Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-09-28T19:10:49Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=ee7f97001b0e193a766a0f889ae16f9d5af40fea'/>
<id>urn:sha1:ee7f97001b0e193a766a0f889ae16f9d5af40fea</id>
<content type='text'>
Every queued record wrote the link's eventfd, a system call each, and woke
the thread to send a packet of a few records. A record queued now wakes
the thread only when it sleeps and nobody woke it yet; one queued while it
sends marks the link, and the thread looks again before it sleeps. With
records queued one at a time as fast as a thread can, 200,000 small ones
went at 400k a second, and now at 730k; queuing one costs 0.43 us, not
1.0.

research/experiments/019-idle-links/transport.c measures the transport
alone: a link and a listener in one process, no app, no store. A backlog
of 200,000 records of 61 bytes drains at 3 to 4 million a second, 0.24 us
a record on each side.
</content>
</entry>
</feed>
