From 920120bbcec9f91df3336f62970b3e010a4fa6c2 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Thu, 6 Mar 2025 16:18:32 +0100 Subject: reduced memory churn using fixed_xxx containers (#236) * Added EASTL to help with eliminating memory allocations * Applied EASTL to eliminate memory allocations, primarily by using `fixed_vector` et al to use stack allocations / inline struct allocations Reduces memory events in traces by close to a factor of 10 in test scenario (starting editor for project F) --- src/zenhttp/httpserver.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/zenhttp/httpserver.cpp') diff --git a/src/zenhttp/httpserver.cpp b/src/zenhttp/httpserver.cpp index 1fbe22628..27a09f339 100644 --- a/src/zenhttp/httpserver.cpp +++ b/src/zenhttp/httpserver.cpp @@ -31,6 +31,8 @@ #include #include +#include + namespace zen { using namespace std::literals; @@ -529,7 +531,7 @@ HttpServerRequest::WriteResponse(HttpResponseCode ResponseCode, HttpContentType { std::span Segments = Payload.GetSegments(); - std::vector Buffers; + eastl::fixed_vector Buffers; Buffers.reserve(Segments.size()); for (auto& Segment : Segments) @@ -537,7 +539,7 @@ HttpServerRequest::WriteResponse(HttpResponseCode ResponseCode, HttpContentType Buffers.push_back(Segment.AsIoBuffer()); } - WriteResponse(ResponseCode, ContentType, Buffers); + WriteResponse(ResponseCode, ContentType, std::span(begin(Buffers), end(Buffers))); } std::string -- cgit v1.2.3 From ea2918767afa3c00c8dfa7dd7d9960a80a460eb9 Mon Sep 17 00:00:00 2001 From: Dmytro Ivanov Date: Wed, 9 Apr 2025 15:35:37 +0200 Subject: Added config, versioning and logging for plugins --- src/zenhttp/httpserver.cpp | 177 ++++++++++++++++++++++----------------------- 1 file changed, 86 insertions(+), 91 deletions(-) (limited to 'src/zenhttp/httpserver.cpp') diff --git a/src/zenhttp/httpserver.cpp b/src/zenhttp/httpserver.cpp index 27a09f339..d12f89a92 100644 --- a/src/zenhttp/httpserver.cpp +++ b/src/zenhttp/httpserver.cpp @@ -787,120 +787,115 @@ HttpRpcHandler::AddRpc(std::string_view RpcId, std::function -CreateHttpServerClass(HttpServerClass Class, const HttpServerConfig& Config) +CreateHttpServerClass(const std::string_view ServerClass, const HttpServerConfig& Config) { - switch (Class) + if (ServerClass == "asio"sv) { - default: - case HttpServerClass::kHttpAsio: - ZEN_INFO("using asio HTTP server implementation"); - return CreateHttpAsioServer(Config.ForceLoopback, Config.ThreadCount); - - case HttpServerClass::kHttpMulti: - { - ZEN_INFO("using multi HTTP server implementation"); - Ref Server{new HttpMultiServer()}; - - // This is hardcoded for now, but should be configurable in the future - Server->AddServer(CreateHttpServerClass(HttpServerClass::kHttpSys, Config)); - Server->AddServer(CreateHttpServerClass(HttpServerClass::kHttpPlugin, Config)); + ZEN_INFO("using asio HTTP server implementation") + return CreateHttpAsioServer(Config.ForceLoopback, Config.ThreadCount); + } +#if ZEN_WITH_HTTPSYS + else if (ServerClass == "httpsys"sv) + { + ZEN_INFO("using http.sys server implementation") + return Ref(CreateHttpSysServer({.ThreadCount = Config.ThreadCount, + .AsyncWorkThreadCount = Config.HttpSys.AsyncWorkThreadCount, + .IsAsyncResponseEnabled = Config.HttpSys.IsAsyncResponseEnabled, + .IsRequestLoggingEnabled = Config.HttpSys.IsRequestLoggingEnabled, + .IsDedicatedServer = Config.IsDedicatedServer, + .ForceLoopback = Config.ForceLoopback})); + } +#endif + else if (ServerClass == "null"sv) + { + ZEN_INFO("using null HTTP server implementation") + return Ref(new HttpNullServer); + } + else + { + ZEN_WARN("unknown HTTP server implementation '{}', falling back to default", ServerClass) - return Server; - } +#if ZEN_WITH_HTTPSYS + return CreateHttpServerClass("httpsys"sv, Config); +#else + return CreateHttpServerClass("asio"sv, Config); +#endif + } +} #if ZEN_WITH_PLUGINS - case HttpServerClass::kHttpPlugin: - { - ZEN_INFO("using plugin HTTP server implementation"); - Ref Server{CreateHttpPluginServer()}; - - // This is hardcoded for now, but should be configurable in the future +Ref +CreateHttpServerPlugin(const HttpServerPluginConfig& PluginConfig) +{ + const std::string& PluginName = PluginConfig.PluginName; -# if 0 - Ref WinsockPlugin{CreateSocketTransportPlugin()}; - WinsockPlugin->Configure("port", "8558"); - Server->AddPlugin(WinsockPlugin); -# endif + ZEN_INFO("using '{}' plugin HTTP server implementation", PluginName) + Ref Server{CreateHttpPluginServer()}; + if (PluginName.starts_with("builtin:"sv)) + { # if 0 - Ref AsioPlugin{CreateAsioTransportPlugin()}; - AsioPlugin->Configure("port", "8558"); - Server->AddPlugin(AsioPlugin); -# endif - -# if 1 - Ref DllPlugin{CreateDllTransportPlugin()}; - DllPlugin->LoadDll("winsock"); - DllPlugin->ConfigureDll("winsock", "port", "8558"); - Server->AddPlugin(DllPlugin); -# endif + Ref Plugin = {}; + if (PluginName == "builtin:winsock"sv) + { + Plugin = CreateSocketTransportPlugin(); + } + else if (PluginName == "builtin:asio"sv) + { + Plugin = CreateAsioTransportPlugin(); + } - return Server; + if (!Plugin.IsNull()) + { + for (const std::pair& Option : PluginConfig.PluginOptions) + { + Plugin->Configure(Option.first.c_str(), Option.second.c_str()); } -#endif - -#if ZEN_WITH_HTTPSYS - case HttpServerClass::kHttpSys: - ZEN_INFO("using http.sys server implementation"); - return Ref(CreateHttpSysServer({.ThreadCount = Config.ThreadCount, - .AsyncWorkThreadCount = Config.HttpSys.AsyncWorkThreadCount, - .IsAsyncResponseEnabled = Config.HttpSys.IsAsyncResponseEnabled, - .IsRequestLoggingEnabled = Config.HttpSys.IsRequestLoggingEnabled, - .IsDedicatedServer = Config.IsDedicatedServer, - .ForceLoopback = Config.ForceLoopback})); -#endif - - case HttpServerClass::kHttpNull: - ZEN_INFO("using null HTTP server implementation"); - return Ref(new HttpNullServer); + Server->AddPlugin(Plugin); + } +# endif } + else + { + Ref DllPlugin{CreateDllTransportPlugin()}; + DllPlugin->LoadDll(PluginName); + for (const std::pair& Option : PluginConfig.PluginOptions) + { + DllPlugin->ConfigureDll(PluginName, Option.first.c_str(), Option.second.c_str()); + } + Server->AddPlugin(DllPlugin); + } + + return Server; } +#endif Ref CreateHttpServer(const HttpServerConfig& Config) { using namespace std::literals; - HttpServerClass Class = HttpServerClass::kHttpNull; - -#if ZEN_WITH_HTTPSYS - Class = HttpServerClass::kHttpSys; -#else - Class = HttpServerClass::kHttpAsio; -#endif - - if (Config.ServerClass == "asio"sv) - { - Class = HttpServerClass::kHttpAsio; - } - else if (Config.ServerClass == "httpsys"sv) - { - Class = HttpServerClass::kHttpSys; - } - else if (Config.ServerClass == "plugin"sv) - { - Class = HttpServerClass::kHttpPlugin; - } - else if (Config.ServerClass == "null"sv) +#if ZEN_WITH_PLUGINS + if (Config.PluginConfigs.empty()) { - Class = HttpServerClass::kHttpNull; + return CreateHttpServerClass(Config.ServerClass, Config); } - else if (Config.ServerClass == "multi"sv) + else { - Class = HttpServerClass::kHttpMulti; - } + Ref Server{new HttpMultiServer()}; + Server->AddServer(CreateHttpServerClass(Config.ServerClass, Config)); - return CreateHttpServerClass(Class, Config); + for (const HttpServerPluginConfig& PluginConfig : Config.PluginConfigs) + { + Server->AddServer(CreateHttpServerPlugin(PluginConfig)); + } + + return Server; + } +#else + return CreateHttpServerClass(Config.ServerClass, Config); +#endif } ////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 199553c86444dcd9c4cff91165938dbd9a5b4bbb Mon Sep 17 00:00:00 2001 From: Dmytro Ivanov Date: Wed, 23 Apr 2025 10:54:22 +0200 Subject: Make plugin loading errors non fatal (#364) make plugin loading errors non fatal --- src/zenhttp/httpserver.cpp | 48 ++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) (limited to 'src/zenhttp/httpserver.cpp') diff --git a/src/zenhttp/httpserver.cpp b/src/zenhttp/httpserver.cpp index d12f89a92..764f2a2a7 100644 --- a/src/zenhttp/httpserver.cpp +++ b/src/zenhttp/httpserver.cpp @@ -831,7 +831,6 @@ CreateHttpServerPlugin(const HttpServerPluginConfig& PluginConfig) const std::string& PluginName = PluginConfig.PluginName; ZEN_INFO("using '{}' plugin HTTP server implementation", PluginName) - Ref Server{CreateHttpPluginServer()}; if (PluginName.starts_with("builtin:"sv)) { @@ -845,28 +844,41 @@ CreateHttpServerPlugin(const HttpServerPluginConfig& PluginConfig) { Plugin = CreateAsioTransportPlugin(); } + else + { + ZEN_WARN("Unknown builtin plugin '{}'", PluginName) + return {}; + } + + ZEN_ASSERT(!Plugin.IsNull()); - if (!Plugin.IsNull()) + for (const std::pair& Option : PluginConfig.PluginOptions) { - for (const std::pair& Option : PluginConfig.PluginOptions) - { - Plugin->Configure(Option.first.c_str(), Option.second.c_str()); - } - Server->AddPlugin(Plugin); + Plugin->Configure(Option.first.c_str(), Option.second.c_str()); } + + Ref Server{CreateHttpPluginServer()}; + Server->AddPlugin(Plugin); + return Server; +# else + ZEN_WARN("Builtin plugin '{}' is not supported", PluginName) + return {}; # endif } - else + + Ref DllPlugin{CreateDllTransportPlugin()}; + if (!DllPlugin->LoadDll(PluginName)) { - Ref DllPlugin{CreateDllTransportPlugin()}; - DllPlugin->LoadDll(PluginName); - for (const std::pair& Option : PluginConfig.PluginOptions) - { - DllPlugin->ConfigureDll(PluginName, Option.first.c_str(), Option.second.c_str()); - } - Server->AddPlugin(DllPlugin); + return {}; + } + + for (const std::pair& Option : PluginConfig.PluginOptions) + { + DllPlugin->ConfigureDll(PluginName, Option.first.c_str(), Option.second.c_str()); } + Ref Server{CreateHttpPluginServer()}; + Server->AddPlugin(DllPlugin); return Server; } #endif @@ -888,7 +900,11 @@ CreateHttpServer(const HttpServerConfig& Config) for (const HttpServerPluginConfig& PluginConfig : Config.PluginConfigs) { - Server->AddServer(CreateHttpServerPlugin(PluginConfig)); + Ref PluginServer = CreateHttpServerPlugin(PluginConfig); + if (!PluginServer.IsNull()) + { + Server->AddServer(PluginServer); + } } return Server; -- cgit v1.2.3