diff --git a/.clang-format b/.clang-format index bde85d66..ac5f8762 100644 --- a/.clang-format +++ b/.clang-format @@ -15,5 +15,3 @@ DisableFormat: true Language: Json DisableFormat: true -Language: Proto -DisableFormat: true diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 75a60689..af65422c 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -8,6 +8,9 @@ set(CINATRA_EXAMPLE add_executable(${project_name} ${CINATRA_EXAMPLE}) target_compile_definitions(${project_name} PRIVATE ASYNC_SIMPLE_HAS_NOT_AIO) +add_executable(benchmark benchmark.cpp) +target_compile_definitions(benchmark PRIVATE ASYNC_SIMPLE_HAS_NOT_AIO) + if (ENABLE_SSL) target_link_libraries(${project_name} ${OPENSSL_LIBRARIES} pthread -ldl) endif() @@ -25,6 +28,7 @@ if (ENABLE_SIMD STREQUAL "AARCH64") add_library(neon INTERFACE IMPORTED) target_compile_options(neon INTERFACE -march=armv8-a+fp+simd) target_link_libraries(${project_name} neon) + target_link_libraries(benchmark neon) endif () elseif (ENABLE_SIMD STREQUAL "SSE42") if (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "x86_64") @@ -35,6 +39,7 @@ elseif (ENABLE_SIMD STREQUAL "SSE42") target_compile_options(sse4_2 INTERFACE -msse4.2) endif() target_link_libraries(${project_name} sse4_2) + target_link_libraries(benchmark neon) endif () elseif (ENABLE_SIMD STREQUAL "AVX2") if (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "x86_64") @@ -45,6 +50,7 @@ elseif (ENABLE_SIMD STREQUAL "AVX2") target_compile_options(avx2 INTERFACE -mavx2) endif() target_link_libraries(${project_name} avx2) + target_link_libraries(benchmark neon) set(CMAKE_CXX_FLAGS "-fpermissive") endif () endif () diff --git a/example/benchmark.cpp b/example/benchmark.cpp new file mode 100644 index 00000000..604ccda6 --- /dev/null +++ b/example/benchmark.cpp @@ -0,0 +1,13 @@ +#include + +using namespace cinatra; +using namespace std::chrono_literals; + +int main() { + coro_http_server server(std::thread::hardware_concurrency(), 8090); + server.set_http_handler( + "/", [](coro_http_request& req, coro_http_response& resp) { + resp.set_status_and_content(status_type::ok, "Hello, world!"); + }); + server.sync_start(); +} \ No newline at end of file diff --git a/include/cinatra/coro_http_response.hpp b/include/cinatra/coro_http_response.hpp index a5e7dd30..ee627ae0 100644 --- a/include/cinatra/coro_http_response.hpp +++ b/include/cinatra/coro_http_response.hpp @@ -38,9 +38,7 @@ class coro_http_response { : status_(status_type::not_implemented), fmt_type_(format_type::normal), delay_(false), - conn_(conn) { - head_.reserve(128); - } + conn_(conn) {} void set_status(cinatra::status_type status) { status_ = status; } void set_content(std::string content) { @@ -67,10 +65,8 @@ class coro_http_response { std::string_view get_boundary() { return boundary_; } void to_buffers(std::vector &buffers) { - build_resp_head(); - buffers.push_back(asio::buffer(to_http_status_string(status_))); - buffers.push_back(asio::buffer(head_)); + build_resp_head(buffers); if (!content_.empty()) { if (fmt_type_ == format_type::chunked) { to_chunked_buffers(buffers, content_, true); @@ -81,7 +77,7 @@ class coro_http_response { } } - void build_resp_head() { + void build_resp_head(std::vector &buffers) { bool has_len = false; bool has_host = false; for (auto &[k, v] : resp_headers_) { @@ -94,7 +90,7 @@ class coro_http_response { } if (!has_host) { - resp_headers_sv_.emplace_back(resp_header_sv{"Host", "cinatra"}); + buffers.emplace_back(asio::buffer(CINATRA_HOST_SV)); } if (content_.empty() && !has_set_content_ && @@ -103,46 +99,51 @@ class coro_http_response { } if (fmt_type_ == format_type::chunked) { - resp_headers_sv_.emplace_back( - resp_header_sv{"Transfer-Encoding", "chunked"}); + buffers.emplace_back(asio::buffer(TRANSFER_ENCODING_SV)); } else { if (!content_.empty()) { auto [ptr, ec] = std::to_chars(buf_, buf_ + 32, content_.size()); - resp_headers_sv_.emplace_back( - resp_header_sv{"Content-Length", - std::string_view(buf_, std::distance(buf_, ptr))}); + buffers.emplace_back(asio::buffer(CONTENT_LENGTH_SV)); + buffers.emplace_back( + asio::buffer(std::string_view(buf_, std::distance(buf_, ptr)))); + buffers.emplace_back(asio::buffer(CRCF)); } else { if (!has_len && boundary_.empty()) - resp_headers_sv_.emplace_back(resp_header_sv{"Content-Length", "0"}); + buffers.emplace_back(asio::buffer(ZERO_LENGTH_SV)); } } - resp_headers_sv_.emplace_back(resp_header_sv{"Date", get_gmt_time_str()}); + buffers.emplace_back(asio::buffer(DATE_SV)); + buffers.emplace_back(asio::buffer(get_gmt_time_str())); + buffers.emplace_back(asio::buffer(CRCF)); if (keepalive_.has_value()) { bool keepalive = keepalive_.value(); - resp_headers_sv_.emplace_back( - resp_header_sv{"Connection", keepalive ? "keep-alive" : "close"}); + keepalive ? buffers.emplace_back(asio::buffer(CONN_KEEP_SV)) + : buffers.emplace_back(asio::buffer(CONN_CLOSE_SV)); + } + + for (auto &[k, v] : resp_headers_) { + buffers.emplace_back(asio::buffer(k)); + buffers.emplace_back(asio::buffer(COLON_SV)); + buffers.emplace_back(asio::buffer(v)); + buffers.emplace_back(asio::buffer(CRCF)); } - append_head(resp_headers_); - append_head(resp_headers_sv_); - head_.append(CRCF); + buffers.emplace_back(asio::buffer(CRCF)); } coro_http_connection *get_conn() { return conn_; } void clear() { - head_.clear(); content_.clear(); if (need_shrink_every_time_) { content_.shrink_to_fit(); } resp_headers_.clear(); - resp_headers_sv_.clear(); keepalive_ = {}; delay_ = false; status_ = status_type::init; @@ -153,25 +154,14 @@ class coro_http_response { void set_shrink_to_fit(bool r) { need_shrink_every_time_ = r; } - void append_head(auto &headers) { - for (auto &[k, v] : headers) { - head_.append(k); - head_.append(":"); - head_.append(v); - head_.append(CRCF); - } - } - private: status_type status_; format_type fmt_type_; - std::string head_; std::string content_; std::optional keepalive_; bool delay_; char buf_[32]; std::vector resp_headers_; - std::vector resp_headers_sv_; coro_http_connection *conn_; std::string boundary_; bool has_set_content_ = false; diff --git a/include/cinatra/define.h b/include/cinatra/define.h index 46907cf9..29bc7d16 100644 --- a/include/cinatra/define.h +++ b/include/cinatra/define.h @@ -87,7 +87,6 @@ constexpr inline auto TEXT = req_content_type::string; constexpr inline auto RANGES = req_content_type::ranges; constexpr inline auto NONE = req_content_type::none; -inline const std::string_view STATIC_RESOURCE = "cinatra_static_resource"; inline const std::string CSESSIONID = "CSESSIONID"; const static inline std::string CRCF = "\r\n"; @@ -96,6 +95,15 @@ const static inline std::string BOUNDARY = "--CinatraBoundary2B8FAF4A80EDB307"; const static inline std::string MULTIPART_END = CRCF + "--" + BOUNDARY + "--" + CRCF; constexpr std::string_view LAST_CHUNK = "0\r\n"; +constexpr std::string_view CINATRA_HOST_SV = "Host: cinatra\r\n"; +constexpr std::string_view TRANSFER_ENCODING_SV = + "Transfer-Encoding: chunked\r\n"; +constexpr std::string_view CONTENT_LENGTH_SV = "Content-Length: "; +constexpr std::string_view ZERO_LENGTH_SV = "Content-Length: 0\r\n"; +constexpr std::string_view DATE_SV = "Date: "; +constexpr std::string_view CONN_KEEP_SV = "Connection: keep-alive\r\n"; +constexpr std::string_view CONN_CLOSE_SV = "Connection: close\r\n"; +constexpr std::string_view COLON_SV = ": "; struct chunked_result { std::error_code ec;