From: Thomas Hellstrom <thellstrom@vmware.com>
To: "Jérôme Glisse" <j.glisse@gmail.com>
Cc: "Michel Dänzer" <michel@daenzer.net>,
"Jérôme Glisse" <jglisse@redhat.com>,
dri-devel@lists.freedesktop.org,
"Konrad Rzeszutek Wilk" <konrad.wilk@oracle.com>
Subject: Re: [PATCH 3/3] drm/ttm: under memory pressure minimize the size of memory pool
Date: Wed, 13 Aug 2014 11:06:25 +0200 [thread overview]
Message-ID: <53EB2A91.3000804@vmware.com> (raw)
In-Reply-To: <1407901926-24516-4-git-send-email-j.glisse@gmail.com>
On 08/13/2014 05:52 AM, Jérôme Glisse wrote:
> From: Jérôme Glisse <jglisse@redhat.com>
>
> When experiencing memory pressure we want to minimize pool size so that
> memory we just shrinked is not added back again just as the next thing.
>
> This will divide by 2 the maximum pool size for each device each time
> the pool have to shrink. The limit is bumped again is next allocation
> happen after one second since the last shrink. The one second delay is
> obviously an arbitrary choice.
Jérôme,
I don't like this patch. It adds extra complexity and its usefulness is
highly questionable.
There are a number of caches in the system, and if all of them added
some sort of voluntary shrink heuristics like this, we'd end up with
impossible-to-debug unpredictable performance issues.
We should let the memory subsystem decide when to reclaim pages from
caches and what caches to reclaim them from.
/Thomas
>
> Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
> Cc: Mario Kleiner <mario.kleiner.de@gmail.com>
> Cc: Michel Dänzer <michel@daenzer.net>
> Cc: Thomas Hellstrom <thellstrom@vmware.com>
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> ---
> drivers/gpu/drm/ttm/ttm_page_alloc.c | 35 +++++++++++++++++++++++++-------
> drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 27 ++++++++++++++++++++++--
> 2 files changed, 53 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
> index 09874d6..ab41adf 100644
> --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
> +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
> @@ -68,6 +68,8 @@
> * @list: Pool of free uc/wc pages for fast reuse.
> * @gfp_flags: Flags to pass for alloc_page.
> * @npages: Number of pages in pool.
> + * @cur_max_size: Current maximum size for the pool.
> + * @shrink_timeout: Timeout for pool maximum size restriction.
> */
> struct ttm_page_pool {
> spinlock_t lock;
> @@ -76,6 +78,8 @@ struct ttm_page_pool {
> gfp_t gfp_flags;
> unsigned npages;
> char *name;
> + unsigned cur_max_size;
> + unsigned long last_shrink;
> unsigned long nfrees;
> unsigned long nrefills;
> };
> @@ -289,6 +293,16 @@ static void ttm_pool_update_free_locked(struct ttm_page_pool *pool,
> pool->nfrees += freed_pages;
> }
>
> +static inline void ttm_pool_update_max_size(struct ttm_page_pool *pool)
> +{
> + if (time_before(jiffies, pool->shrink_timeout))
> + return;
> + /* In case we reached zero bounce back to 512 pages. */
> + pool->cur_max_size = max(pool->cur_max_size << 1, 512);
> + pool->cur_max_size = min(pool->cur_max_size,
> + _manager->options.max_size);
> +}
> +
> /**
> * Free pages from pool.
> *
> @@ -407,6 +421,9 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
> if (shrink_pages == 0)
> break;
> pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];
> + /* No matter what make sure the pool do not grow in next second. */
> + pool->cur_max_size = pool->cur_max_size >> 1;
> + pool->shrink_timeout = jiffies + HZ;
> shrink_pages = ttm_page_pool_free(pool, nr_free,
> sc->gfp_mask);
> freed += nr_free - shrink_pages;
> @@ -701,13 +718,12 @@ static void ttm_put_pages(struct page **pages, unsigned npages, int flags,
> }
> /* Check that we don't go over the pool limit */
> npages = 0;
> - if (pool->npages > _manager->options.max_size) {
> - npages = pool->npages - _manager->options.max_size;
> - /* free at least NUM_PAGES_TO_ALLOC number of pages
> - * to reduce calls to set_memory_wb */
> - if (npages < NUM_PAGES_TO_ALLOC)
> - npages = NUM_PAGES_TO_ALLOC;
> - }
> + /*
> + * Free at least NUM_PAGES_TO_ALLOC number of pages to reduce calls to
> + * set_memory_wb.
> + */
> + if (pool->npages > (pool->cur_max_size + NUM_PAGES_TO_ALLOC))
> + npages = pool->npages - pool->cur_max_size;
> spin_unlock_irqrestore(&pool->lock, irq_flags);
> if (npages)
> ttm_page_pool_free(pool, npages, GFP_KERNEL);
> @@ -751,6 +767,9 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags,
> return 0;
> }
>
> + /* Update pool size in case shrinker limited it. */
> + ttm_pool_update_max_size(pool);
> +
> /* combine zero flag to pool flags */
> gfp_flags |= pool->gfp_flags;
>
> @@ -803,6 +822,8 @@ static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags,
> pool->npages = pool->nfrees = 0;
> pool->gfp_flags = flags;
> pool->name = name;
> + pool->cur_max_size = _manager->options.max_size;
> + pool->shrink_timeout = jiffies;
> }
>
> int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
> diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
> index a076ff3..80b10aa 100644
> --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
> +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
> @@ -93,6 +93,8 @@ enum pool_type {
> * @size: Size used during DMA allocation.
> * @npages_free: Count of available pages for re-use.
> * @npages_in_use: Count of pages that are in use.
> + * @cur_max_size: Current maximum size for the pool.
> + * @shrink_timeout: Timeout for pool maximum size restriction.
> * @nfrees: Stats when pool is shrinking.
> * @nrefills: Stats when the pool is grown.
> * @gfp_flags: Flags to pass for alloc_page.
> @@ -110,6 +112,8 @@ struct dma_pool {
> unsigned size;
> unsigned npages_free;
> unsigned npages_in_use;
> + unsigned cur_max_size;
> + unsigned long last_shrink;
> unsigned long nfrees; /* Stats when shrunk. */
> unsigned long nrefills; /* Stats when grown. */
> gfp_t gfp_flags;
> @@ -331,6 +335,17 @@ static void __ttm_dma_free_page(struct dma_pool *pool, struct dma_page *d_page)
> kfree(d_page);
> d_page = NULL;
> }
> +
> +static inline void ttm_dma_pool_update_max_size(struct dma_pool *pool)
> +{
> + if (time_before(jiffies, pool->shrink_timeout))
> + return;
> + /* In case we reached zero bounce back to 512 pages. */
> + pool->cur_max_size = max(pool->cur_max_size << 1, 512);
> + pool->cur_max_size = min(pool->cur_max_size,
> + _manager->options.max_size);
> +}
> +
> static struct dma_page *__ttm_dma_alloc_page(struct dma_pool *pool)
> {
> struct dma_page *d_page;
> @@ -606,6 +621,8 @@ static struct dma_pool *ttm_dma_pool_init(struct device *dev, gfp_t flags,
> pool->size = PAGE_SIZE;
> pool->type = type;
> pool->nrefills = 0;
> + pool->cur_max_size = _manager->options.max_size;
> + pool->shrink_timeout = jiffies;
> p = pool->name;
> for (i = 0; i < 5; i++) {
> if (type & t[i]) {
> @@ -892,6 +909,9 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev)
> }
> }
>
> + /* Update pool size in case shrinker limited it. */
> + ttm_dma_pool_update_max_size(pool);
> +
> INIT_LIST_HEAD(&ttm_dma->pages_list);
> for (i = 0; i < ttm->num_pages; ++i) {
> ret = ttm_dma_pool_get_pages(pool, ttm_dma, i);
> @@ -953,9 +973,9 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev)
> } else {
> pool->npages_free += count;
> list_splice(&ttm_dma->pages_list, &pool->free_list);
> - if (pool->npages_free >= (_manager->options.max_size +
> + if (pool->npages_free >= (pool->cur_max_size +
> NUM_PAGES_TO_ALLOC))
> - npages = pool->npages_free - _manager->options.max_size;
> + npages = pool->npages_free - pool->cur_max_size;
> }
> spin_unlock_irqrestore(&pool->lock, irq_flags);
>
> @@ -1024,6 +1044,9 @@ ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
> /* Do it in round-robin fashion. */
> if (++idx < pool_offset)
> continue;
> + /* No matter what make sure the pool do not grow in next second. */
> + p->pool->cur_max_size = p->pool->cur_max_size >> 1;
> + p->pool->shrink_timeout = jiffies + HZ;
> nr_free = shrink_pages;
> shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free,
> sc->gfp_mask);
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
next prev parent reply other threads:[~2014-08-13 9:06 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-13 3:52 [PATCH 0/3] drm/ttm: hard to swim in an empty pool Jérôme Glisse
2014-08-13 3:52 ` [PATCH 1/3] drm/ttm: set sensible pool size limit Jérôme Glisse
2014-08-13 6:24 ` Michel Dänzer
2014-08-13 3:52 ` [PATCH 2/3] drm/ttm: fix object deallocation to properly fill in the page pool Jérôme Glisse
2015-03-25 19:06 ` Konrad Rzeszutek Wilk
2015-07-06 9:11 ` Michel Dänzer
2015-07-06 16:10 ` Jerome Glisse
2015-07-07 6:39 ` Michel Dänzer
2015-07-07 17:41 ` Jerome Glisse
2015-07-08 2:34 ` Michel Dänzer
2014-08-13 3:52 ` [PATCH 3/3] drm/ttm: under memory pressure minimize the size of memory pool Jérôme Glisse
2014-08-13 6:32 ` Michel Dänzer
2014-08-13 9:06 ` Thomas Hellstrom [this message]
2014-08-13 10:42 ` Daniel Vetter
2014-08-13 12:35 ` GEM memory DOS (WAS Re: [PATCH 3/3] drm/ttm: under memory pressure minimize the size of memory pool) Thomas Hellstrom
2014-08-13 12:40 ` David Herrmann
2014-08-13 12:48 ` Thomas Hellstrom
2014-08-13 13:01 ` Daniel Vetter
2014-08-13 14:09 ` Oded Gabbay
2014-08-13 15:19 ` Thomas Hellstrom
2014-08-13 16:30 ` Daniel Vetter
2014-08-13 15:13 ` Thomas Hellstrom
2014-08-13 16:24 ` Daniel Vetter
2014-08-13 16:30 ` Alex Deucher
2014-08-13 16:38 ` Daniel Vetter
2014-08-13 16:45 ` Daniel Vetter
2014-08-13 17:38 ` Thomas Hellstrom
2014-08-13 17:20 ` Thomas Hellstrom
2014-08-14 22:29 ` Jesse Barnes
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=53EB2A91.3000804@vmware.com \
--to=thellstrom@vmware.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=j.glisse@gmail.com \
--cc=jglisse@redhat.com \
--cc=konrad.wilk@oracle.com \
--cc=michel@daenzer.net \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox