Skip to content

Commit

Permalink
[k2] implement STD-like script allocator (#1199)
Browse files Browse the repository at this point in the history
  • Loading branch information
apolyakov authored Jan 9, 2025
1 parent 11f593f commit b3dc973
Show file tree
Hide file tree
Showing 16 changed files with 145 additions and 96 deletions.
2 changes: 0 additions & 2 deletions runtime-common/stdlib/math/math-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

#pragma once

#include <string_view>

#include "common/mixin/not_copyable.h"
#include "runtime-common/core/runtime-core.h"

Expand Down
23 changes: 23 additions & 0 deletions runtime-light/allocator/allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,33 @@
#pragma once

#include <concepts>
#include <cstddef>

#include "runtime-common/core/allocator/runtime-allocator.h"
#include "runtime-common/core/allocator/script-allocator-managed.h"

template<std::derived_from<ScriptAllocatorManaged> T, typename... Args>
requires std::constructible_from<T, Args...> auto make_unique_on_script_memory(Args &&...args) noexcept {
return std::make_unique<T>(std::forward<Args>(args)...);
}

namespace kphp {

namespace memory {

template<typename T>
struct script_allocator {
using value_type = T;

constexpr value_type *allocate(size_t n) noexcept {
return static_cast<value_type *>(RuntimeAllocator::get().alloc_script_memory(n * sizeof(T)));
}

constexpr void deallocate(T *p, size_t n) noexcept {
RuntimeAllocator::get().free_script_memory(p, n);
}
};

} // namespace memory

} // namespace kphp
10 changes: 5 additions & 5 deletions runtime-light/core/globals/php-script-globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

#include <string_view>

#include "runtime-common/core/memory-resource/resource_allocator.h"
#include "runtime-common/core/memory-resource/unsynchronized_pool_resource.h"
#include "runtime-common/core/runtime-core.h"
#include "runtime-light/allocator/allocator.h"
#include "runtime-light/core/std/containers.h"

namespace PhpServerSuperGlobalIndices {

Expand Down Expand Up @@ -68,14 +68,14 @@ struct PhpScriptBuiltInSuperGlobals {

class PhpScriptMutableGlobals {
template<typename Key, typename Value>
using unordered_map = memory_resource::stl::unordered_map<Key, Value, memory_resource::unsynchronized_pool_resource>;
using unordered_map = kphp::stl::unordered_map<Key, Value, kphp::memory::script_allocator>;

char *g_linear_mem{nullptr};
unordered_map<int64_t, char *> libs_linear_mem;
PhpScriptBuiltInSuperGlobals superglobals;

public:
explicit PhpScriptMutableGlobals(memory_resource::unsynchronized_pool_resource &resource)
: libs_linear_mem(unordered_map<int64_t, char *>::allocator_type{resource}) {}
PhpScriptMutableGlobals() noexcept = default;

static PhpScriptMutableGlobals &current() noexcept;

Expand Down
51 changes: 51 additions & 0 deletions runtime-light/core/std/containers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Compiler for PHP (aka KPHP)
// Copyright (c) 2024 LLC «V Kontakte»
// Distributed under the GPL v3 License, see LICENSE.notice.txt

#pragma once

#include <deque>
#include <functional>
#include <list>
#include <map>
#include <queue>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

namespace kphp {

namespace stl {

template<class Key, class T, template<class> class Allocator, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>>
using unordered_map = std::unordered_map<Key, T, Hash, KeyEqual, Allocator<std::pair<const Key, T>>>;

template<class T, template<class> class Allocator, class Hash = std::hash<T>, class KeyEqual = std::equal_to<T>>
using unordered_set = std::unordered_set<T, Hash, KeyEqual, Allocator<T>>;

template<class Key, class Value, template<class> class Allocator, class Cmp = std::less<Key>>
using map = std::map<Key, Value, Cmp, Allocator<std::pair<const Key, Value>>>;

template<class Key, class Value, template<class> class Allocator, class Cmp = std::less<Key>>
using multimap = std::multimap<Key, Value, Cmp, Allocator<std::pair<const Key, Value>>>;

template<class T, template<class> class Allocator>
using deque = std::deque<T, Allocator<T>>;

template<class T, template<class> class Allocator>
using queue = std::queue<T, std::deque<T, Allocator<T>>>;

template<class T, template<class> class Allocator>
using list = std::list<T, Allocator<T>>;

template<class T, template<class> class Allocator>
using vector = std::vector<T, Allocator<T>>;

template<template<class> class Allocator>
using string = std::basic_string<char, std::char_traits<char>, Allocator<char>>;

} // namespace stl

} // namespace kphp
20 changes: 8 additions & 12 deletions runtime-light/scheduler/scheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
#include <utility>
#include <variant>

#include "runtime-common/core/memory-resource/resource_allocator.h"
#include "runtime-common/core/memory-resource/unsynchronized_pool_resource.h"
#include "runtime-common/core/utils/hash.h"
#include "runtime-light/allocator/allocator.h"
#include "runtime-light/core/std/containers.h"
#include "runtime-light/utils/concepts.h"

/**
Expand Down Expand Up @@ -149,8 +149,8 @@ struct std::hash<SuspendToken> {
* 7. have `cancel` method that cancels specified SuspendToken.
*/
template<class scheduler_t>
concept CoroutineSchedulerConcept = std::constructible_from<scheduler_t, memory_resource::unsynchronized_pool_resource &>
&& requires(scheduler_t && s, ScheduleEvent::EventT schedule_event, SuspendToken token) {
concept CoroutineSchedulerConcept =
std::default_initializable<scheduler_t> && requires(scheduler_t && s, ScheduleEvent::EventT schedule_event, SuspendToken token) {
{ scheduler_t::get() } noexcept -> std::same_as<scheduler_t &>;
{ s.done() } noexcept -> std::convertible_to<bool>;
{ s.schedule(schedule_event) } noexcept -> std::same_as<ScheduleStatus>;
Expand All @@ -165,13 +165,13 @@ concept CoroutineSchedulerConcept = std::constructible_from<scheduler_t, memory_
// We need to finalize our decision whether we allow to do it from PHP code or not.
class SimpleCoroutineScheduler {
template<hashable Key, typename Value>
using unordered_map = memory_resource::stl::unordered_map<Key, Value, memory_resource::unsynchronized_pool_resource>;
using unordered_map = kphp::stl::unordered_map<Key, Value, kphp::memory::script_allocator>;

template<hashable T>
using unordered_set = memory_resource::stl::unordered_set<T, memory_resource::unsynchronized_pool_resource>;
using unordered_set = kphp::stl::unordered_set<T, kphp::memory::script_allocator>;

template<typename T>
using deque = memory_resource::stl::deque<T, memory_resource::unsynchronized_pool_resource>;
using deque = kphp::stl::deque<T, kphp::memory::script_allocator>;

deque<SuspendToken> yield_tokens;
deque<SuspendToken> awaiting_for_stream_tokens;
Expand All @@ -184,11 +184,7 @@ class SimpleCoroutineScheduler {
ScheduleStatus scheduleOnYield() noexcept;

public:
explicit SimpleCoroutineScheduler(memory_resource::unsynchronized_pool_resource &memory_resource) noexcept
: yield_tokens(deque<SuspendToken>::allocator_type{memory_resource})
, awaiting_for_stream_tokens(deque<SuspendToken>::allocator_type{memory_resource})
, awaiting_for_update_tokens(unordered_map<uint64_t, SuspendToken>::allocator_type{memory_resource})
, suspend_tokens(unordered_set<SuspendToken>::allocator_type{memory_resource}) {}
SimpleCoroutineScheduler() noexcept = default;

static SimpleCoroutineScheduler &get() noexcept;

Expand Down
17 changes: 7 additions & 10 deletions runtime-light/server/http/http-server-state.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
#include <string_view>

#include "common/mixin/not_copyable.h"
#include "runtime-common/core/memory-resource/resource_allocator.h"
#include "runtime-common/core/memory-resource/unsynchronized_pool_resource.h"
#include "runtime-common/core/runtime-core.h"
#include "runtime-light/allocator/allocator.h"
#include "runtime-light/core/std/containers.h"

enum class HttpMethod : uint8_t { GET, POST, HEAD, OTHER };

Expand Down Expand Up @@ -42,8 +42,8 @@ enum HttpStatus : uint16_t {
};

struct HttpServerInstanceState final : private vk::not_copyable {
using header_t = memory_resource::stl::string<memory_resource::unsynchronized_pool_resource>;
using headers_map_t = memory_resource::stl::multimap<header_t, header_t, memory_resource::unsynchronized_pool_resource>;
using header_t = kphp::stl::string<kphp::memory::script_allocator>;
using headers_map_t = kphp::stl::multimap<header_t, header_t, kphp::memory::script_allocator>;

static constexpr auto ENCODING_GZIP = static_cast<uint32_t>(1U << 0U);
static constexpr auto ENCODING_DEFLATE = static_cast<uint32_t>(1U << 1U);
Expand All @@ -56,25 +56,22 @@ struct HttpServerInstanceState final : private vk::not_copyable {
HttpConnectionKind connection_kind{HttpConnectionKind::CLOSE};

private:
memory_resource::unsynchronized_pool_resource &memory_resource_;
headers_map_t headers_;

public:
explicit HttpServerInstanceState(memory_resource::unsynchronized_pool_resource &memory_resource) noexcept
: memory_resource_(memory_resource)
, headers_(headers_map_t::allocator_type{memory_resource}) {}
HttpServerInstanceState() noexcept = default;

const headers_map_t &headers() const noexcept {
return headers_;
}

void add_header(std::string_view name_view, std::string_view value_view, bool replace) noexcept {
header_t name{name_view, header_t::allocator_type{memory_resource_}};
header_t name{name_view};
std::ranges::for_each(name, [](auto &c) noexcept { c = std::tolower(c); });
if (const auto it{headers_.find(name)}; replace && it != headers_.end()) [[unlikely]] {
headers_.erase(name);
}
headers_.emplace(std::move(name), header_t{value_view, header_t::allocator_type{memory_resource_}});
headers_.emplace(std::move(name), header_t{value_view});
}

static HttpServerInstanceState &get() noexcept;
Expand Down
4 changes: 2 additions & 2 deletions runtime-light/server/http/init-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,8 @@ task_t<void> finalize_http_server(const string_buffer &output) noexcept {
const bool deflate_encoded{static_cast<bool>(http_server_instance_st.encoding & HttpServerInstanceState::ENCODING_DEFLATE)};
// compress body if needed
if (gzip_encoded || deflate_encoded) {
auto encoded_body{zlib::encode({body.c_str(), static_cast<size_t>(body.size())}, zlib::DEFAULT_COMPRESSION_LEVEL,
gzip_encoded ? zlib::ENCODING_GZIP : zlib::ENCODING_DEFLATE)};
auto encoded_body{kphp::zlib::encode({body.c_str(), static_cast<size_t>(body.size())}, kphp::zlib::DEFAULT_COMPRESSION_LEVEL,
gzip_encoded ? kphp::zlib::ENCODING_GZIP : kphp::zlib::ENCODING_DEFLATE)};
if (encoded_body.has_value()) [[likely]] {
body = std::move(*encoded_body);

Expand Down
24 changes: 7 additions & 17 deletions runtime-light/state/instance-state.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
#include <utility>

#include "common/mixin/not_copyable.h"
#include "runtime-common/core/memory-resource/resource_allocator.h"
#include "runtime-common/core/memory-resource/unsynchronized_pool_resource.h"
#include "runtime-common/core/runtime-core.h"
#include "runtime-light/allocator/allocator.h"
#include "runtime-light/core/globals/php-script-globals.h"
#include "runtime-light/core/std/containers.h"
#include "runtime-light/coroutine/task.h"
#include "runtime-light/k2-platform/k2-api.h"
#include "runtime-light/scheduler/scheduler.h"
Expand All @@ -25,8 +25,8 @@
#include "runtime-light/stdlib/file/file-system-state.h"
#include "runtime-light/stdlib/fork/fork-state.h"
#include "runtime-light/stdlib/job-worker/job-worker-client-state.h"
#include "runtime-light/stdlib/math/random-state.h"
#include "runtime-light/stdlib/math/math-state.h"
#include "runtime-light/stdlib/math/random-state.h"
#include "runtime-light/stdlib/output/output-buffer.h"
#include "runtime-light/stdlib/rpc/rpc-state.h"
#include "runtime-light/stdlib/serialization/serialization-state.h"
Expand All @@ -49,26 +49,16 @@ enum class ImageKind : uint8_t { Invalid, CLI, Server, Oneshot, Multishot };

struct InstanceState final : vk::not_copyable {
template<typename T>
using unordered_set = memory_resource::stl::unordered_set<T, memory_resource::unsynchronized_pool_resource>;
using unordered_set = kphp::stl::unordered_set<T, kphp::memory::script_allocator>;

template<typename T>
using deque = memory_resource::stl::deque<T, memory_resource::unsynchronized_pool_resource>;
using deque = kphp::stl::deque<T, kphp::memory::script_allocator>;

template<typename T>
using list = memory_resource::stl::list<T, memory_resource::unsynchronized_pool_resource>;
using list = kphp::stl::list<T, kphp::memory::script_allocator>;

InstanceState() noexcept
: allocator(INIT_INSTANCE_ALLOCATOR_SIZE, 0)
, scheduler(allocator.memory_resource)
, fork_instance_state(allocator.memory_resource)
, php_script_mutable_globals_singleton(allocator.memory_resource)
, rpc_instance_state(allocator.memory_resource)
, http_server_instance_state(allocator.memory_resource)
, regex_instance_state(allocator.memory_resource)
, shutdown_functions(decltype(shutdown_functions)::allocator_type{allocator.memory_resource})
, incoming_streams_(decltype(incoming_streams_)::allocator_type{allocator.memory_resource})
, opened_streams_(decltype(opened_streams_)::allocator_type{allocator.memory_resource})
, pending_updates_(decltype(pending_updates_)::allocator_type{allocator.memory_resource}) {}
: allocator(INIT_INSTANCE_ALLOCATOR_SIZE, 0) {}

~InstanceState() = default;

Expand Down
8 changes: 4 additions & 4 deletions runtime-light/stdlib/fork/fork-state.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@
#include <utility>

#include "common/mixin/not_copyable.h"
#include "runtime-common/core/memory-resource/unsynchronized_pool_resource.h"
#include "runtime-common/core/utils/kphp-assert-core.h"
#include "runtime-light/allocator/allocator.h"
#include "runtime-light/core/std/containers.h"
#include "runtime-light/coroutine/task.h"
#include "runtime-light/utils/concepts.h"

inline constexpr int64_t INVALID_FORK_ID = -1;

class ForkInstanceState final : private vk::not_copyable {
template<hashable Key, typename Value>
using unordered_map = memory_resource::stl::unordered_map<Key, Value, memory_resource::unsynchronized_pool_resource>;
using unordered_map = kphp::stl::unordered_map<Key, Value, kphp::memory::script_allocator>;

static constexpr auto FORK_ID_INIT = 0;
// type erased tasks that represent forks
Expand Down Expand Up @@ -45,8 +46,7 @@ class ForkInstanceState final : private vk::not_copyable {
public:
int64_t running_fork_id{FORK_ID_INIT};

explicit ForkInstanceState(memory_resource::unsynchronized_pool_resource &memory_resource) noexcept
: forks(unordered_map<int64_t, task_t<void>>::allocator_type{memory_resource}) {}
ForkInstanceState() noexcept = default;

static ForkInstanceState &get() noexcept;

Expand Down
14 changes: 5 additions & 9 deletions runtime-light/stdlib/rpc/rpc-state.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,26 @@
#include <utility>

#include "common/mixin/not_copyable.h"
#include "runtime-common/core/memory-resource/resource_allocator.h"
#include "runtime-common/core/runtime-core.h"
#include "runtime-light/allocator/allocator.h"
#include "runtime-light/core/std/containers.h"
#include "runtime-light/stdlib/rpc/rpc-extra-info.h"
#include "runtime-light/stdlib/rpc/rpc-tl-defs.h"
#include "runtime-light/stdlib/rpc/rpc-tl-query.h"
#include "runtime-light/tl/tl-core.h"

struct RpcInstanceState final : private vk::not_copyable {
template<typename Key, typename Value>
using unordered_map = memory_resource::stl::unordered_map<Key, Value, memory_resource::unsynchronized_pool_resource>;
using unordered_map = kphp::stl::unordered_map<Key, Value, kphp::memory::script_allocator>;

tl::TLBuffer rpc_buffer;
int64_t current_query_id{0};
CurrentTlQuery current_query;
CurrentTlQuery current_query{};
unordered_map<int64_t, int64_t> response_waiter_forks;
unordered_map<int64_t, class_instance<RpcTlQuery>> response_fetcher_instances;
unordered_map<int64_t, std::pair<rpc_response_extra_info_status_t, rpc_response_extra_info_t>> rpc_responses_extra_info;

explicit RpcInstanceState(memory_resource::unsynchronized_pool_resource &memory_resource) noexcept
: current_query()
, response_waiter_forks(unordered_map<int64_t, int64_t>::allocator_type{memory_resource})
, response_fetcher_instances(unordered_map<int64_t, class_instance<RpcTlQuery>>::allocator_type{memory_resource})
, rpc_responses_extra_info(
unordered_map<int64_t, std::pair<rpc_response_extra_info_status_t, rpc_response_extra_info_t>>::allocator_type{memory_resource}) {}
RpcInstanceState() noexcept = default;

static RpcInstanceState &get() noexcept;
};
Expand Down
Loading

0 comments on commit b3dc973

Please sign in to comment.