All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anatoly Burakov <anatoly.burakov@intel.com>
To: dev@dpdk.org
Cc: remy.horton@intel.com
Subject: [PATCH v4 1/3] malloc: add biggest free IOVA-contiguous element to stats
Date: Mon, 14 May 2018 12:19:53 +0100	[thread overview]
Message-ID: <064458eb7fc48457ed4e7fed521e11e68cb32c62.1526296329.git.anatoly.burakov@intel.com> (raw)
In-Reply-To: <cover.1526296329.git.anatoly.burakov@intel.com>
In-Reply-To: <cover.1526296329.git.anatoly.burakov@intel.com>

User might be interested to find out what is the biggest chunk of
IOVA-contiguous free space that can be allocated from malloc. Add
relevant malloc-internal functions and expose this through malloc
stats calculation call.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---

Notes:
    v4:
    - Fix comments to be more up to date with v4 code
    - Add comments explaining trailer handling
    
    v2:
    - Add header to newly recalculated element start
    
    v2:
    - Add header to newly recalculated element start

 lib/librte_eal/common/include/rte_malloc.h |  1 +
 lib/librte_eal/common/malloc_elem.c        | 79 ++++++++++++++++++++++++++++++
 lib/librte_eal/common/malloc_elem.h        |  6 +++
 lib/librte_eal/common/malloc_heap.c        | 11 +++++
 lib/librte_eal/common/rte_malloc.c         |  2 +
 5 files changed, 99 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_malloc.h b/lib/librte_eal/common/include/rte_malloc.h
