Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1514838 > unrolled thread
| Started by | Vitaly Wool <vitalywool@gmail.com> |
|---|---|
| First post | 2016-11-03 22:10 +0100 |
| Last post | 2016-11-03 22:40 +0100 |
| Articles | 3 — 2 participants |
Back to article view | Back to linux.kernel
[PATH] z3fold: extend compaction function Vitaly Wool <vitalywool@gmail.com> - 2016-11-03 22:10 +0100
Re: [PATH] z3fold: extend compaction function Andrew Morton <akpm@linux-foundation.org> - 2016-11-03 22:20 +0100
Re: [PATH] z3fold: extend compaction function Vitaly Wool <vitalywool@gmail.com> - 2016-11-03 22:40 +0100
| From | Vitaly Wool <vitalywool@gmail.com> |
|---|---|
| Date | 2016-11-03 22:10 +0100 |
| Subject | [PATH] z3fold: extend compaction function |
| Message-ID | <szxqN-KH-7@gated-at.bofh.it> |
z3fold_compact_page() currently only handles the situation when
there's a single middle chunk within the z3fold page. However it
may be worth it to move middle chunk closer to either first or
last chunk, whichever is there, if the gap between them is big
enough.
This patch adds the relevant code, using BIG_CHUNK_GAP define as
a threshold for middle chunk to be worth moving.
Signed-off-by: Vitaly Wool <vitalywool@gmail.com>
---
mm/z3fold.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 47 insertions(+), 13 deletions(-)
diff --git a/mm/z3fold.c b/mm/z3fold.c
index 4d02280..fea6791 100644
--- a/mm/z3fold.c
+++ b/mm/z3fold.c
@@ -250,26 +250,60 @@ static void z3fold_destroy_pool(struct z3fold_pool *pool)
kfree(pool);
}
+static inline void *mchunk_memmove(struct z3fold_header *zhdr,
+ unsigned short dst_chunk)
+{
+ void *beg = zhdr;
+ return memmove(beg + (dst_chunk << CHUNK_SHIFT),
+ beg + (zhdr->start_middle << CHUNK_SHIFT),
+ zhdr->middle_chunks << CHUNK_SHIFT);
+}
+
+#define BIG_CHUNK_GAP 3
/* Has to be called with lock held */
static int z3fold_compact_page(struct z3fold_header *zhdr)
{
struct page *page = virt_to_page(zhdr);
- void *beg = zhdr;
+ int ret = 0;
+
+ if (test_bit(MIDDLE_CHUNK_MAPPED, &page->private))
+ goto out;
+ if (zhdr->middle_chunks != 0) {
+ if (zhdr->first_chunks == 0 && zhdr->last_chunks == 0) {
+ mchunk_memmove(zhdr, 1); /* move to the beginning */
+ zhdr->first_chunks = zhdr->middle_chunks;
+ zhdr->middle_chunks = 0;
+ zhdr->start_middle = 0;
+ zhdr->first_num++;
+ ret = 1;
+ goto out;
+ }
- if (!test_bit(MIDDLE_CHUNK_MAPPED, &page->private) &&
- zhdr->middle_chunks != 0 &&
- zhdr->first_chunks == 0 && zhdr->last_chunks == 0) {
- memmove(beg + ZHDR_SIZE_ALIGNED,
- beg + (zhdr->start_middle << CHUNK_SHIFT),
- zhdr->middle_chunks << CHUNK_SHIFT);
- zhdr->first_chunks = zhdr->middle_chunks;
- zhdr->middle_chunks = 0;
- zhdr->start_middle = 0;
- zhdr->first_num++;
- return 1;
+ /*
+ * moving data is expensive, so let's only do that if
+ * there's substantial gain (at least BIG_CHUNK_GAP chunks)
+ */
+ if (zhdr->first_chunks != 0 && zhdr->last_chunks == 0 &&
+ zhdr->start_middle > zhdr->first_chunks + BIG_CHUNK_GAP) {
+ mchunk_memmove(zhdr, zhdr->first_chunks + 1);
+ zhdr->start_middle = zhdr->first_chunks + 1;
+ ret = 1;
+ goto out;
+ }
+ if (zhdr->last_chunks != 0 && zhdr->first_chunks == 0 &&
+ zhdr->middle_chunks + zhdr->last_chunks <=
+ NCHUNKS - zhdr->start_middle - BIG_CHUNK_GAP) {
+ unsigned short new_start = NCHUNKS - zhdr->last_chunks -
+ zhdr->middle_chunks;
+ mchunk_memmove(zhdr, new_start);
+ zhdr->start_middle = new_start;
+ ret = 1;
+ goto out;
+ }
}
- return 0;
+out:
+ return ret;
}
/**
--
2.4.2
[toc] | [next] | [standalone]
| From | Andrew Morton <akpm@linux-foundation.org> |
|---|---|
| Date | 2016-11-03 22:20 +0100 |
| Message-ID | <szxAu-NU-7@gated-at.bofh.it> |
| In reply to | #1514838 |
On Thu, 3 Nov 2016 22:04:28 +0100 Vitaly Wool <vitalywool@gmail.com> wrote: > z3fold_compact_page() currently only handles the situation when > there's a single middle chunk within the z3fold page. However it > may be worth it to move middle chunk closer to either first or > last chunk, whichever is there, if the gap between them is big > enough. "may be worth it" is vague. Does the patch improve the driver or does it not? If it *does* improve the driver then in what way? *Why* is is "worth it"? > This patch adds the relevant code, using BIG_CHUNK_GAP define as > a threshold for middle chunk to be worth moving.
[toc] | [prev] | [next] | [standalone]
| From | Vitaly Wool <vitalywool@gmail.com> |
|---|---|
| Date | 2016-11-03 22:40 +0100 |
| Message-ID | <szxTQ-UG-31@gated-at.bofh.it> |
| In reply to | #1514842 |
On Thu, Nov 3, 2016 at 10:16 PM, Andrew Morton <akpm@linux-foundation.org> wrote: > On Thu, 3 Nov 2016 22:04:28 +0100 Vitaly Wool <vitalywool@gmail.com> wrote: > >> z3fold_compact_page() currently only handles the situation when >> there's a single middle chunk within the z3fold page. However it >> may be worth it to move middle chunk closer to either first or >> last chunk, whichever is there, if the gap between them is big >> enough. > > "may be worth it" is vague. Does the patch improve the driver or does > it not? If it *does* improve the driver then in what way? *Why* is is > "worth it"? Yep, I must admit I wasn't clear enough here. Basically compression ratio wise, it always makes sense to move middle chunk as close as possible to another in-page z3fold object, because then the third object can use all the remaining space. However, moving big object just by one chunk will hurt performance without gaining much compression ratio wise. So the gap between the middle object and the edge object should be big enough to justify the move. So, this patch improves compression ratio because in-page compaction becomes more comprehensive; this patch (which came as a surprise) also increases performance in fio randrw tests (I am not 100% sure why, but probably due to less actual page allocations on hot path due to denser in-page allocation). ~vitaly
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web