Tarantool development patches archive
 help / color / mirror / Atom feed
From: Cyrill Gorcunov <gorcunov@gmail.com>
To: tarantool-patches@freelists.org
Cc: gorcunov@gmail.com, vdavydov.dev@gmail.com
Subject: [rfc 4/4] core/fiber: Shrink stack when recycling
Date: Sat, 02 Mar 2019 15:55:28 +0300	[thread overview]
Message-ID: <20190302130034.125890957@gmail.com> (raw)
In-Reply-To: <20190302125524.279852704@gmail.com>

[-- Attachment #1: fiber-stack-wmark-dyna-2 --]
[-- Type: text/plain, Size: 4741 bytes --]

Currently we've a static mark in stack to detect the situation
where its usage is close to exhausting. We can move forward and
try to shrink stack everytime it is recycling.

For this sake we add wmark_addr pointing into a fiber and
put it next to the last page on the stack. On recycle we
test if mark has been modified. If it is still present
we wimply shrink stack by one page and continue this way
until stack usage is balanced. Once we met first overwrite
we stop tracking and freeze the mark to not longer do any
access assuming stack won't get bigger.

Note that "stack is close to overflow" is still present
since it is separate mechanism.

Closes #3418
---
 src/lib/core/fiber.c |   65 +++++++++++++++++++++++++++++++++++++++++++--------
 src/lib/core/fiber.h |    2 +
 2 files changed, 57 insertions(+), 10 deletions(-)

Index: tarantool.git/src/lib/core/fiber.c
===================================================================
--- tarantool.git.orig/src/lib/core/fiber.c
+++ tarantool.git/src/lib/core/fiber.c
@@ -124,6 +124,9 @@ static const uint64_t poison_pool[] = {
 #define POISON_GAP	(128 + sizeof(poison_pool[0]))
 #define POISON_OFF	(POISON_GAP / sizeof(poison_pool[0]))
 
+#define wmark_freeze(_pp) do { *((uintptr_t *)(_pp)) |= (uintptr_t)1; } while (0)
+#define wmark_frozen(_p) ((uintptr_t)(_p) & (uintptr_t)1)
+
 static void fiber_wmark_recycle(struct fiber *fiber);
 
 void
@@ -763,6 +766,31 @@ stack_put_wmark(void *addr)
 }
 
 static void
+stack_shrink(struct fiber *fiber)
+{
+	void *hi, *lo;
+
+	if (stack_direction < 0) {
+		hi = fiber->stack + fiber->stack_size;
+		lo = fiber->stack_wmark_ofl + page_size;
+	} else {
+		hi = fiber->stack_wmark_ofl - page_size;
+		lo = fiber->stack - fiber->stack_size;
+	}
+
+	if (fiber->stack_wmark <= lo ||
+	    fiber->stack_wmark >= hi)
+		return;
+
+	madvise(fiber->stack_wmark, page_size, MADV_DONTNEED);
+	if (stack_direction < 0)
+		fiber->stack_wmark += page_size;
+	else
+		fiber->stack_wmark -= page_size;
+	stack_put_wmark(fiber);
+}
+
+static void
 fiber_wmark_recycle(struct fiber *fiber)
 {
 	static bool overflow_warned = false;
@@ -772,20 +800,30 @@ fiber_wmark_recycle(struct fiber *fiber)
 
 	/*
 	 * We are watching for stack overflow in one shot way:
-	 * firstly to not spam a user with messages and secondly
-	 * to relax system from additional operations while our
-	 * watermark is not dynamic.
+	 * to not spam a user with messages.
 	 */
-	if (overflow_warned)
-		return;
-
-	if (!stack_has_wmark(fiber->stack_wmark_ofl)) {
-		if (!overflow_warned) {
+	if (!overflow_warned) {
+		if (!stack_has_wmark(fiber->stack_wmark_ofl)) {
 			say_warn("fiber %d is close to a stack limit",
 				 fiber->name, fiber->fid);
 			overflow_warned = true;
 		}
 	}
+
+	if (wmark_frozen(fiber->stack_wmark))
+		return;
+
+	/*
+	 * On recycle we're trying to shrink stack
+	 * as much as we can until first mark overwrite
+	 * detected, then we simply freeze watermark and
+	 * assume the stack is balanced and won't change
+	 * much in future.
+	 */
+	if (!stack_has_wmark(fiber->stack_wmark))
+		wmark_freeze(&fiber->stack_wmark);
+	else
+		stack_shrink(fiber);
 }
 
 static void
@@ -797,6 +835,7 @@ fiber_wmark_init(struct fiber *fiber)
 	 */
 	if (fiber->flags & FIBER_CUSTOM_STACK) {
 		fiber->stack_wmark_ofl = NULL;
+		fiber->stack_wmark = NULL;
 		return;
 	}
 
@@ -805,11 +844,15 @@ fiber_wmark_init(struct fiber *fiber)
 	 * to catch if we're getting close to
 	 * stack exhausting.
 	 */
-	if (stack_direction < 0)
+	if (stack_direction < 0) {
 		fiber->stack_wmark_ofl = fiber->stack;
-	else
+		fiber->stack_wmark = fiber->stack_wmark_ofl + page_size;
+	} else {
 		fiber->stack_wmark_ofl = fiber->stack + fiber->stack_size - page_size;
+		fiber->stack_wmark = fiber->stack_wmark_ofl - page_size;
+	}
 	stack_put_wmark(fiber->stack_wmark_ofl);
+	stack_put_wmark(fiber->stack_wmark);
 }
 
 static int
@@ -1030,9 +1073,11 @@ cord_create(struct cord *cord, const cha
 	tt_pthread_attr_getstack(cord->id, &cord->sched.stack,
 				 &cord->sched.stack_size);
 	cord->sched.stack_wmark_ofl = cord->sched.stack;
+	cord->sched.stack_wmark = cord->sched.stack;
 #else
 	cord->sched.stack = NULL;
 	cord->sched.stack_wmark_ofl = NULL;
+	cord->sched.stack_wmark = NULL;
 	cord->sched.stack_size = 0;
 #endif
 }
Index: tarantool.git/src/lib/core/fiber.h
===================================================================
--- tarantool.git.orig/src/lib/core/fiber.h
+++ tarantool.git/src/lib/core/fiber.h
@@ -348,6 +348,8 @@ struct fiber {
 	struct slab *stack_slab;
 	/** Coro stack addr. */
 	void *stack;
+	/** Stack watermark addr. */
+	void *stack_wmark;
 	/** Stack watermark addr for overflow detection. */
 	void *stack_wmark_ofl;
 	/** Coro stack size. */

  parent reply	other threads:[~2019-03-02 12:55 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-02 12:55 [rfc 0/4] fiber/stack: Increase stack size and shrink rss usage Cyrill Gorcunov
2019-03-02 12:55 ` [rfc 1/4] core/fiber: Increase default stack size Cyrill Gorcunov
2019-03-02 12:55 ` [rfc 2/4] core/fiber: Mark stack as unneeded on creation Cyrill Gorcunov
2019-03-02 12:55 ` [rfc 3/4] core/fiber: Put static watermark into stack to track its usage Cyrill Gorcunov
2019-03-05  8:08   ` [tarantool-patches] " Konstantin Osipov
2019-03-05  8:17     ` Cyrill Gorcunov
2019-03-05  8:10   ` Konstantin Osipov
2019-03-05  8:14     ` Cyrill Gorcunov
2019-03-05 19:17     ` Cyrill Gorcunov
2019-03-05  8:20   ` Konstantin Osipov
2019-03-05  8:27     ` Cyrill Gorcunov
2019-03-02 12:55 ` Cyrill Gorcunov [this message]
2019-03-05  8:30   ` [tarantool-patches] [rfc 4/4] core/fiber: Shrink stack when recycling Konstantin Osipov
2019-03-05  8:41     ` Cyrill Gorcunov
2019-03-05  9:32       ` [tarantool-patches] " Konstantin Osipov

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=20190302130034.125890957@gmail.com \
    --to=gorcunov@gmail.com \
    --cc=tarantool-patches@freelists.org \
    --cc=vdavydov.dev@gmail.com \
    --subject='Re: [rfc 4/4] core/fiber: Shrink stack when recycling' \
    /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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox