Skip to content

6.5.2 - The open stops re-fetching what it already has

Choose a tag to compare

@superuser404notfound superuser404notfound released this 02 Aug 17:58

Measured with aetherctl against a Range-logging origin, six container layouts, all sized above the 32 MB range so their tails lie outside the first window. Three defects, all the same shape: bytes already in hand were thrown away and fetched again.

Fixed

  • A range that finished delivering is read out of the window instead of fetched again. A completed range clears activeTask exactly as a dropped one does, and the no-connection branch reconnected at the READ position regardless, which resets winStart and drops everything still resident. The parse pass is precisely the consumer this bites: it reads one 256 KB AVIO buffer at a time while the transfer runs at line rate. A 764450 B trailing moov cost three connections and 1506918 delivered bytes, 1.97x its own size, each reconnect landing exactly one AVIO buffer further on. It now costs one. Serving what is in hand first also revives the #220 frontier refill, which could not run while this branch preempted it on every completed range.

  • A read at the end of the file no longer opens a connection for it. The EOF decision sat below that reconnect, so a position at exactly fileSize issued bytes=<fileSize>- and took an empty 206, whose reconnect reset winStart past the last byte and dropped the window the parse was still reading.

  • The head of the file is retained across the open phase, so the return trip after a parse excursion is a copy. 6.4.5 parked the window at seek time, cut from winStart, on the reasoning that the demuxer returns to the window's start. It returns to the FILE's start: measured landings of 48, 1161, 5752 across six layouts and 265159 in a field trace. Those coincide only while the parse seeks away before reading anything. A fragmented MP4 reads 33 MB first, so the parked copy began megabytes past everything the return asked for and served nothing on any layout measured. The head is now collected as the data connection delivers it, which is the only point at which it can be, since trimWindowLocked drops it as the parse moves forward. The parked window is gone.

Measured

Requests per open, and which resident span answered:

layout before after answered by
moov at end, 764450 B 5 3 retained head
fragmented, mfra at end 5 3 tail prefetch + retained head
moov at end, 23337 B 2 2 tail prefetch
faststart 2 2 nothing
MKV, Cues at end 2 2 nothing
MKV, Cues at front 2 2 nothing

Wall clock against the same origin with 300 ms of latency per request, since a loopback one cannot show an overlap: opening the fragmented fixture went from 1732 ms and four requests to 1219 ms and three.

Two things worth knowing that fell out of the same matrix. Matroska does not read its Cues at open, wherever they sit, so the speculative suffix fetch is spent on every MKV. And the deep tail read of a fragmented MP4 is a media fragment, not an index: EOF-4739057 in the fixture, EOF-80288 in the field trace. Its distance from the end scales with the fragment size, so no suffix window covers that class and the fetch is deliberately not sized for it.

Compatibility

No API changes. Peak transient footprint during an open is lower: the retained head replaces the parked window at the same 4 MB cap rather than sitting beside it.

Upgrading

.package(url: "https://github.com/superuser404notfound/AetherEngine", from: "6.5.2")