Repository navigation
Conversation
[Medium impact] The PR appears safe to merge; no new actionable issues were found. SummaryThis PR overlaps the first folder and sidebar reads with window creation.
The earlier findings were rechecked against the current code. No new actionable issues were found. Tests were inspected but not run.
|
thisisgm
force-pushed
the
launch
branch
3 times, most recently
from
November 12, 2026 06:04
dbae059 to
fab9ca6
Compare
Building a listing asked the disk about every file a second time, because Qt stats a file again before it reads the name. A regular file is now typed from the name the listing already read; a link, a pipe or a device keeps the full lookup.
A selection, a folder count or a second view of the same folder each made the model copy its whole listing. They now read it in place, so a large folder is held once however many views show it.
The preview's folder summary sorted every name to count them and to pick two pictures. It now keeps the first two pictures in one pass, so summarizing a large folder no longer holds every name.
Every entry kept its own copy of its type, kind and extension, and the listing kept spare room for entries that never came. The entries of a listing now share those strings, and the spare room is given back.
Opening a folder typed every file before its first row showed. The listing now leaves a regular file's type, kind and extension unread until a role asks, which touches no disk; a sort by kind still types every entry in the worker.
Every refresh of Places, the 15 second poll included, told all four sidebar lists they had changed. Each list now has its own signal and is announced only when its contents differ.
While active, Folio ran hyprctl once a second to read the corner rounding. It now reads it at start, on a palette change, on return to the window and when Hyprland's event socket reports a reloaded config.
Sorting 100,000 names collated both strings on every compare. A listing that arrives in a few ordered runs is now merged, and a name or kind sort makes one sort key an entry first. The comparator is the same, so every order and tie stays; the C locale compares as before.
A name or kind listing read every entry's size and date before its first row showed. It now reads the first 320 rows, and a later row when a view asks, one batch a turn, off the UI thread. A row not read yet shows no size and no date, never 0 B.
A re-read that found the same names kept each folder's item count, even when the folder's own date had moved. Such a folder's count is now dropped and counted again, as it was before the listing learned to keep its rows through a re-read.
The event socket was opened once. Hyprland hangs up on a reader that fell behind, and after that a config reload no longer reached the corners. The watch is now taken up again when Folio is back in use.
A text tile past the rows read at first asked for its page with no date, then again when the date arrived, and a page has no cache on disk, so the file was read and drawn twice. Like a thumbnail, a page is now asked for only once its date is known.
A folder past the rows read at first is counted without its date being read, so a re-read had nothing to compare and kept its old count. Its date is now read just before it is counted and kept with the count, and the re-read sees the folder changed since.
A burst of events was read whole into memory before any of it was looked at, on the UI thread. One turn of the event loop now reads 64 KiB at most and looks at each piece as it comes, and a line too long to keep is dropped to its end, its last piece included.
Hung up on by Hyprland, the theme took its watch up again only when Folio was left and come back to, so a config reload in between left the corners as they were. While in use it now connects again after a pause, and reads the rounding for a reload that went by untold.
Hung up on while Folio stayed in use, the theme tried Hyprland's event socket once more after a pause. A try that found no socket was the last, and reloads went untold until Folio was left and come back to. Each failed try now starts the pause again.
A re-read drops the answers on their way and reads the rows asked for itself. A row it could not read either stayed marked as being read, so no view could ask for it again. Such a row is now owed: a view may ask again, the folder's next re-read tries it again, and a view is told when another view read it.
A view asks for a row's kind, MIME type and extension each time it makes the row, and each ask read them from the name again: 48 us a row in /usr/bin. The model now keeps up to 4,096 names' types, until a folder is found changed.
The home folders, the views, the bookmarks and the system's device were read in the constructor, on the UI thread, before the window's QML was compiled. A thread now reads them from the constructor on, and the first look at any list waits for it, so the first frame still draws every list whole and no change signal follows it.
The window's folder was listed only once its model existed, after the QML was compiled and the window built, so a large folder's rows came well after the window. The folder named at launch is now read from the start, under a watch, and the first model takes that reading unless the folder changed since, when it reads it again. A reading nobody takes, or whose model has left for another folder, stops, and one not yet begun opens nothing.
The first folder is read while the window is made, and taken when its watch saw no change. A link on the way that came to lead to another folder changes nothing in the folder read, so its rows stood under a path that led elsewhere. The folder is now noted, and the reading left unless it is the same.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #26: its eighteen commits come first here, the last three are this pull request's, and I will rebase it as soon as #26 lands.
Two changes to how the first window comes up, one commit each with its own tests: the sidebar's lists and the folder named at launch are read on the thread pool while the window is being made, where the lists were read on the UI thread before the window existed and the folder only after it. From a cold start into a folder of 100,000 files the rows are listed about 600 ms sooner, and by the medians the window has settled about 330 ms sooner in the grid, 300 ms in the list and 65 ms in the columns. A third commit leaves that reading when the path has since come to lead to another folder. In the grid the window itself comes up later and comes up whole; that and the memory it costs there are under Limits. The suite goes from 236 to 241 tests. No library,
dependsoroptdependsentry is added, and nothing is kept running: one reading, taken or dropped in the first turn of the event loop.What you'd notice
Placesconstructor, on the UI thread, before the QML was compiled. A pool thread now reads them from the constructor on, and the first look at any list waits for it. The first frame still draws every list whole, and no change signal follows it.main()now starts reading the folder named at launch before the window is made, and the first model takes that reading. The sidebar and the rows appear together.Numbers
Measured on a mini PC, cold start into a folder of 100,000 files, six runs a view, #26's head (
e7ccfe5) against this branch's. Settled is the time until the window is up and the process has gone quiet. Both are the CMake build.Where the time goes, from a build of each over today's main with three marks added (list, cold, twelve runs, counted from exec): the folder is listed at 707 to 814 ms where it was listed at 1317 to 1420 ms, and the first frame is drawn at 774 to 883 ms where it was drawn at 836 to 915 ms.
Screenshots
The grid from a warm start, frames of a screen recording, each with its time from launch. Before, the sidebar stands beside an empty pane until the rows land; after, the window comes up with its rows.
Tests
Five new cases, each failing without its commit: the sidebar's lists are read off the UI thread and are whole at the first look; a folder read ahead is taken once, and a change made after the reading began (a file grown, a file added) is seen by the model, never the reading; a folder that can't be watched is read by the model itself; and a reading nobody wants (never taken, or taken by a model that left) opens no folder, counted with
IN_OPENon the folders themselves while the pool is held; and a reading whose path was switched to another folder after it was made is left for that folder's own rows, while one through a link left alone is taken.Limits