From: Cyrill Gorcunov via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: Serge Petrenko <sergepetrenko@tarantool.org>
Cc: v.shpilevoy@tarantool.org, tarantool-patches@dev.tarantool.org
Subject: Re: [Tarantool-patches] [PATCH v2] wal: introduce limits on simultaneous writes
Date: Mon, 15 Feb 2021 14:17:59 +0300 [thread overview]
Message-ID: <YCpYZ/K8V8ePZvSD@grain> (raw)
In-Reply-To: <20210211121750.46298-1-sergepetrenko@tarantool.org>
On Thu, Feb 11, 2021 at 03:17:50PM +0300, Serge Petrenko wrote:
> diff --git a/src/box/applier.cc b/src/box/applier.cc
> index 553db76fc..06aaa0a79 100644
> --- a/src/box/applier.cc
> +++ b/src/box/applier.cc
> @@ -967,6 +967,15 @@ applier_apply_tx(struct applier *applier, struct stailq *rows)
> goto success;
> }
>
> + /*
> + * Do not spam WAL with excess write requests, let it process what's
> + * piled up first.
> + * This is done before opening the transaction to avoid problems with
> + * yielding inside it.
> + */
> + if (journal_queue_is_full(current_journal))
> + journal_wait_queue();
> +
Serge, just a few comments, feel free to ignore.
Maybe it would be better to pass current_journal to journal_wait_queue,
otherwise it looks somehow inconsistent, no?
if (journal_queue_is_full(current_journal))
journal_wait_queue(current_journal);
Actually I would name journal queue engine as plain journalq, this would
look like
if (journalq_is_full(current_journal))
journalq_wait(current_journal);
But it is very humble pov, lets stick with long `journal_queue`.
...
> +/** Wake the journal queue up. */
> +static inline void
> +journal_queue_wakeup(struct journal *j, bool force_ready)
> +{
> + assert(j == current_journal);
Seems this assert is not needed. The overall idea of passing
journal as an argument is quite the reverse, ie to work with
any journal. This is not a blocker, could be cleaned up on top
or simply ignored.
> + assert(!rlist_empty(&j->waiters));
> + if (j->queue_is_woken)
> + return;
> + j->queue_is_woken = true;
> + journal_queue_wakeup_next(&j->waiters, force_ready);
> +}
> +
> +/**
> + * Check whether any of the queue size limits is reached.
> + * If the queue is full, we must wait for some of the entries to be written
> + * before proceeding with a new asynchronous write request.
> + */
> +static inline bool
> +journal_queue_is_full(struct journal *j)
> +{
> + assert(j == current_journal);
same, no need for assert()
> + return (j->queue_max_size != 0 && j->queue_size >= j->queue_max_size) ||
> + (j->queue_max_len != 0 && j->queue_len >= j->queue_max_len);
> +}
> +
> +/**
> + * Check whether anyone is waiting for the journal queue to empty. If there are
> + * other waiters we must go after them to preserve write order.
> + */
> +static inline bool
> +journal_queue_has_waiters(struct journal *j)
> +{
> + assert(j == current_journal);
same, no need for assert()
> + return !rlist_empty(&j->waiters);
> +}
> +
> +/** Yield until there's some space in the journal queue. */
> +void
> +journal_wait_queue(void);
> +
> /**
> * Complete asynchronous write.
> */
> @@ -131,15 +199,15 @@ static inline void
> journal_async_complete(struct journal_entry *entry)
> {
> assert(entry->write_async_cb != NULL);
> + current_journal->queue_len--;
> + current_journal->queue_size -= entry->approx_len;
Myabe worth to make queue ops closed into some helper? Because
length and size can't be updated without a tangle. IOW, something
like
static inline void
journal_queue_attr_dec(struct journal *j, struct journal_entry *entry)
{
j->queue_len--;
j->queue_size -= entry->approx_len;
}
static inline void
journal_queue_attr_inc(struct journal *j, struct journal_entry *entry)
{
j->queue_len++;
j->queue_size += entry->approx_len;
}
Again, this is my pov, **free to ignore**. attr here stands for
attributes because queue_len and queue_size are not the queue
itself but attributes which controls when we need to wait
data to be flushed.
> + assert(current_journal->queue_len >= 0);
> + assert(current_journal->queue_size >= 0);
> + if (journal_queue_has_waiters(current_journal))
> + journal_queue_wakeup(current_journal, false);
> entry->write_async_cb(entry);
> }
next prev parent reply other threads:[~2021-02-15 11:18 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-02-11 12:17 Serge Petrenko via Tarantool-patches
2021-02-15 11:17 ` Cyrill Gorcunov via Tarantool-patches [this message]
2021-02-16 12:47 ` Serge Petrenko via Tarantool-patches
2021-02-16 12:49 ` Cyrill Gorcunov via Tarantool-patches
2021-02-17 20:46 ` Vladislav Shpilevoy via Tarantool-patches
2021-02-18 20:06 ` Serge Petrenko via Tarantool-patches
2021-02-23 22:19 ` Vladislav Shpilevoy via Tarantool-patches
2021-02-24 19:32 ` Serge Petrenko via Tarantool-patches
2021-02-26 0:58 ` Vladislav Shpilevoy via Tarantool-patches
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=YCpYZ/K8V8ePZvSD@grain \
--to=tarantool-patches@dev.tarantool.org \
--cc=gorcunov@gmail.com \
--cc=sergepetrenko@tarantool.org \
--cc=v.shpilevoy@tarantool.org \
--subject='Re: [Tarantool-patches] [PATCH v2] wal: introduce limits on simultaneous writes' \
/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