From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Date: Tue, 22 Jan 2019 12:09:01 +0300 From: Vladimir Davydov Subject: Re: [PATCH 9/9] vinyl: throttle tx to ensure compaction keeps up with dumps Message-ID: <20190122090901.6dyslnsi4httxbxe@esperanza> References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: To: tarantool-patches@freelists.org List-ID: On Mon, Jan 21, 2019 at 12:17:08AM +0300, Vladimir Davydov wrote: > +void > +vy_regulator_update_rate_limit(struct vy_regulator *regulator, > + const struct vy_scheduler_stat *stat, > + int compaction_threads) > +{ > + struct vy_scheduler_stat *last = ®ulator->sched_stat_last; > + struct vy_scheduler_stat *recent = ®ulator->sched_stat_recent; > + /* > + * The maximal dump rate the database can handle while > + * maintaining the current level of write amplification > + * equals: > + * > + * dump_output > + * max_dump_rate = compaction_rate * ----------------- > + * compaction_output > + * > + * The average compaction rate can be estimated with: > + * > + * compaction_output > + * compaction_rate = compaction_threads * ----------------- > + * compaction_time > + * > + * Putting it all together and taking into account data > + * compaction during memory dump, we get for the max > + * transaction rate: > + * > + * dump_input > + * max_tx_rate = max_dump_rate * ----------- = > + * dump_output > + * > + * dump_input > + * compaction_threads * --------------- > + * compaction_time > + * > + * We set the rate limit to half that to leave the database > + * engine enough room needed for growing write amplification. > + */ > + recent->dump_count += stat->dump_count - last->dump_count; > + recent->dump_input += stat->dump_input - last->dump_input; > + recent->compaction_time += stat->compaction_time - > + last->compaction_time; > + *last = *stat; > + > + if (recent->compaction_time == 0 || > + recent->dump_input < (int)VY_DUMP_SIZE_ACCT_MIN) > + return; > + > + double rate = 0.5 * compaction_threads * recent->dump_input / > + recent->compaction_time; ^^^ I ran some tests that showed that 0.75 down-shifting coefficient works fine as well: the instance didn't accumulate much of compaction debt while the average compaction thread utilization grew from 50-60% to about 80%. However, write amplification decreased from 4 to 3.6, which indicates that the instance didn't have enough breathing space for compaction to keep up with dumps. Setting the coefficient to a higher value, say 0.9, results in a very bad performance - compaction queue grows up to 100% and write amplification stays at about 2. Probably, we could make this coefficient dynamic - scale it from 0.5 up to 1 depending on the compaction queue size - but that's going to be tricky to implement while maintaining a steady RPS, without spikes and falls - we'll need to run many more tests. I think we should start with a static coefficient, which is predictable and results in a steady RPS, and then think of something more sophisticated if there's a demand for that. If so, what coefficient should we choose? 0.5 is safe while 0.75 yields higher RPS. The user can always increase the number of compaction threads if RPS happens to be too small due to regulator decisions, but still, which one is better? > + vy_quota_set_rate_limit(regulator->quota, VY_QUOTA_RESOURCE_DISK, > + MIN(rate, SIZE_MAX)); > + > + /* > + * Periodically rotate statistics for quicker adaptation > + * to workload changes. > + */ > + if (recent->dump_count > VY_RECENT_DUMP_COUNT) { > + recent->dump_count /= 2; > + recent->dump_input /= 2; > + recent->compaction_time /= 2; > + } > +}