A library resolves whole before any of it is filed #32
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
A pass hands its rows to a writer a hundred at a time, so what it has read is
bounded. What it is about to read is not: resolving a library materialises a
Writefor every item in it before the first batch is filed, and the walkholds the whole listing beside it.
On a four-thousand-film library the peak is ~35 MB, against ~49 MB before the
batching — so the enriched rows and their streams, chapters and images were
the bulk of it. The skeleton is what is left, and it grows with the library.
Worth measuring on the thirteen-thousand-file library before deciding whether
it is worth streaming the resolver, which is a larger change than the batching
was:
library_treesorts its nodes, and the sort is what makes a folder comebefore what is under it.
Measured before changing anything, on
/mnt/media(peak RSS isVmHWM, readfrom
/proc/<pid>/statusat the moment thescannedline is logged).An instrumented
passover the music library — 5387 rows, nothing else running— says where the memory is:
So the skeleton is ~11 MB of a 41 MB peak, about 2 KB an item, and the rows
already filed plus the maps built from them are another ~10 MB — the same order,
and not what this issue is about.
Streaming the resolver does not pay for itself.
libraryneeds every nodetwice — once for the map from a node's path to its id, and again in
series_link, which looks a season's series up among its siblings — so a lazylibrarywould hold the nodes for as long as the eager one holds the rows.Nodes measure 5 MB and rows 4 MB: the swap is a wash, for a change that reaches
through
library_tree,libraryandplan.What was pure duplication has gone instead: the resolved tree now goes out of
scope with the rows it built, and
planis drawn one row at a time rather thancollected into a second vector the size of the library.
Two samples each for the music library, three each for the whole one. The
whole-library figure is a mean: those runs spread over 8 MB, which is wider than
the saving, so all it says is that nothing got worse. The music library is the
measurement that resolves — three libraries in a row reuse each other's freed
skeleton, and one does not.
Left open, and bigger than what is left of the skeleton:
Filedreads every row,every chain and every track on record into memory before the pass starts, which
is ~19 MB at 14578 rows and grows with the library exactly as this issue
describes.
Partly fixed and merged, with the premise measured and set aside.
The proposed fix does not pay
Streaming the resolver was measured before being attempted, and it is a wash:
library()needs every node twice — once for the path-to-id map and once forthe sibling lookup a series link does — so a lazy resolver would hold the nodes
exactly as long as the eager one holds the rows it built them into. A change
reaching through three modules for no saving.
What was worth removing was duplication: the resolved tree now goes out of scope
with the rows it built, and a pass draws its plan one row at a time rather than
collecting a second library-sized list of it.
Measured
/mnt/media/music, 5387 rows, release build,VmHWMat the scan's end, threeruns each:
The row order a pass files in is unchanged — the same sequence and the same
25574 ancestor rows — and a rescan still writes nothing.
What is now the larger term
Two things a pass holds that grew since this issue was opened, both worth their
own measurement rather than being folded in here:
Filedreads every row, every chain and every track on record before the passstarts — around 19 MB at 14578 rows, and it grows with the library.
so the chains a pass resolved are held until the last library is read. That is
what makes a folder two libraries share hang below both (#33), and it is a
library-sized map.