index a9fb7e4..2553201 100644
--- a/lib/librte_eal/common/include/rte_malloc.h
+++ b/lib/librte_eal/common/include/rte_malloc.h
@@ -27,6 +27,7 @@ struct rte_malloc_socket_stats {
 	size_t heap_totalsz_bytes; /**< Total bytes on heap */
 	size_t heap_freesz_bytes;  /**< Total free bytes on heap */
 	size_t greatest_free_size; /**< Size in bytes of largest free block */
+	size_t greatest_free_iova_contig_size; /**< Size in bytes of largest IOVA-contiguous block */
 	unsigned free_count;       /**< Number of free elements on heap */
 	unsigned alloc_count;      /**< Number of allocated elements on heap */
 	size_t heap_allocsz_bytes; /**< Total allocated bytes on heap */
diff --git a/lib/librte_eal/common/malloc_elem.c b/lib/librte_eal/common/malloc_elem.c
index 9bfe9b9..f1bb4fe 100644
--- a/lib/librte_eal/common/malloc_elem.c
+++ b/lib/librte_eal/common/malloc_elem.c
@@ -18,10 +18,89 @@
 #include <rte_common.h>
 #include <rte_spinlock.h>
 
+#include "eal_internal_cfg.h"
 #include "eal_memalloc.h"
 #include "malloc_elem.h"
 #include "malloc_heap.h"
 
+size_t
+malloc_elem_find_max_iova_contig(struct malloc_elem *elem, size_t align)
+{
+	void *cur_page, *contig_seg_start, *page_end, *cur_seg_end;
+	void *data_start, *data_end;
+	rte_iova_t expected_iova;
+	struct rte_memseg *ms;
+	size_t page_sz, cur, max;
+
+	page_sz = (size_t)elem->msl->page_sz;
+	data_start = RTE_PTR_ADD(elem, MALLOC_ELEM_HEADER_LEN);
+	data_end = RTE_PTR_ADD(elem, elem->size - MALLOC_ELEM_TRAILER_LEN);
+	/* segment must start after header and with specified alignment */
+	contig_seg_start = RTE_PTR_ALIGN_CEIL(data_start, align);
+
+	/* if we're in IOVA as VA mode, or if we're in legacy mode with
+	 * hugepages, all elements are IOVA-contiguous.
+	 */
+	if (rte_eal_iova_mode() == RTE_IOVA_VA ||
+			(internal_config.legacy_mem && rte_eal_has_hugepages()))
+		return RTE_PTR_DIFF(data_end, contig_seg_start);
+
+	cur_page = RTE_PTR_ALIGN_FLOOR(contig_seg_start, page_sz);
+	ms = rte_mem_virt2memseg(cur_page, elem->msl);
+
+	/* do first iteration outside the loop */
+	page_end = RTE_PTR_ADD(cur_page, page_sz);
+	cur_seg_end = RTE_MIN(page_end, data_end);
+	cur = RTE_PTR_DIFF(cur_seg_end, contig_seg_start) -
+			MALLOC_ELEM_TRAILER_LEN;
+	max = cur;
+	expected_iova = ms->iova + page_sz;
+	/* memsegs are contiguous in memory */
+	ms++;
+
+	cur_page = RTE_PTR_ADD(cur_page, page_sz);
+
+	while (cur_page < data_end) {
+		page_end = RTE_PTR_ADD(cur_page, page_sz);
+		cur_seg_end = RTE_MIN(page_end, data_end);
+
+		/* reset start of contiguous segment if unexpected iova */
+		if (ms->iova != expected_iova) {
+			/* next contiguous segment must start at specified
+			 * alignment.
+			 */
+			contig_seg_start = RTE_PTR_ALIGN(cur_page, align);
+			/* new segment start may be on a different page, so find
+			 * the page and skip to next iteration to make sure
+			 * we're not blowing past data end.
+			 */
+			ms = rte_mem_virt2memseg(contig_seg_start, elem->msl);
+			cur_page = ms->addr;
+			/* don't trigger another recalculation */
+			expected_iova = ms->iova;
+			continue;
+		}
+		/* cur_seg_end ends on a page boundary or on data end. if we're
+		 * looking at data end, then malloc trailer is already included
+		 * in the calculations. if we're looking at page end, then we
+		 * know there's more data past this page and thus there's space
+		 * for malloc element trailer, so don't count it here.
+		 */
+		cur = RTE_PTR_DIFF(cur_seg_end, contig_seg_start);
+		/* update max if cur value is bigger */
+		if (cur > max)
+			max = cur;
+
+		/* move to next page */
+		cur_page = page_end;
+		expected_iova = ms->iova + page_sz;
+		/* memsegs are contiguous in memory */
+		ms++;
+	}
+
+	return max;
+}
+
 /*
  * Initialize a general malloc_elem header structure
  */
diff --git a/lib/librte_eal/common/malloc_elem.h b/lib/librte_eal/common/malloc_elem.h
index 7331af9..e2bda4c 100644
--- a/lib/librte_eal/common/malloc_elem.h
+++ b/lib/librte_eal/common/malloc_elem.h
@@ -179,4 +179,10 @@ malloc_elem_free_list_index(size_t size);
 void
 malloc_elem_free_list_insert(struct malloc_elem *elem);
 
+/*
+ * Find biggest IOVA-contiguous zone within an element with specified alignment.
+ */
+size_t
+malloc_elem_find_max_iova_contig(struct malloc_elem *elem, size_t align);
+
 #endif /* MALLOC_ELEM_H_ */
diff --git a/lib/librte_eal/common/malloc_heap.c b/lib/librte_eal/common/malloc_heap.c
index d6cf3af..9305b38 100644
--- a/lib/librte_eal/common/malloc_heap.c
+++ b/lib/librte_eal/common/malloc_heap.c
@@ -803,16 +803,27 @@ malloc_heap_get_stats(struct malloc_heap *heap,
 	socket_stats->free_count = 0;
 	socket_stats->heap_freesz_bytes = 0;
 	socket_stats->greatest_free_size = 0;
+	socket_stats->greatest_free_iova_contig_size = 0;
 
 	/* Iterate through free list */
 	for (idx = 0; idx < RTE_HEAP_NUM_FREELISTS; idx++) {
 		for (elem = LIST_FIRST(&heap->free_head[idx]);
 			!!elem; elem = LIST_NEXT(elem, free_list))
 		{
+			size_t iova_contig_sz;
 			socket_stats->free_count++;
 			socket_stats->heap_freesz_bytes += elem->size;
 			if (elem->size > socket_stats->greatest_free_size)
 				socket_stats->greatest_free_size = elem->size;
+			iova_contig_sz =
+					malloc_elem_find_max_iova_contig(elem,
+							RTE_CACHE_LINE_SIZE);
+			/* find_max_iova_contig doesn't include overhead */
+			iova_contig_sz += MALLOC_ELEM_OVERHEAD;
+			if (iova_contig_sz >
+					socket_stats->greatest_free_iova_contig_size)
+				socket_stats->greatest_free_iova_contig_size =
+						iova_contig_sz;
 		}
 	}
 	/* Get stats on overall heap and allocated memory on this heap */
diff --git a/lib/librte_eal/common/rte_malloc.c b/lib/librte_eal/common/rte_malloc.c
index b51a6d1..b4e87a3 100644
--- a/lib/librte_eal/common/rte_malloc.c
+++ b/lib/librte_eal/common/rte_malloc.c
@@ -195,6 +195,8 @@ rte_malloc_dump_stats(FILE *f, __rte_unused const char *type)
 		fprintf(f, "\tAlloc_size:%zu,\n", sock_stats.heap_allocsz_bytes);
 		fprintf(f, "\tGreatest_free_size:%zu,\n",
 				sock_stats.greatest_free_size);
+		fprintf(f, "\tGreatest_free_iova_contig_size:%zu,\n",
+				sock_stats.greatest_free_iova_contig_size);
 		fprintf(f, "\tAlloc_count:%u,\n",sock_stats.alloc_count);
 		fprintf(f, "\tFree_count:%u,\n", sock_stats.free_count);
 	}
-- 
2.7.4

  parent reply	other threads:[~2018-05-14 11:19 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-25 14:10 [PATCH 1/2] malloc: add biggest free IOVA-contiguous element to stats Anatoly Burakov
2018-04-25 14:10 ` [PATCH 2/2] memzone: allow IOVA-contiguous memzones with zero size Anatoly Burakov
2018-04-25 14:40 ` [PATCH 1/2] malloc: add biggest free IOVA-contiguous element to stats Burakov, Anatoly
2018-04-26  8:06 ` [PATCH v2 " Anatoly Burakov
2018-05-03 17:17   ` [PATCH v3 0/3] Improve zero-length memzone allocation Anatoly Burakov
2018-05-14 11:19     ` [PATCH v4 " Anatoly Burakov
2018-05-14 13:47       ` [PATCH v5 " Anatoly Burakov
2018-05-31  9:50         ` [PATCH v6 " Anatoly Burakov
2018-07-13  9:24           ` Thomas Monjalon
2018-05-31  9:50         ` [PATCH v6 1/3] malloc: add finding biggest free IOVA-contiguous element Anatoly Burakov
2018-05-31  9:51         ` [PATCH v6 2/3] malloc: allow reserving biggest element Anatoly Burakov
2018-05-31  9:51         ` [PATCH v6 3/3] memzone: improve zero-length memzone reserve Anatoly Burakov
2018-05-14 13:47       ` [PATCH v5 1/3] malloc: add biggest free IOVA-contiguous element to stats Anatoly Burakov
2018-05-14 13:58         ` Shreyansh Jain
2018-05-14 13:47       ` [PATCH v5 2/3] malloc: allow reserving biggest element Anatoly Burakov
2018-05-14 13:47       ` [PATCH v5 3/3] memzone: improve zero-length memzone reserve Anatoly Burakov
2018-05-14 11:19     ` Anatoly Burakov [this message]
2018-05-14 11:19     ` [PATCH v4 2/3] malloc: allow reserving biggest element Anatoly Burakov
2018-05-14 11:19     ` [PATCH v4 3/3] memzone: improve zero-length memzone reserve Anatoly Burakov
2018-05-03 17:17   ` [PATCH v3 1/3] malloc: add biggest free IOVA-contiguous element to stats Anatoly Burakov
2018-05-10 13:39     ` Remy Horton
2018-05-03 17:18   ` [PATCH v3 2/3] malloc: allow reserving biggest element Anatoly Burakov
2018-05-10 13:57     ` Remy Horton
2018-05-14  8:22       ` Burakov, Anatoly
2018-05-03 17:18   ` [PATCH v3 3/3] memzone: improve zero-length memzone reserve Anatoly Burakov
2018-05-11 10:25     ` Remy Horton
2018-05-14  8:21       ` Burakov, Anatoly
2018-05-14 11:29         ` Burakov, Anatoly
2018-05-14 12:23           ` Burakov, Anatoly
2018-05-15  6:24           ` Remy Horton
2018-05-15  8:37             ` Burakov, Anatoly
2018-04-26  8:06 ` [PATCH v2 2/2] memzone: allow IOVA-contiguous memzones with zero size Anatoly Burakov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=064458eb7fc48457ed4e7fed521e11e68cb32c62.1526296329.git.anatoly.burakov@intel.com \
    --to=anatoly.burakov@intel.com \
    --cc=dev@dpdk.org \
    --cc=remy.horton@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.