Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pagecache: use an objcache as page heap #1757

Merged
merged 4 commits into from
Aug 6, 2022
Merged

Conversation

francescolavra
Copy link
Member

In the pagecache code, allocating 4KB pages directly from the linear backed heap creates excessive fragmentation, which in
low-memory conditions may cause other allocations in the kernel (which typically use objcaches with a 2MB page size) to fail even when pagecache drain requests are fully executed.
This changeset addresses the fragmentation issue by changing the pagecache code to use an objcache (with a 2MB page size, and with the linear backed heap as parent heap) as page heap; this allows a pagecache drain to release memory in large chunks that are then available for other allocation requests throughout the kernel.
As part of this changeset, a generic memory cleaner interface is being implemented, which allows various parts of the kernel to register a closure to be invoked to release cached memory when the system is low on memory (#1130). In addition, a new heap sub-type, called caching_heap, is being defined; a caching_heap exports an additional callback to drain memory that has been
cached (#1494); the objcache heap is now a caching_heap.

Copy link
Collaborator

@sanderssj sanderssj left a comment

Choose a reason for hiding this comment

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

I'm wondering if some of the i/o objcache cleaners (maybe net drivers and pagecache?) should retain a small minimum number of objects that do not get freed so that in a low memory condition critical resources can still function. If the operation requiring lots of memory requires i/o of some sort in order to free memory, starving those devices completely of memory could deadlock the system. What do you think?

src/runtime/heap/objcache.c Outdated Show resolved Hide resolved
@francescolavra
Copy link
Member Author

I'm wondering if some of the i/o objcache cleaners (maybe net drivers and pagecache?) should retain a small minimum number of objects that do not get freed so that in a low memory condition critical resources can still function. If the operation requiring lots of memory requires i/o of some sort in order to free memory, starving those devices completely of memory could deadlock the system. What do you think?

Yes, I think it makes sense to provide a way for a caching heap to retain a configurable amount of memory when a drain is requested; e.g. by adding a retain parameter to the drain function, which indicates the number of bytes that should be kept cached. And then, caching heaps where an allocation failure would be critical (like those used by the pagecache and by net and disk drivers) will be drained with a retain argument corresponding to the number of objects that should be kept in the cache.

@francescolavra
Copy link
Member Author

I added a retain parameter to the drain function. Network and disk drivers, as well as the pagecache code, invoke the drain function with a retain value that allows retaining in the cache a number of objects set via defines in config.h.

Copy link
Collaborator

@sanderssj sanderssj left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@wjhun wjhun left a comment

Choose a reason for hiding this comment

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

Looks good!

src/unix/unix.c Outdated Show resolved Hide resolved
With this change, it is possible to register different "memory
cleaner" closures, which will be invoked to free up memory when the
system is low on available physical memory. The virtio balloon
deflater and the pagecache drain function have been converted to
use this interface.

Partially addresses #1130.
This macro is being amended so that it is possible to remove a page
list element from within the loop that walks the list. This will be
needed to implement the cache drain functionality.
This change introduces a new heap sub-type, called caching_heap,
that exports an additional callback to drain memory that has been
cached. The objcache heap is now a caching_heap.
In addition, the objcache heap now implements locking, which allows
safe use of the drain functionality in concurrently accessed heaps
without the need for an external lock.
Memory cleaner instances have been added in various places where an
objcache is used, so that caching heaps can be drained when the
system is low on memory.

Partially addresses #1494.
In the pagecache code, allocating 4KB pages directly from the
linear backed heap creates excessive fragmentation, which in
low-memory conditions may cause other allocations in the kernel
(which typically use objcaches with a 2MB page size) to fail even
when pagecache drain requests are fully executed.
This commit addresses the fragmentation issue by changing the
pagecache code to use an objcache (with a 2MB page size, and with
the linear backed heap as parent heap) as page heap; this allows a
pagecache drain to release memory in large chunks that are then
available for other allocation requests throughout the kernel.
In addition, the pagecache completion heap is now drained if a
drain request could not be fully executed by draining the page
heap.
@francescolavra francescolavra merged commit 22add9b into master Aug 6, 2022
@francescolavra francescolavra deleted the feature/caching_heap branch August 6, 2022 10:01
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.

3 participants