| /** @file |
| |
| Pre-Warming Pool Size Algorithm |
| |
| v1: periodical pre-warming only |
| v2: periodical pre-warming + event based pre-warming |
| |
| @section license License |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| #pragma once |
| |
| #include "tscore/ink_assert.h" |
| #include "tscore/ink_error.h" |
| |
| #include <cstdint> |
| #include <algorithm> |
| |
| namespace PreWarm |
| { |
| enum class Algorithm { |
| V1 = 1, |
| V2, |
| }; |
| |
| inline PreWarm::Algorithm |
| algorithm_version(int i) |
| { |
| switch (i) { |
| case 2: |
| return PreWarm::Algorithm::V2; |
| case 1: |
| return PreWarm::Algorithm::V1; |
| default: |
| ink_abort("unsupported version v=%d", i); |
| } |
| } |
| |
| /** |
| Periodical pre-warming for algorithm v1 |
| |
| Expand the pool size to @requested_size |
| |
| @params min : min connections (configured) |
| @params max : max connections (configured), -1 : unlimited |
| |
| @return how many connections needs to be pre-warmed for next period |
| */ |
| inline uint32_t |
| prewarm_size_v1_on_event_interval(uint32_t requested_size, uint32_t current_size, uint32_t min, int32_t max) |
| { |
| uint32_t n = requested_size; |
| |
| // keep tunnel_min connections pre-warmed at least |
| n = std::max(n, min); |
| |
| if (max >= 0) { |
| n = std::min(n, static_cast<uint32_t>(max)); |
| } |
| |
| if (current_size >= n) { |
| // we already have enough connections, don't need to open new connection |
| return 0; |
| } else { |
| n -= current_size; |
| } |
| |
| return n; |
| } |
| |
| /** |
| Periodical pre-warming for algorithm v2 |
| |
| Expand the pool size to @current_size + @miss * @rate. The event based pre-warming handles the hit cases. |
| |
| @params min : min connections (configured) |
| @params max : max connections (configured), -1 : unlimited |
| |
| @return how many connections needs to be pre-warmed for next period |
| */ |
| inline uint32_t |
| prewarm_size_v2_on_event_interval(uint32_t hit, uint32_t miss, uint32_t current_size, uint32_t min, int32_t max, double rate) |
| { |
| if (hit + miss + current_size < min) { |
| // fallback to v1 to keep min size |
| return prewarm_size_v1_on_event_interval(hit + miss, current_size, min, max); |
| } |
| |
| // Reached limit - do nothing |
| if (max >= 0 && current_size >= static_cast<uint32_t>(max)) { |
| return 0; |
| } |
| |
| // Add #miss connections to the pool |
| uint32_t n = miss * rate; |
| |
| // Check limit |
| if (max >= 0 && n + current_size > static_cast<uint32_t>(max)) { |
| ink_release_assert(static_cast<uint32_t>(max) > current_size); |
| n = max - current_size; |
| } |
| |
| return n; |
| } |
| |
| } // namespace PreWarm |