Skip to content
1 change: 1 addition & 0 deletions runtime-common/core/allocator/pool-allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct pool_allocator : private vk::not_copyable {
size_t m_min_extra_mem_size{0};

auto request_extra_memory(size_t requested_size) noexcept -> void;
[[noreturn]] auto raise_out_of_memory(size_t requested_size) const noexcept -> void;

public:
pool_allocator(size_t script_mem_size, size_t min_extra_mem_size, size_t oom_handling_mem_size) noexcept;
Expand Down
26 changes: 22 additions & 4 deletions runtime-light/allocator/pool-allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ auto pool_allocator::alloc_script_memory(size_t size) noexcept -> void* {
request_extra_memory(size);
mem = memory_resource.allocate(size);

kphp::log::assertion(mem != nullptr);
if (mem == nullptr) [[unlikely]] {
raise_out_of_memory(size);
}
}

return mem;
Expand All @@ -64,7 +66,9 @@ auto pool_allocator::calloc_script_memory(size_t size) noexcept -> void* {
request_extra_memory(size);
mem = memory_resource.allocate0(size);

kphp::log::assertion(mem != nullptr);
if (mem == nullptr) [[unlikely]] {
raise_out_of_memory(size);
}
}

return mem;
Expand All @@ -78,7 +82,9 @@ auto pool_allocator::realloc_script_memory(void* old_mem, size_t new_size, size_
request_extra_memory(new_size * 2);
new_mem = memory_resource.reallocate(old_mem, new_size, old_size);

kphp::log::assertion(new_mem != nullptr);
if (new_mem == nullptr) [[unlikely]] {
raise_out_of_memory(new_size);
}
}

return new_mem;
Expand All @@ -104,8 +110,20 @@ auto pool_allocator::request_extra_memory(size_t requested_size) noexcept -> voi
extra_mem_size = std::bit_ceil(extra_mem_size);

auto* extra_mem{kphp::memory::platform::alloc(extra_mem_size)};
kphp::log::assertion(extra_mem != nullptr);
Comment thread
apolyakov marked this conversation as resolved.
if (extra_mem == nullptr) [[unlikely]] {
raise_out_of_memory(extra_mem_size);
}
Comment thread
denisichh marked this conversation as resolved.
memory_resource.add_extra_memory(new (extra_mem) memory_resource::extra_memory_pool{extra_mem_size});
}

auto pool_allocator::raise_out_of_memory(size_t requested_size) const noexcept -> void {
const auto& stats{memory_resource.get_memory_stats()};
kphp::log::error("pool_allocator: out of memory (requested {} bytes), "
"memory usage: {} of {} bytes (max {}), real usage: {} bytes (max {}), "
"total allocations: {}, total memory allocated: {} bytes, "
"defragmentation calls: {}, huge memory pieces: {}, small memory pieces: {}",
requested_size, stats.memory_used, stats.memory_limit, stats.max_memory_used, stats.real_memory_used, stats.max_real_memory_used,
stats.total_allocations, stats.total_memory_allocated, stats.defragmentation_calls, stats.huge_memory_pieces, stats.small_memory_pieces);
}

} // namespace kphp::memory
32 changes: 20 additions & 12 deletions runtime-light/stdlib/diagnostics/logs.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <optional>
#include <source_location>
#include <span>
#include <string_view>

#include "runtime-light/k2-platform/k2-api.h"
#include "runtime-light/stdlib/diagnostics/backtrace.h"
Expand Down Expand Up @@ -37,29 +38,36 @@ void log(level level, std::optional<std::span<void* const>> trace, std::format_s
return std::nullopt;
})};

const size_t tagged_entries_size{
static_cast<size_t>((trace.has_value() ? 1 : 0) + opt_tags.transform([](contextual_tags& tags) noexcept { return tags.size(); }).value_or(0))};
kphp::stl::vector<k2::LogTaggedEntry, kphp::memory::script_allocator> tagged_entries{};
tagged_entries.reserve(tagged_entries_size);
size_t tagged_entries_size{};
static constexpr size_t TAGGED_ENTRIES_BUFFER_SIZE{24UZ};
std::array<k2::LogTaggedEntry, TAGGED_ENTRIES_BUFFER_SIZE> tagged_entries_buffer; // NOLINT

opt_tags.transform([&tagged_entries](contextual_tags& tags) noexcept {
// Reserve one slot for the trace when it's present
const size_t tagged_entries_capacity{trace.has_value() ? TAGGED_ENTRIES_BUFFER_SIZE - 1 : TAGGED_ENTRIES_BUFFER_SIZE};

opt_tags.transform([&tagged_entries_buffer, &tagged_entries_size, tagged_entries_capacity](contextual_tags& tags) noexcept {
for (const auto& [key, value] : tags.values()) {
tagged_entries.push_back(k2::LogTaggedEntry{.key = key.data(), .value = value.data(), .key_len = key.size(), .value_len = value.size()});
if (tagged_entries_size == tagged_entries_capacity) {
break;
}

tagged_entries_buffer[tagged_entries_size++] =
k2::LogTaggedEntry{.key = key.data(), .value = value.data(), .key_len = key.size(), .value_len = value.size()};
}
return 0;
});
if (trace.has_value()) {
static constexpr std::string_view BACKTRACE_KEY = "trace";
static constexpr size_t BACKTRACE_BUFFER_SIZE = 1024UZ * 4UZ;
static constexpr std::string_view BACKTRACE_KEY{"trace"};
static constexpr size_t BACKTRACE_BUFFER_SIZE{1024UZ * 4UZ};
std::array<char, BACKTRACE_BUFFER_SIZE> backtrace_buffer; // NOLINT
size_t backtrace_size{impl::resolve_log_trace(backtrace_buffer, *trace)};
tagged_entries.push_back(
k2::LogTaggedEntry{.key = BACKTRACE_KEY.data(), .value = backtrace_buffer.data(), .key_len = BACKTRACE_KEY.size(), .value_len = backtrace_size});
k2::log(std::to_underlying(level), message, tagged_entries);
tagged_entries_buffer[tagged_entries_size++] =
k2::LogTaggedEntry{.key = BACKTRACE_KEY.data(), .value = backtrace_buffer.data(), .key_len = BACKTRACE_KEY.size(), .value_len = backtrace_size};
k2::log(std::to_underlying(level), message, {tagged_entries_buffer.data(), tagged_entries_size});
return;
}

k2::log(std::to_underlying(level), message, tagged_entries);
k2::log(std::to_underlying(level), message, {tagged_entries_buffer.data(), tagged_entries_size});
}

} // namespace impl
Expand Down
Loading