Skip to content

storage: last-ref unmap and defer munmap to the disk thread#850

Open
j-c-m wants to merge 3 commits into
rakshasa:masterfrom
j-c-m:feature/disk-thread-munmap
Open

storage: last-ref unmap and defer munmap to the disk thread#850
j-c-m wants to merge 3 commits into
rakshasa:masterfrom
j-c-m:feature/disk-thread-munmap

Conversation

@j-c-m

@j-c-m j-c-m commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Unmap piece maps on last handle release and run MS_ASYNC + munmap on the
disk thread so main is not blocked on teardown.

Flush policy: dirty MAP_SHARED writeback is left mostly to the OS (kernel
page cache). Previously, last writable handles kept maps sticky on
ChunkList::m_queue until a periodic sync_chunks drain on main, which could
msync/munmap a large dirty set at once (main-thread flush storms under
fast leech). Maps are now retired as pieces complete instead of
accumulating for a bulk main-thread pass.

Last-ref unmap — drop the sticky writable hold; when refs hit zero, clear/unmap immediately (writable and RO share the same path). Previously there was a policy to have them be sticky for a bit, but this seems unnecessary now as modern OS stack here will hold these in page cache for some duration and manage the disk IO better.

Deferred teardown — MemoryChunk::unmap queues the VA to ThreadDisk, which does msync(MS_ASYNC) then munmap. This gets the blocking off the ui / peers thread, this was more of an issue on FreeBSD as msync(MS_ASYNC) eventually blocks for a long duration during a big flush storm, Linux would did see some blocking in munmap() but not as much overall. In any case, this keeps it from blocking UI and peer network transfers at all.

These changes offer a large removal opportunity as last-ref unmap means nothing new is parked on ChunkList::m_queue. Callers of the sticky sync path still exist, but for maps released this way they no longer do useful work

@rakshasa

Copy link
Copy Markdown
Owner

Just like the aync fd close changes I did, this should be in a separate thread.

j-c-m added 2 commits July 25, 2026 13:06
Drop the sticky writable hold that parked dirty pieces on m_queue so
they stayed mmap'd until a periodic sync drain. release() now decrements
every handle and clear_chunk/munmap when references hit zero. MS_ASYNC
on the sync path is unchanged; writeback pacing for retired maps is
handled when teardown is deferred to the disk thread.
Queue MemoryChunk unmap regions onto rtorrent disk so last-ref/clear
does not block the caller (usually main) on writeback kickoff or munmap.
On disk, issue MS_ASYNC then munmap so dirty MAP_SHARED pages start
writeback as pieces are retired, avoiding multi-GB flusher storms.

Falls back to the same MS_ASYNC + munmap sequence when the disk thread is
inactive (tests/shutdown). Drain the queue in call_events and cleanup_thread.
@j-c-m
j-c-m force-pushed the feature/disk-thread-munmap branch from d250d8f to efba7bc Compare July 25, 2026 19:06
@j-c-m

j-c-m commented Jul 25, 2026

Copy link
Copy Markdown
Contributor Author

Light testing on the move to std::async, will continue more.

Comment thread src/data/memory_chunk.cc Outdated
if (manager != nullptr) {
manager->chunk_manager()->queue_munmap(ptr, length);
return;
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the wrong place for this, MemoryChunk is supposed to be a simple type.

Comment thread src/utils/munmap_queue.h Outdated
// Persistent std::async worker that issues MS_ASYNC + munmap off the caller
// (and off ThreadDisk). Same shape as FdCloseQueue.

class MunmapQueue {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MemoryUnmapQueue

Comment thread src/utils/munmap_queue.h Outdated
MunmapQueue(const MunmapQueue&) = delete;
MunmapQueue& operator=(const MunmapQueue&) = delete;

using region_type = std::pair<void*, size_t>;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

queue_type with the vector

Own MemoryUnmapQueue on ChunkManager (FdCloseQueue-style worker:
MS_ASYNC + munmap), not ThreadDisk. Queue from ChunkList::clear_chunk so
MemoryChunk stays a simple type.
@j-c-m
j-c-m force-pushed the feature/disk-thread-munmap branch from 19c9696 to 3a6d558 Compare July 26, 2026 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants