From 505ecd7b30fca1dc296205ff3c0dc3aff9d76e12 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Mon, 26 Jun 2023 14:26:50 +0300 Subject: Shrink struct vm_page size struct vm_page is supposed to be a "small structure", but it takes up 96 bytes on x86_64 (to represent a 4k page). By utilizing bitfields and strategically reordering members to avoid excessive padding, it can be shrunk to 80 bytes. - page_lock and unlock_request only need to store a bitmask of VM_PROT_READ, VM_PROT_WRITE, and VM_PROT_EXECUTE. Even though the special values VM_PROT_NO_CHANGE and VM_PROT_NOTIFY are defined, they are not used for the two struct vm_page members. - type and seg_index both need to store one of the four possible values in the range from 0 to 3. Two bits are sufficient for this. - order needs to store a number from 0 to VM_PAGE_NR_FREE_LISTS (which is 11), or a special value VM_PAGE_ORDER_UNLISTED. Four bits are sufficient for this. No functional change. Message-Id: <20230626112656.435622-2-bugaevc@gmail.com> --- vm/vm_page.c | 4 ++-- vm/vm_page.h | 18 ++++++++++++------ vm/vm_resident.c | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/vm/vm_page.c b/vm/vm_page.c index 50916b74..ce37c8aa 100644 --- a/vm/vm_page.c +++ b/vm/vm_page.c @@ -94,7 +94,7 @@ struct vm_page_cpu_pool { * Special order value for pages that aren't in a free list. Such pages are * either allocated, or part of a free block of pages but not the head page. */ -#define VM_PAGE_ORDER_UNLISTED ((unsigned short)-1) +#define VM_PAGE_ORDER_UNLISTED (VM_PAGE_NR_FREE_LISTS + 1) /* * Doubly-linked list of free blocks. @@ -1016,7 +1016,7 @@ vm_page_seg_balance_page(struct vm_page_seg *seg, vm_page_set_type(dest, 0, src->type); memcpy(&dest->vm_page_header, &src->vm_page_header, - sizeof(*dest) - VM_PAGE_HEADER_SIZE); + VM_PAGE_BODY_SIZE); vm_page_copy(src, dest); if (!src->dirty) { diff --git a/vm/vm_page.h b/vm/vm_page.h index d457f9a2..b2581d9e 100644 --- a/vm/vm_page.h +++ b/vm/vm_page.h @@ -79,9 +79,6 @@ struct vm_page { struct list node; /* page queues or free list (P) */ - unsigned short type; - unsigned short seg_index; - unsigned short order; void *priv; /* @@ -95,7 +92,6 @@ struct vm_page { /* We use an empty struct as the delimiter. */ struct {} vm_page_header; -#define VM_PAGE_HEADER_SIZE offsetof(struct vm_page, vm_page_header) vm_object_t object; /* which object am I in (O,P) */ vm_offset_t offset; /* offset into that object (O,P) */ @@ -126,10 +122,20 @@ struct vm_page { * without having data. (O) * [See vm_object_overwrite] */ - vm_prot_t page_lock; /* Uses prohibited by data manager (O) */ - vm_prot_t unlock_request; /* Outstanding unlock request (O) */ + vm_prot_t page_lock:3; /* Uses prohibited by data manager (O) */ + vm_prot_t unlock_request:3; /* Outstanding unlock request (O) */ + + struct {} vm_page_footer; + + unsigned short type:2; + unsigned short seg_index:2; + unsigned short order:4; }; +#define VM_PAGE_BODY_SIZE \ + (offsetof(struct vm_page, vm_page_footer) \ + - offsetof(struct vm_page, vm_page_header)) + /* * For debugging, this macro can be defined to perform * some useful check on a page structure. diff --git a/vm/vm_resident.c b/vm/vm_resident.c index e0a03bf5..d4777e70 100644 --- a/vm/vm_resident.c +++ b/vm/vm_resident.c @@ -746,7 +746,7 @@ boolean_t vm_page_convert(struct vm_page **mp) memcpy(&real_m->vm_page_header, &fict_m->vm_page_header, - sizeof(*fict_m) - VM_PAGE_HEADER_SIZE); + VM_PAGE_BODY_SIZE); real_m->fictitious = FALSE; vm_page_insert(real_m, object, offset); -- cgit v1.2.3