Skip to content

Commit

Permalink
Update K2 component modes (#1087)
Browse files Browse the repository at this point in the history
Previously we had two component modes: oneshot, multshot. This commit introduces following modes:
* k2-cli: most simple mode. Semantically equivalent to regular PHP script
* k2-server: semantically equivalent to current KPHP-server
* k2-oneshot: K2 oneshot component
* k2-multishot: K2 multishot component
  • Loading branch information
apolyakov authored Sep 5, 2024
1 parent 24fcf35 commit 6091ab7
Show file tree
Hide file tree
Showing 16 changed files with 189 additions and 130 deletions.
53 changes: 23 additions & 30 deletions compiler/code-gen/files/init-scripts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ void StaticInit::compile(CodeGenerator &W) const {
W << "extern array<tl_storer_ptr> gen$tl_storers_ht;" << NL;
FunctionSignatureGenerator(W) << "void fill_tl_storers_ht()" << SemicolonAndNL() << NL;
}
if (!G->is_output_mode_k2_component()) {
if (!G->is_output_mode_k2()) {
FunctionSignatureGenerator(W) << ("const char *get_php_scripts_version()") << BEGIN << "return " << RawString(G->settings().php_code_version.get()) << ";"
<< NL << END << NL << NL;
}

if (!G->is_output_mode_k2_component()) {
if (!G->is_output_mode_k2()) {
FunctionSignatureGenerator(W) << ("char **get_runtime_options([[maybe_unused]] int *count)") << BEGIN;

const auto &runtime_opts = G->get_kphp_runtime_opts();
Expand Down Expand Up @@ -113,19 +113,16 @@ struct RunInterruptedFunction {

void compile(CodeGenerator &W) const {
std::string await_prefix = function->is_interruptible ? "co_await " : "";
/**
* Oneshot components work the same way as php scripts:
* 1) Start when the request came in
* 2) Collecting output buffer after script finished
**/
std::string script_start = G->settings().k2_component_is_oneshot.get() ? "co_await accept_initial_stream();" : "";
std::string script_finish = G->settings().k2_component_is_oneshot.get() ? "co_await shutdown_script();" : "";
FunctionSignatureGenerator(W) << "task_t<void> " << FunctionName(function) << "$run() " << BEGIN
<< script_start << NL
<< await_prefix << FunctionName(function) << "();" << NL
<< script_finish << NL
<< "co_return;"
<< END;
std::string component_kind = G->is_output_mode_k2_cli() ? "ComponentKind::CLI"
: G->is_output_mode_k2_server() ? "ComponentKind::Server"
: G->is_output_mode_k2_oneshot() ? "ComponentKind::Oneshot"
: G->is_output_mode_k2_multishot() ? "ComponentKind::Multishot"
: "ComponentKind::Invalid";

std::string script_start = "co_await get_component_context()->run_component_prologue<" + component_kind + ">();";
std::string script_finish = "co_await get_component_context()->run_component_epilogue();";
FunctionSignatureGenerator(W) << "task_t<void> " << FunctionName(function) << "$run() " << BEGIN << script_start << NL << await_prefix
<< FunctionName(function) << "();" << NL << script_finish << NL << "co_return;" << END;
W << NL;
}
};
Expand Down Expand Up @@ -207,7 +204,7 @@ void InitScriptsCpp::compile(CodeGenerator &W) const {
W << OpenFile("init_php_scripts.cpp", "", false);

W << ExternInclude(G->settings().runtime_headers.get());
if (!G->is_output_mode_k2_component()) {
if (!G->is_output_mode_k2()) {
W << ExternInclude("server/php-init-scripts.h");
}

Expand All @@ -227,14 +224,14 @@ void InitScriptsCpp::compile(CodeGenerator &W) const {
return;
}

if (G->is_output_mode_k2_component()) {
if (G->is_output_mode_k2()) {
W << RunInterruptedFunction(main_file_id->main_function) << NL;
} else {
W << RunFunction(main_file_id->main_function) << NL;
}
W << GlobalsResetFunction(main_file_id->main_function) << NL;

if (G->is_output_mode_k2_component()) {
if (G->is_output_mode_k2()) {
FunctionSignatureGenerator(W) << "void init_php_scripts_in_each_worker(" << PhpMutableGlobalsRefArgument() << ", task_t<void> &run" ")" << BEGIN;
} else {
FunctionSignatureGenerator(W) << "void init_php_scripts_in_each_worker(" << PhpMutableGlobalsRefArgument() << ")" << BEGIN;
Expand All @@ -249,7 +246,7 @@ void InitScriptsCpp::compile(CodeGenerator &W) const {

W << FunctionName(main_file_id->main_function) << "$globals_reset(php_globals);" << NL;

if (G->is_output_mode_k2_component()) {
if (G->is_output_mode_k2()) {
W << "run = " << FunctionName(main_file_id->main_function) << "$run();" << NL;
} else {
W << "set_script ("
Expand Down Expand Up @@ -283,20 +280,16 @@ void CppMainFile::compile(CodeGenerator &W) const {
}

void ComponentInfoFile::compile(CodeGenerator &W) const {
kphp_assert(G->is_output_mode_k2_component());
kphp_assert(G->is_output_mode_k2());
G->settings().get_version();
auto now = std::chrono::system_clock::now();
W << OpenFile("image_info.cpp");
W << ExternInclude(G->settings().runtime_headers.get());
W << "const ImageInfo *vk_k2_describe() " << BEGIN
<< "static ImageInfo imageInfo {\"" << G->settings().k2_component_name.get() << "\"" << ","
<< std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count() << ","
<< "K2_PLATFORM_HEADER_H_VERSION, "
<< "{}," //todo:k2 add commit hash
<< "{}," //todo:k2 add compiler hash?
<< (G->settings().k2_component_is_oneshot.get() ? "1" : "0")
<< "};" << NL
<< "return &imageInfo;" << NL
<< END;
W << "const ImageInfo *vk_k2_describe() " << BEGIN << "static ImageInfo imageInfo {\"" << G->settings().k2_component_name.get() << "\"" << ","
<< std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count() << ","
<< "K2_PLATFORM_HEADER_H_VERSION, "
<< "{}," // todo:k2 add commit hash
<< "{}," // todo:k2 add compiler hash?
<< (G->is_output_mode_k2_multishot() ? "0" : "1") << "};" << NL << "return &imageInfo;" << NL << END;
W << CloseFile();
}
2 changes: 1 addition & 1 deletion compiler/code-gen/files/tl2cpp/tl-combinator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ void CombinatorStore::gen_arg_processing(CodeGenerator &W, const std::unique_ptr
auto *as_type_var = arg->type_expr->as<vk::tlo_parsing::type_var>();
kphp_assert(as_type_var);
if (!typed_mode) {
const auto *k2_tl_storers_prefix = G->is_output_mode_k2_component() ? "RpcImageState::get()." : "";
const auto *k2_tl_storers_prefix = G->is_output_mode_k2() ? "RpcImageState::get()." : "";
W << "auto _cur_arg = "
<< fmt_format("tl_arr_get(tl_object, {}, {}, {}L)", tl2cpp::register_tl_const_str(arg->name), arg->idx, tl2cpp::hash_tl_const_str(arg->name))
<< ";" << NL;
Expand Down
17 changes: 12 additions & 5 deletions compiler/compiler-core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,22 @@ void CompilerCore::finish() {
}

void CompilerCore::register_settings(CompilerSettings *settings) {
kphp_assert (settings_ == nullptr);
kphp_assert(settings_ == nullptr);
settings_ = settings;
const auto mode = settings->mode.get();

if (settings->mode.get() == "cli") {
if (mode == "cli") {
output_mode = OutputMode::cli;
} else if (settings->mode.get() == "lib") {
} else if (mode == "lib") {
output_mode = OutputMode::lib;
} else if (settings->mode.get() == "k2-component") {
output_mode = OutputMode::k2_component;
} else if (mode == "k2-cli") {
output_mode = OutputMode::k2_cli;
} else if (mode == "k2-server") {
output_mode = OutputMode::k2_server;
} else if (mode == "k2-oneshot") {
output_mode = OutputMode::k2_oneshot;
} else if (mode == "k2-multishot") {
output_mode = OutputMode::k2_multishot;
} else {
output_mode = OutputMode::server;
}
Expand Down
31 changes: 25 additions & 6 deletions compiler/compiler-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@
#include "compiler/tl-classes.h"

enum class OutputMode {
server, // -M server
cli, // -M cli
lib, // -M lib
k2_component // -M k2-component
server, // -M server
cli, // -M cli
lib, // -M lib
k2_cli, // -M k2-cli
k2_server, // -M k2-server
k2_oneshot, // -M k2-oneshot
k2_multishot, // -M k2-multishot
};

class CompilerCore {
Expand Down Expand Up @@ -189,8 +192,24 @@ class CompilerCore {
return output_mode == OutputMode::lib;
}

bool is_output_mode_k2_component() const {
return output_mode == OutputMode::k2_component;
bool is_output_mode_k2_cli() const {
return output_mode == OutputMode::k2_cli;
}

bool is_output_mode_k2_server() const {
return output_mode == OutputMode::k2_server;
}

bool is_output_mode_k2_oneshot() const {
return output_mode == OutputMode::k2_oneshot;
}

bool is_output_mode_k2_multishot() const {
return output_mode == OutputMode::k2_multishot;
}

bool is_output_mode_k2() const {
return is_output_mode_k2_cli() || is_output_mode_k2_server() || is_output_mode_k2_oneshot() || is_output_mode_k2_multishot();
}

Stats stats;
Expand Down
16 changes: 9 additions & 7 deletions compiler/compiler-settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,25 +216,27 @@ void CompilerSettings::init() {
option_as_dir(kphp_src_path);
functions_file.value_ = get_full_path(functions_file.get());
runtime_sha256_file.value_ = get_full_path(runtime_sha256_file.get());

bool is_k2_mode = mode.get().substr(0, 3) == "k2-";
if (link_file.value_.empty()) {
if (mode.get() == "k2-component") {
if (is_k2_mode) {
link_file.value_ = kphp_src_path.get() + "/objs/libkphp-light-runtime.a";
} else {
link_file.value_ = kphp_src_path.get() + "/objs/libkphp-full-runtime.a";
}
}
link_file.value_ = get_full_path(link_file.get());
if (functions_file.value_.empty()) {
if (mode.get() == "k2-component") {
if (is_k2_mode) {
functions_file.value_ = kphp_src_path.get() + "/builtin-functions/kphp-light/functions.txt";
} else {
functions_file.value_ = kphp_src_path.get() + "/builtin-functions/kphp-full/_functions.txt";
}
}
functions_file.value_ = get_full_path(functions_file.get());

if (k2_component_name.get() != "KPHP" || k2_component_is_oneshot.get()) {
kphp_error(mode.get() == "k2-component", "Options \"k2-component-name\" and \"oneshot\" available only fore k2-component mode");
if (k2_component_name.get() != "KPHP") {
kphp_error(is_k2_mode, "Option \"k2-component-name\" is only available for k2 component modes");
}

if (mode.get() == "lib") {
Expand Down Expand Up @@ -302,7 +304,7 @@ void CompilerSettings::init() {
if (!no_pch.get()) {
ss << " -Winvalid-pch -fpch-preprocess";
}
if (mode.get() == "k2-component" || dynamic_incremental_linkage.get()) {
if (is_k2_mode || dynamic_incremental_linkage.get()) {
ss << " -fPIC";
}
if (vk::contains(cxx.get(), "clang")) {
Expand All @@ -316,7 +318,7 @@ void CompilerSettings::init() {
#error unsupported __cplusplus value
#endif

if (mode.get() == "k2-component") {
if (is_k2_mode) {
// for now k2-component must be compiled with clang and statically linked libc++
ss << " -stdlib=libc++";
} else {
Expand Down Expand Up @@ -413,7 +415,7 @@ void CompilerSettings::init() {
option_as_dir(dest_dir);
dest_cpp_dir.value_ = dest_dir.get() + "kphp/";
dest_objs_dir.value_ = dest_dir.get() + "objs/";
if (mode.get() == "k2-component") {
if (is_k2_mode) {
binary_path.value_ = dest_dir.get() + k2_component_name.get() + ".so";
} else {
binary_path.value_ = dest_dir.get() + mode.get();
Expand Down
3 changes: 1 addition & 2 deletions compiler/compiler-settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,8 @@ class CompilerSettings : vk::not_copyable {
KphpOption<std::string> compilation_metrics_file;
KphpOption<std::string> override_kphp_version;
KphpOption<std::string> php_code_version;
KphpOption<std::string> k2_component_name;

KphpOption<bool> k2_component_is_oneshot;
KphpOption<std::string> k2_component_name;

KphpOption<std::string> cxx;
KphpOption<std::string> cxx_toolchain_dir;
Expand Down
6 changes: 2 additions & 4 deletions compiler/kphp2cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,8 @@ int main(int argc, char *argv[]) {
'f', "functions-file", "KPHP_FUNCTIONS");
parser.add("File with kphp runtime sha256 hash", settings->runtime_sha256_file,
"runtime-sha256", "KPHP_RUNTIME_SHA256", "${KPHP_PATH}/objs/php_lib_version.sha256");
parser.add("The output binary type: server, k2-component, cli or lib", settings->mode,
'M', "mode", "KPHP_MODE", "server", {"server", "k2-component", "cli", "lib"});
parser.add("The output binary type: server, cli, lib, k2-cli, k2-server, k2-oneshot, k2-multishot", settings->mode, 'M', "mode", "KPHP_MODE", "server",
{"server", "cli", "lib", "k2-cli", "k2-server", "k2-oneshot", "k2-multishot"});
parser.add("A runtime library for building the output binary", settings->link_file,
'l', "link-with", "KPHP_LINK_FILE");
parser.add("Build runtime from sources", settings->force_link_runtime,
Expand Down Expand Up @@ -298,8 +298,6 @@ int main(int argc, char *argv[]) {
"require-class-typing", "KPHP_REQUIRE_CLASS_TYPING");
parser.add("Define k2 component name. Default is \"KPHP\"", settings->k2_component_name,
"k2-component-name", "KPHP_K2_COMPONENT_NAME", "KPHP");
parser.add("Enable oneshot mode to k2 component", settings->k2_component_is_oneshot,
"oneshot", "KPHP_K2_COMPONENT_IS_ONESHOT");

parser.add_implicit_option("Linker flags", settings->ld_flags);
parser.add_implicit_option("Incremental linker flags", settings->incremental_linker_flags);
Expand Down
4 changes: 2 additions & 2 deletions compiler/make/make.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -548,10 +548,10 @@ void run_make() {
auto objs = run_pre_make(output_mode, settings, make_stats_file, make, obj_index, bin_file, obj_rt_index);
stage::die_if_global_errors();

if (output_mode == OutputMode::lib) {
if (G->is_output_mode_lib()) {
// todo:k2 think about kphp libraries
make.create_objs2static_lib_target(objs, &bin_file);
} else if (output_mode == OutputMode::k2_component) {
} else if (G->is_output_mode_k2()) {
make.create_objs2k2_component_target(objs, &bin_file);
} else {
const std::string build_stage{"Compiling"};
Expand Down
2 changes: 1 addition & 1 deletion compiler/pipes/calc-bad-vars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ class CalcBadVars {

{
FuncCallGraph call_graph(std::move(functions), dep_datas);
if (G->is_output_mode_k2_component()) {
if (G->is_output_mode_k2()) {
calc_k2_fork(call_graph, dep_datas);
calc_interruptible(call_graph);
} else {
Expand Down
6 changes: 3 additions & 3 deletions compiler/pipes/code-gen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ void CodeGenF::on_finish(DataStream<std::unique_ptr<CodeGenRootCmd>> &os) {

// TODO: should be done in lib mode also, but in some other way
if (!G->is_output_mode_lib()) {
if (!G->is_output_mode_k2_component()) {
if (!G->is_output_mode_k2()) {
code_gen_start_root_task(os, std::make_unique<TypeTagger>(vk::singleton<ForkableTypeStorage>::get().flush_forkable_types(),
vk::singleton<ForkableTypeStorage>::get().flush_waitable_types()));
}
Expand All @@ -132,10 +132,10 @@ void CodeGenF::on_finish(DataStream<std::unique_ptr<CodeGenRootCmd>> &os) {

code_gen_start_root_task(os, std::make_unique<TlSchemaToCpp>());
code_gen_start_root_task(os, std::make_unique<LibVersionHFile>());
if (!G->is_output_mode_lib() && !G->is_output_mode_k2_component()) {
if (!G->is_output_mode_lib() && !G->is_output_mode_k2()) {
code_gen_start_root_task(os, std::make_unique<CppMainFile>());
}
if (G->is_output_mode_k2_component()) {
if (G->is_output_mode_k2()) {
code_gen_start_root_task(os, std::make_unique<ComponentInfoFile>());
}
}
Expand Down
Loading

0 comments on commit 6091ab7

Please sign in to comment.