Skip to content

Commit def57ff

Browse files
authored
[k2] undo revert of "make init instance memory size adjustable" and add small fixes (#1615)
* Undo revert of "make init instance memory size adjustable" * Decreased default min extra memory size * Removed useless parameter of request_extra_memory --------- Signed-off-by: Petr Shumilov <p.shumilov@vkteam.ru>
1 parent ccd5a17 commit def57ff

11 files changed

Lines changed: 104 additions & 43 deletions

File tree

runtime-common/core/allocator/runtime-allocator.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ struct RuntimeAllocator final : vk::not_copyable {
1313
static RuntimeAllocator& get() noexcept;
1414

1515
RuntimeAllocator() = default;
16-
RuntimeAllocator(size_t script_mem_size, size_t oom_handling_mem_size);
16+
RuntimeAllocator(size_t script_mem_size, size_t min_extra_mem_size, size_t oom_handling_mem_size);
1717

1818
void init(void* buffer, size_t script_mem_size, size_t oom_handling_mem_size);
1919
void free();
@@ -28,5 +28,12 @@ struct RuntimeAllocator final : vk::not_copyable {
2828
void* realloc_global_memory(void* mem, size_t new_size, size_t old_size) noexcept;
2929
void free_global_memory(void* mem, size_t size) noexcept;
3030

31+
private:
32+
void request_extra_memory(size_t requested_size) noexcept;
33+
34+
public:
3135
memory_resource::unsynchronized_pool_resource memory_resource;
36+
37+
private:
38+
size_t m_min_extra_mem_size{0};
3239
};

runtime-common/core/memory-resource/unsynchronized_pool_resource.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010

1111
namespace memory_resource {
1212

13-
constexpr size_t unsynchronized_pool_resource::MAX_CHUNK_BLOCK_SIZE_;
14-
1513
void unsynchronized_pool_resource::init(void* buffer, size_t buffer_size, size_t oom_handling_buffer_size) noexcept {
1614
monotonic_buffer_resource::init(buffer, buffer_size);
1715

runtime-common/core/memory-resource/unsynchronized_pool_resource.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class unsynchronized_pool_resource : private monotonic_buffer_resource {
3030
void* allocate(size_t size) noexcept {
3131
void* mem = nullptr;
3232
const auto aligned_size = details::align_for_chunk(size);
33-
if (aligned_size < MAX_CHUNK_BLOCK_SIZE_) {
33+
if (aligned_size < MAX_CHUNK_BLOCK_SIZE) {
3434
mem = try_allocate_small_piece(aligned_size);
3535
if (!mem) {
3636
mem = allocate_small_piece_from_fallback_resource(aligned_size);
@@ -123,7 +123,7 @@ class unsynchronized_pool_resource : private monotonic_buffer_resource {
123123
void put_memory_back(void* mem, size_t size) noexcept {
124124
const bool from_extra_pool = (extra_memory_head_ != &extra_memory_tail_) && is_memory_from_extra_pool(mem, size);
125125
if (from_extra_pool || !monotonic_buffer_resource::put_memory_back(mem, size)) {
126-
if (size < MAX_CHUNK_BLOCK_SIZE_) {
126+
if (size < MAX_CHUNK_BLOCK_SIZE) {
127127
size_t chunk_id = details::get_chunk_id(size);
128128
free_chunks_[chunk_id].put_mem(mem);
129129
++stats_.small_memory_pieces;
@@ -134,15 +134,18 @@ class unsynchronized_pool_resource : private monotonic_buffer_resource {
134134
}
135135
}
136136

137+
public:
138+
static constexpr size_t MAX_CHUNK_BLOCK_SIZE{static_cast<size_t>(16U * 1024U)};
139+
140+
private:
137141
details::memory_chunk_tree huge_pieces_;
138142
monotonic_buffer_resource fallback_resource_;
139143
size_t oom_handling_memory_size_{0};
140144

141145
extra_memory_pool* extra_memory_head_{nullptr};
142146
extra_memory_pool extra_memory_tail_{sizeof(extra_memory_pool)};
143147

144-
static constexpr size_t MAX_CHUNK_BLOCK_SIZE_{static_cast<size_t>(16U * 1024U)};
145-
std::array<details::memory_chunk_list, details::get_chunk_id(MAX_CHUNK_BLOCK_SIZE_)> free_chunks_;
148+
std::array<details::memory_chunk_list, details::get_chunk_id(MAX_CHUNK_BLOCK_SIZE)> free_chunks_;
146149
};
147150

148151
} // namespace memory_resource

runtime-light/allocator/allocator-state.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include "runtime-common/core/allocator/runtime-allocator.h"
1212
#include "runtime-light/stdlib/diagnostics/logs.h"
1313

14+
inline constexpr auto DEFAULT_MIN_EXTRA_MEMORY_POOL_SIZE{static_cast<size_t>(1 * 1024U * 1024U)}; // 1Mib
15+
1416
class AllocatorState final : private vk::not_copyable {
1517
uint32_t m_libc_alloc_allowed{};
1618

@@ -27,8 +29,8 @@ class AllocatorState final : private vk::not_copyable {
2729
return m_libc_alloc_allowed != 0;
2830
}
2931

30-
AllocatorState(size_t script_mem_size, size_t oom_handling_mem_size) noexcept
31-
: allocator(script_mem_size, oom_handling_mem_size) {}
32+
AllocatorState(size_t script_mem_size, size_t min_extra_mem_size, size_t oom_handling_mem_size) noexcept
33+
: allocator(script_mem_size, min_extra_mem_size, oom_handling_mem_size) {}
3234

3335
static const AllocatorState& get() noexcept;
3436
static AllocatorState& get_mutable() noexcept;

runtime-light/allocator/runtime-light-allocator.cpp

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,12 @@
1010
#include "runtime-light/k2-platform/k2-api.h"
1111
#include "runtime-light/stdlib/diagnostics/logs.h"
1212

13-
namespace {
14-
// TODO: make it depend on max chunk size, e.g. MIN_EXTRA_MEM_SIZE = f(MAX_CHUNK_SIZE);
15-
constexpr auto MIN_EXTRA_MEM_SIZE = static_cast<size_t>(1024U * 1024U); // extra mem size should be greater than max chunk block size
16-
constexpr auto EXTRA_MEMORY_MULTIPLIER = 2;
17-
18-
void request_extra_memory(size_t requested_size) noexcept {
19-
const size_t extra_mem_size{std::max(MIN_EXTRA_MEM_SIZE, EXTRA_MEMORY_MULTIPLIER * requested_size)};
20-
auto& allocator{RuntimeAllocator::get()};
21-
auto* extra_mem{allocator.alloc_global_memory(extra_mem_size)};
22-
allocator.memory_resource.add_extra_memory(new (extra_mem) memory_resource::extra_memory_pool{extra_mem_size});
23-
}
24-
25-
} // namespace
26-
2713
RuntimeAllocator& RuntimeAllocator::get() noexcept {
2814
return AllocatorState::get_mutable().allocator;
2915
}
3016

31-
RuntimeAllocator::RuntimeAllocator(size_t script_mem_size, size_t oom_handling_mem_size) {
17+
RuntimeAllocator::RuntimeAllocator(size_t script_mem_size, size_t min_extra_mem_size, size_t oom_handling_mem_size)
18+
: m_min_extra_mem_size(min_extra_mem_size) {
3219
kphp::log::debug("create runtime allocator -> {:p}: script memory -> {}, oom handling size -> {}", reinterpret_cast<void*>(this), script_mem_size,
3320
oom_handling_mem_size);
3421
void* buffer{alloc_global_memory(script_mem_size)};
@@ -113,3 +100,19 @@ void* RuntimeAllocator::realloc_global_memory(void* old_mem, size_t new_size, si
113100
void RuntimeAllocator::free_global_memory(void* mem, size_t /*unused*/) noexcept {
114101
k2::free(mem);
115102
}
103+
104+
void RuntimeAllocator::request_extra_memory(size_t requested_size) noexcept {
105+
// Extra mem size have to be greater than max chunk block
106+
const auto min_size{std::max(m_min_extra_mem_size, memory_resource::unsynchronized_pool_resource::MAX_CHUNK_BLOCK_SIZE)};
107+
108+
// If the requested size is greater than or equal to half of min_size, it’s more efficient to allocate a multiple of the requested size.
109+
size_t extra_mem_size{std::max(min_size, 2 * requested_size)};
110+
111+
// Take into account internal layout of `memory_resource::extra_memory_pool`
112+
extra_mem_size += sizeof(memory_resource::extra_memory_pool);
113+
114+
kphp::log::debug("requested extra memory pool with size {} bytes, will be allocated {} bytes", requested_size, extra_mem_size);
115+
116+
auto* extra_mem{alloc_global_memory(extra_mem_size)};
117+
memory_resource.add_extra_memory(new (extra_mem) memory_resource::extra_memory_pool{extra_mem_size});
118+
}

runtime-light/runtime-light.cpp

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,9 @@
1515
#define VISIBILITY_DEFAULT __attribute__((visibility("default")))
1616

1717
VISIBILITY_DEFAULT ImageState* k2_create_image() {
18-
kphp::log::debug("start image state creation");
18+
kphp::log::debug("start image state creation, requested {} bytes", sizeof(ImageState));
1919
auto* image_state_ptr{static_cast<ImageState*>(k2::alloc(sizeof(ImageState)))};
20-
if (image_state_ptr == nullptr) [[unlikely]] {
21-
kphp::log::error("can't allocate enough memory for image state");
22-
}
20+
kphp::log::assertion(image_state_ptr != nullptr); // Not enough memory for image state
2321
kphp::log::debug("finish image state creation");
2422
return image_state_ptr;
2523
}
@@ -32,11 +30,9 @@ VISIBILITY_DEFAULT void k2_init_image() {
3230
}
3331

3432
VISIBILITY_DEFAULT ComponentState* k2_create_component() {
35-
kphp::log::debug("start component state creation");
33+
kphp::log::debug("start component state creation, requested {} bytes", sizeof(ComponentState));
3634
auto* component_state_ptr{static_cast<ComponentState*>(k2::alloc(sizeof(ComponentState)))};
37-
if (component_state_ptr == nullptr) [[unlikely]] {
38-
kphp::log::error("can't allocate enough memory for component state");
39-
}
35+
kphp::log::assertion(component_state_ptr != nullptr); // Not enough memory for component state
4036
kphp::log::debug("finish component state creation");
4137
return component_state_ptr;
4238
}
@@ -48,11 +44,9 @@ VISIBILITY_DEFAULT void k2_init_component() {
4844
}
4945

5046
VISIBILITY_DEFAULT InstanceState* k2_create_instance() {
51-
kphp::log::debug("start instance state creation");
47+
kphp::log::debug("start instance state creation, requested {} bytes", sizeof(InstanceState));
5248
auto* instance_state_ptr{static_cast<InstanceState*>(k2::alloc(sizeof(InstanceState)))};
53-
if (instance_state_ptr == nullptr) [[unlikely]] {
54-
kphp::log::error("can't allocate enough memory for instance state");
55-
}
49+
kphp::log::assertion(instance_state_ptr != nullptr); // Not enough memory for instance state
5650
kphp::log::debug("finish instance state creation");
5751
return instance_state_ptr;
5852
}

runtime-light/state/component-state.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44

55
#include "runtime-light/state/component-state.h"
66

7+
#include <charconv>
78
#include <cstddef>
9+
#include <cstdint>
810
#include <cstring>
911
#include <iterator>
1012
#include <memory>
13+
#include <optional>
1114
#include <span>
1215
#include <string_view>
1316
#include <sys/mman.h>
1417
#include <sys/stat.h>
18+
#include <system_error>
1519
#include <utility>
1620

1721
#include "runtime-common/core/runtime-core.h"
@@ -20,6 +24,24 @@
2024
#include "runtime-light/stdlib/diagnostics/logs.h"
2125
#include "runtime-light/stdlib/file/resource.h"
2226

27+
namespace {
28+
29+
std::optional<uint64_t> parse_uint64(std::string_view value_view) noexcept {
30+
// Num of symbols in max u64 (18_446_744_073_709_551_615) is 20
31+
if (value_view.empty() || value_view.size() > 20) {
32+
return std::nullopt;
33+
}
34+
35+
uint64_t res{};
36+
if (const auto [ptr, err_code]{std::from_chars(value_view.begin(), value_view.end(), /* out paremeter */ res)};
37+
err_code != std::errc{} || ptr != value_view.end()) {
38+
return std::nullopt;
39+
}
40+
return res;
41+
}
42+
43+
} // namespace
44+
2345
void ComponentState::parse_env() noexcept {
2446
for (auto i = 0; i < envc; ++i) {
2547
const auto [env_key, env_value]{k2::env_fetch(i)};
@@ -92,6 +114,24 @@ void ComponentState::parse_exit_after_response_arg(std::string_view value_view)
92114
}
93115
}
94116

117+
void ComponentState::parse_initial_instance_memory_size_arg(std::string_view value_view) noexcept {
118+
const auto parsed{parse_uint64(value_view)};
119+
if (!parsed) {
120+
kphp::log::error("couldn't parse initial instance memory size, got {}", value_view);
121+
}
122+
initial_instance_memory_size = *parsed;
123+
kphp::log::info("set initial instance memory size to {} bytes", initial_instance_memory_size);
124+
}
125+
126+
void ComponentState::parse_min_instance_extra_memory_size_arg(std::string_view value_view) noexcept {
127+
const auto parsed{parse_uint64(value_view)};
128+
if (!parsed) {
129+
kphp::log::error("couldn't parse min instance extra memory size, got {}", value_view);
130+
}
131+
min_instance_extra_memory_size = *parsed;
132+
kphp::log::info("set min instance extra memory size to {} bytes", min_instance_extra_memory_size);
133+
}
134+
95135
void ComponentState::parse_args() noexcept {
96136
for (auto i = 0; i < argc; ++i) {
97137
const auto [arg_key, arg_value]{k2::arg_fetch(i)};
@@ -108,6 +148,10 @@ void ComponentState::parse_args() noexcept {
108148
parse_cluster_name_arg(value_view);
109149
} else if (key_view == EXIT_AFTER_RESPONSE_ARG) {
110150
parse_exit_after_response_arg(value_view);
151+
} else if (key_view == INITIAL_INSTANCE_MEMORY_SIZE_ARG) {
152+
parse_initial_instance_memory_size_arg(value_view);
153+
} else if (key_view == MIN_INSTANCE_EXTRA_MEMORY_SIZE_ARG) {
154+
parse_min_instance_extra_memory_size_arg(value_view);
111155
} else {
112156
kphp::log::warning("unexpected argument format: {}", key_view);
113157
}

runtime-light/state/component-state.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include "runtime-light/stdlib/kml/kml-state.h"
2020

2121
struct ComponentState final : private vk::not_copyable {
22-
AllocatorState component_allocator_state{INIT_COMPONENT_ALLOCATOR_SIZE, 0};
22+
AllocatorState component_allocator_state{INIT_COMPONENT_ALLOCATOR_SIZE, DEFAULT_MIN_EXTRA_MEMORY_POOL_SIZE, 0};
2323
KmlComponentState kml_component_state; // This member does not hold any KPHP types, so setting a reference counter is unnecessary.
2424

2525
const uint32_t argc{k2::args_count()};
@@ -29,6 +29,8 @@ struct ComponentState final : private vk::not_copyable {
2929
mixed runtime_config;
3030
string cluster_name{DEFAULT_CLUSTER_NAME.data(), DEFAULT_CLUSTER_NAME.size()};
3131
bool exit_after_response{};
32+
uint64_t initial_instance_memory_size{INIT_INSTANCE_ALLOCATOR_SIZE};
33+
uint64_t min_instance_extra_memory_size{DEFAULT_MIN_EXTRA_MEMORY_POOL_SIZE};
3234

3335
ComponentState() noexcept {
3436
parse_env();
@@ -59,7 +61,10 @@ struct ComponentState final : private vk::not_copyable {
5961
static constexpr std::string_view CLUSTER_NAME_ARG = "cluster-name";
6062
static constexpr std::string_view DEFAULT_CLUSTER_NAME = "default";
6163
static constexpr std::string_view EXIT_AFTER_RESPONSE_ARG = "exit-after-response";
62-
static constexpr auto INIT_COMPONENT_ALLOCATOR_SIZE = static_cast<size_t>(1024U * 1024U); // 1MB
64+
static constexpr std::string_view INITIAL_INSTANCE_MEMORY_SIZE_ARG = "initial-instance-memory-size";
65+
static constexpr std::string_view MIN_INSTANCE_EXTRA_MEMORY_SIZE_ARG = "min-instance-extra-memory-size";
66+
static constexpr auto INIT_COMPONENT_ALLOCATOR_SIZE = static_cast<size_t>(1024U * 1024U); // 1MiB
67+
static constexpr auto INIT_INSTANCE_ALLOCATOR_SIZE = static_cast<size_t>(64U * 1024U * 1024U); // 64MiB
6368

6469
void parse_env() noexcept;
6570

@@ -74,4 +79,8 @@ struct ComponentState final : private vk::not_copyable {
7479
void parse_cluster_name_arg(std::string_view) noexcept;
7580

7681
void parse_exit_after_response_arg(std::string_view) noexcept;
82+
83+
void parse_initial_instance_memory_size_arg(std::string_view) noexcept;
84+
85+
void parse_min_instance_extra_memory_size_arg(std::string_view) noexcept;
7786
};

runtime-light/state/image-state.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#include "runtime-light/stdlib/visitors/shape-visitors.h"
3030

3131
struct ImageState final : private vk::not_copyable {
32-
AllocatorState image_allocator_state{INIT_IMAGE_ALLOCATOR_SIZE, 0};
32+
AllocatorState image_allocator_state{INIT_IMAGE_ALLOCATOR_SIZE, DEFAULT_MIN_EXTRA_MEMORY_POOL_SIZE, 0};
3333

3434
uint32_t pid{k2::getpid()};
3535
uid_t uid{k2::getuid()};
@@ -100,5 +100,5 @@ struct ImageState final : private vk::not_copyable {
100100
}
101101

102102
private:
103-
static constexpr auto INIT_IMAGE_ALLOCATOR_SIZE = static_cast<size_t>(1024U * 1024U); // 1MB
103+
static constexpr auto INIT_IMAGE_ALLOCATOR_SIZE = static_cast<size_t>(1024U * 1024U); // 1MiB
104104
};

runtime-light/state/instance-state.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ struct InstanceState final : vk::not_copyable {
8888
return instance_kind_;
8989
}
9090

91-
AllocatorState instance_allocator_state{INIT_INSTANCE_ALLOCATOR_SIZE, 0};
91+
AllocatorState instance_allocator_state{ComponentState::get().initial_instance_memory_size, ComponentState::get().min_instance_extra_memory_size, 0};
9292

9393
kphp::log::contextual_tags instance_tags;
9494
kphp::coro::io_scheduler io_scheduler;
@@ -135,6 +135,4 @@ struct InstanceState final : vk::not_copyable {
135135

136136
enum image_kind image_kind_ { image_kind::invalid };
137137
enum instance_kind instance_kind_ { instance_kind::invalid };
138-
139-
static constexpr auto INIT_INSTANCE_ALLOCATOR_SIZE = static_cast<size_t>(128U * 1024U * 1024U);
140138
};

0 commit comments

Comments
 (0)