@@ -373,6 +373,46 @@ using socket_t = int;
373373#include < zstd.h>
374374#endif
375375
376+ // Profiling support
377+ #ifdef CPPHTTPLIB_PROFILE
378+ #include < chrono>
379+ #include < iostream>
380+
381+ namespace httplib {
382+ namespace detail {
383+ // Thread-local profiling base time
384+ inline std::chrono::high_resolution_clock::time_point &get_profile_base_time () {
385+ thread_local auto base_time = std::chrono::high_resolution_clock::now ();
386+ return base_time;
387+ }
388+ } // namespace detail
389+ } // namespace httplib
390+
391+ #define CPPHTTPLIB_PROFILE_START () \
392+ do { \
393+ httplib::detail::get_profile_base_time () = \
394+ std::chrono::high_resolution_clock::now (); \
395+ } while (0 )
396+
397+ #define CPPHTTPLIB_PROFILE_POINT (name ) \
398+ do { \
399+ auto __profile_now = std::chrono::high_resolution_clock::now (); \
400+ auto __profile_elapsed = \
401+ std::chrono::duration_cast<std::chrono::microseconds>( \
402+ __profile_now - httplib::detail::get_profile_base_time ()) \
403+ .count (); \
404+ std::cout << " [PROFILE] " << name << " : " << __profile_elapsed << " μs" \
405+ << std::endl; \
406+ } while (0 )
407+ #else
408+ #define CPPHTTPLIB_PROFILE_START () \
409+ do { \
410+ } while (0 )
411+ #define CPPHTTPLIB_PROFILE_POINT (name ) \
412+ do { \
413+ } while (0 )
414+ #endif
415+
376416/*
377417 * Declaration
378418 */
@@ -4090,6 +4130,7 @@ inline socket_t create_client_socket(
40904130 time_t connection_timeout_usec, time_t read_timeout_sec,
40914131 time_t read_timeout_usec, time_t write_timeout_sec,
40924132 time_t write_timeout_usec, const std::string &intf, Error &error) {
4133+ CPPHTTPLIB_PROFILE_POINT (" create_client_socket start" );
40934134 auto sock = create_socket (
40944135 host, ip, port, address_family, 0 , tcp_nodelay, ipv6_v6only,
40954136 std::move (socket_options),
@@ -4107,16 +4148,20 @@ inline socket_t create_client_socket(
41074148
41084149 set_nonblocking (sock2, true );
41094150
4151+ CPPHTTPLIB_PROFILE_POINT (" before connect()" );
41104152 auto ret =
41114153 ::connect (sock2, ai.ai_addr, static_cast <socklen_t >(ai.ai_addrlen));
4154+ CPPHTTPLIB_PROFILE_POINT (" after connect()" );
41124155
41134156 if (ret < 0 ) {
41144157 if (is_connection_error ()) {
41154158 error = Error::Connection;
41164159 return false ;
41174160 }
4161+ CPPHTTPLIB_PROFILE_POINT (" before wait_until_socket_is_ready" );
41184162 error = wait_until_socket_is_ready (sock2, connection_timeout_sec,
41194163 connection_timeout_usec);
4164+ CPPHTTPLIB_PROFILE_POINT (" after wait_until_socket_is_ready" );
41204165 if (error != Error::Success) {
41214166 if (error == Error::ConnectionTimeout) { quit = true ; }
41224167 return false ;
@@ -8728,6 +8773,8 @@ inline bool ClientImpl::send(Request &req, Response &res, Error &error) {
87288773}
87298774
87308775inline bool ClientImpl::send_ (Request &req, Response &res, Error &error) {
8776+ CPPHTTPLIB_PROFILE_START ();
8777+ CPPHTTPLIB_PROFILE_POINT (" send_ start" );
87318778 {
87328779 std::lock_guard<std::mutex> guard (socket_mutex_);
87338780
@@ -8738,6 +8785,7 @@ inline bool ClientImpl::send_(Request &req, Response &res, Error &error) {
87388785
87398786 auto is_alive = false ;
87408787 if (socket_.is_open ()) {
8788+ CPPHTTPLIB_PROFILE_POINT (" check socket is_alive" );
87418789 is_alive = detail::is_socket_alive (socket_.sock );
87428790
87438791#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
@@ -8761,10 +8809,12 @@ inline bool ClientImpl::send_(Request &req, Response &res, Error &error) {
87618809 }
87628810
87638811 if (!is_alive) {
8812+ CPPHTTPLIB_PROFILE_POINT (" before create_and_connect_socket" );
87648813 if (!create_and_connect_socket (socket_, error)) {
87658814 output_error_log (error, &req);
87668815 return false ;
87678816 }
8817+ CPPHTTPLIB_PROFILE_POINT (" after create_and_connect_socket" );
87688818
87698819#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
87708820 // TODO: refactoring
@@ -8857,6 +8907,7 @@ inline Result ClientImpl::send_(Request &&req) {
88578907inline bool ClientImpl::handle_request (Stream &strm, Request &req,
88588908 Response &res, bool close_connection,
88598909 Error &error) {
8910+ CPPHTTPLIB_PROFILE_POINT (" handle_request start" );
88608911 if (req.path .empty ()) {
88618912 error = Error::Connection;
88628913 output_error_log (error, &req);
@@ -8870,11 +8921,15 @@ inline bool ClientImpl::handle_request(Stream &strm, Request &req,
88708921 if (!is_ssl () && !proxy_host_.empty () && proxy_port_ != -1 ) {
88718922 auto req2 = req;
88728923 req2.path = " http://" + host_and_port_ + req.path ;
8924+ CPPHTTPLIB_PROFILE_POINT (" before process_request (proxy)" );
88738925 ret = process_request (strm, req2, res, close_connection, error);
8926+ CPPHTTPLIB_PROFILE_POINT (" after process_request (proxy)" );
88748927 req = req2;
88758928 req.path = req_save.path ;
88768929 } else {
8930+ CPPHTTPLIB_PROFILE_POINT (" before process_request" );
88778931 ret = process_request (strm, req, res, close_connection, error);
8932+ CPPHTTPLIB_PROFILE_POINT (" after process_request" );
88788933 }
88798934
88808935 if (!ret) { return false ; }
0 commit comments