diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index b4c6bdd92..4ac71ed4b 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -105,6 +105,12 @@ inotify_auto_reload off; # default: on auto_reload_for_docker on; +# For tcmalloc, the release rate. +# @see https://gperftools.github.io/gperftools/tcmalloc.html +# @remark Should run configure --with-gperf +# default: 0.8 +tcmalloc_release_rate 0.8; + ############################################################################################# # heartbeat/stats sections ############################################################################################# diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index b1df5deff..c70e551b9 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3518,7 +3518,7 @@ srs_error_t SrsConfig::check_normal_config() && n != "utc_time" && n != "work_dir" && n != "asprocess" && n != "ff_log_level" && n != "grace_final_wait" && n != "force_grace_quit" && n != "grace_start_wait" && n != "empty_ip_ok" && n != "disable_daemon_for_docker" - && n != "inotify_auto_reload" && n != "auto_reload_for_docker" + && n != "inotify_auto_reload" && n != "auto_reload_for_docker" && n != "tcmalloc_release_rate" ) { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal directive %s", n.c_str()); } @@ -4202,6 +4202,22 @@ bool SrsConfig::auto_reload_for_docker() return SRS_CONF_PERFER_TRUE(conf->arg0()); } +// TODO: FIXME: Support reload. +double SrsConfig::tcmalloc_release_rate() +{ + static double DEFAULT = SRS_PERF_TCMALLOC_RELEASE_RATE; + + SrsConfDirective* conf = root->get("tcmalloc_release_rate"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + double trr = ::atof(conf->arg0().c_str()); + trr = srs_min(10, trr); + trr = srs_max(0, trr); + return trr; +} + vector SrsConfig::get_stream_casters() { srs_assert(root); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index ebf34ff3f..01732bb11 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -483,6 +483,8 @@ public: virtual bool inotify_auto_reload(); // Whether enable auto reload config for docker. virtual bool auto_reload_for_docker(); + // For tcmalloc, get the release rate. + virtual double tcmalloc_release_rate(); // stream_caster section public: // Get all stream_caster in config file. diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index 70f06f814..2ccd394ad 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -268,6 +268,7 @@ srs_error_t SrsGoApiV1::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r urls->set("raw", SrsJsonAny::str("raw api for srs, support CUID srs for instance the config")); urls->set("clusters", SrsJsonAny::str("origin cluster server API")); urls->set("perf", SrsJsonAny::str("System performance stat")); + urls->set("tcmalloc", SrsJsonAny::str("tcmalloc api with params ?page=summary|api")); SrsJsonObject* tests = SrsJsonAny::object(); obj->set("tests", tests); @@ -1636,7 +1637,6 @@ srs_error_t SrsGoApiError::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage } #ifdef SRS_AUTO_GB28181 - SrsGoApiGb28181::SrsGoApiGb28181() { } @@ -1761,7 +1761,83 @@ srs_error_t SrsGoApiGb28181::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa return srs_api_response_code(w, r, ERROR_GB28181_SERVER_NOT_RUN); } } +#endif + +#ifdef SRS_AUTO_GPERF +#include + +SrsGoApiTcmalloc::SrsGoApiTcmalloc() +{ +} + +SrsGoApiTcmalloc::~SrsGoApiTcmalloc() +{ +} + +srs_error_t SrsGoApiTcmalloc::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) +{ + srs_error_t err = srs_success; + + string page = r->query_get("page"); + + if (page == "summary") { + char buffer[32 * 1024]; + MallocExtension::instance()->GetStats(buffer, sizeof(buffer)); + + string data(buffer); + if ((err = w->write((char*)data.data(), (int)data.length())) != srs_success) { + return srs_error_wrap(err, "write"); + } + + return err; + } + + // By default, response the json style response. + SrsJsonObject* obj = SrsJsonAny::object(); + SrsAutoFree(SrsJsonObject, obj); + + obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS)); + SrsJsonObject* data = SrsJsonAny::object(); + obj->set("data", data); + + size_t value = 0; + + // @see https://gperftools.github.io/gperftools/tcmalloc.html + data->set("release_rate", SrsJsonAny::number(MallocExtension::instance()->GetMemoryReleaseRate())); + + if (true) { + SrsJsonObject* p = SrsJsonAny::object(); + data->set("generic", p); + + MallocExtension::instance()->GetNumericProperty("generic.current_allocated_bytes", &value); + p->set("current_allocated_bytes", SrsJsonAny::integer(value)); + + MallocExtension::instance()->GetNumericProperty("generic.heap_size", &value); + p->set("heap_size", SrsJsonAny::integer(value)); + } + if (true) { + SrsJsonObject* p = SrsJsonAny::object(); + data->set("tcmalloc", p); + + MallocExtension::instance()->GetNumericProperty("tcmalloc.pageheap_free_bytes", &value); + p->set("pageheap_free_bytes", SrsJsonAny::integer(value)); + + MallocExtension::instance()->GetNumericProperty("tcmalloc.pageheap_unmapped_bytes", &value); + p->set("pageheap_unmapped_bytes", SrsJsonAny::integer(value)); + + MallocExtension::instance()->GetNumericProperty("tcmalloc.slack_bytes", &value); + p->set("slack_bytes", SrsJsonAny::integer(value)); + + MallocExtension::instance()->GetNumericProperty("tcmalloc.max_total_thread_cache_bytes", &value); + p->set("max_total_thread_cache_bytes", SrsJsonAny::integer(value)); + + MallocExtension::instance()->GetNumericProperty("tcmalloc.current_total_thread_cache_bytes", &value); + p->set("current_total_thread_cache_bytes", SrsJsonAny::integer(value)); + } + + return srs_api_response(w, r, obj->dumps()); +} #endif SrsHttpApi::SrsHttpApi(IConnectionManager* cm, srs_netfd_t fd, SrsHttpServeMux* m, string cip) diff --git a/trunk/src/app/srs_app_http_api.hpp b/trunk/src/app/srs_app_http_api.hpp index 80cde35fd..6dbed63d5 100644 --- a/trunk/src/app/srs_app_http_api.hpp +++ b/trunk/src/app/srs_app_http_api.hpp @@ -241,9 +241,7 @@ public: virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); }; - #ifdef SRS_AUTO_GB28181 - class SrsGoApiGb28181 : public ISrsHttpHandler { public: @@ -252,7 +250,17 @@ public: public: virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); }; +#endif +#ifdef SRS_AUTO_GPERF +class SrsGoApiTcmalloc : public ISrsHttpHandler +{ +public: + SrsGoApiTcmalloc(); + virtual ~SrsGoApiTcmalloc(); +public: + virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); +}; #endif class SrsHttpApi : virtual public SrsConnection, virtual public ISrsReloadHandler diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index 13d513277..f4045ce40 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -1014,6 +1014,14 @@ srs_error_t SrsServer::http_handle() if ((err = http_api_mux->handle("error.srs.com/api/v1/tests/errors", new SrsGoApiError())) != srs_success) { return srs_error_wrap(err, "handle tests errors for error.srs.com"); } + +#ifdef SRS_AUTO_GPERF + // The test api for get tcmalloc stats. + // @see Memory Introspection in https://gperftools.github.io/gperftools/tcmalloc.html + if ((err = http_api_mux->handle("/api/v1/tcmalloc", new SrsGoApiTcmalloc())) != srs_success) { + return srs_error_wrap(err, "handle tests errors"); + } +#endif // TODO: FIXME: for console. // TODO: FIXME: support reload. diff --git a/trunk/src/core/srs_core_performance.hpp b/trunk/src/core/srs_core_performance.hpp index 122a1469f..07c1e1539 100644 --- a/trunk/src/core/srs_core_performance.hpp +++ b/trunk/src/core/srs_core_performance.hpp @@ -58,6 +58,10 @@ #define SRS_PERF_MR_ENABLED false #define SRS_PERF_MR_SLEEP (350 * SRS_UTIME_MILLISECONDS) +// For tcmalloc, set the default release rate. +// @see https://gperftools.github.io/gperftools/tcmalloc.html +#define SRS_PERF_TCMALLOC_RELEASE_RATE 0.8 + /** * the MW(merged-write) send cache time in srs_utime_t. * the default value, user can override it in config. diff --git a/trunk/src/main/srs_main_server.cpp b/trunk/src/main/srs_main_server.cpp index 83f87d105..e4641285c 100644 --- a/trunk/src/main/srs_main_server.cpp +++ b/trunk/src/main/srs_main_server.cpp @@ -37,6 +37,10 @@ using namespace std; #include #endif +#ifdef SRS_AUTO_GPERF +#include +#endif + #include using namespace std; @@ -185,6 +189,16 @@ srs_error_t do_main(int argc, char** argv) // features show_macro_features(); + +#ifdef SRS_AUTO_GPERF + // For tcmalloc, use slower release rate. + if (true) { + double trr = _srs_config->tcmalloc_release_rate(); + double otrr = MallocExtension::instance()->GetMemoryReleaseRate(); + MallocExtension::instance()->SetMemoryReleaseRate(trr); + srs_trace("tcmalloc: set release-rate %.2f=>%.2f", otrr, trr); + } +#endif if ((err = run_directly_or_daemon()) != srs_success) { return srs_error_wrap(err, "run");