From 878ce873290deb9f707ee88a9725c4ac5254628c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=8F=E6=A5=9A?= <771730766@qq.com> Date: Mon, 27 Dec 2021 17:40:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=BA=BF=E7=A8=8B=E5=86=85?= =?UTF-8?q?=E5=AD=98malloc=E7=BB=9F=E8=AE=A1=20(#1317)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 3rdpart/ZLToolKit | 2 +- server/WebApi.cpp | 53 +++++++++++++++++-- server/WebApi.h | 2 +- server/WebHook.cpp | 12 ++--- src/Common/config.cpp | 118 +++++++++++++++++++++++++++--------------- 5 files changed, 132 insertions(+), 55 deletions(-) diff --git a/3rdpart/ZLToolKit b/3rdpart/ZLToolKit index 8afa63c3..f2f79123 160000 --- a/3rdpart/ZLToolKit +++ b/3rdpart/ZLToolKit @@ -1 +1 @@ -Subproject commit 8afa63c31522e031c3d4857f0c723ee4e97447fc +Subproject commit f2f79123f23943381009e89b407aa6f8ef683a82 diff --git a/server/WebApi.cpp b/server/WebApi.cpp index 96fd7481..2b3f61db 100755 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -212,6 +212,7 @@ static ApiArgsType getAllArgs(const Parser &parser) { } extern uint64_t getTotalMemUsage(); +extern uint64_t getThisThreadMemUsage(); static inline void addHttpListener(){ GET_CONFIG(bool, api_debug, API::kApiDebug); @@ -356,8 +357,9 @@ Value makeMediaSourceJson(MediaSource &media){ return item; } -Value getStatisticJson() { - Value val(objectValue); +void getStatisticJson(const function &cb) { + auto obj = std::make_shared(objectValue); + auto &val = *obj; val["MediaSource"] = (Json::UInt64)(ObjectStatistic::count()); val["MultiMediaSourceMuxer"] = (Json::UInt64)(ObjectStatistic::count()); @@ -382,8 +384,46 @@ Value getStatisticJson() { auto bytes = getTotalMemUsage(); val["totalMemUsage"] = (Json::UInt64)bytes; val["totalMemUsageMB"] = (int)(bytes / 1024 / 1024); + + auto thread_size = EventPollerPool::Instance().getExecutorSize() + WorkThreadPool::Instance().getExecutorSize(); + std::shared_ptr > thread_mem_info = std::make_shared >(thread_size); + std::shared_ptr > thread_mem_total = std::make_shared >(0); + + shared_ptr finished(nullptr, [thread_mem_info, cb, obj, thread_mem_total](void *) { + //poller和work线程开辟的内存 + for (auto &val : *thread_mem_info) { + (*obj)["threadMem"].append(val); + } + + //其他线程申请的内存为总内存减去poller和work线程开辟的内存 + auto bytes = getTotalMemUsage() - *thread_mem_total; + Value val; + val["threadName"] = "other threads"; + val["threadMemUsage"] = (Json::UInt64) bytes; + val["threadMemUsageMB"] = (int) (bytes / 1024 / 1024); + (*obj)["threadMem"].append(val); + + //触发回调 + cb(*obj); + }); + + auto pos = 0; + auto lam = [&](const TaskExecutor::Ptr &executor) { + auto &val = (*thread_mem_info)[pos++]; + executor->async([finished, thread_mem_total, &val]() { + auto bytes = getThisThreadMemUsage(); + *thread_mem_total += bytes; + + val["threadName"] = getThreadName(); + val["threadMemUsage"] = (Json::UInt64) bytes; + val["threadMemUsageMB"] = (int) (bytes / 1024 / 1024); + }); + }; + EventPollerPool::Instance().for_each(lam); + WorkThreadPool::Instance().for_each(lam); +#else + cb(*obj); #endif - return val; } /** @@ -1278,9 +1318,12 @@ void installWebApi() { }); }); - api_regist("/index/api/getStatistic",[](API_ARGS_MAP){ + api_regist("/index/api/getStatistic",[](API_ARGS_MAP_ASYNC){ CHECK_SECRET(); - val["data"] = getStatisticJson(); + getStatisticJson([headerOut, val, invoker](const Value &data) mutable{ + val["data"] = data; + invoker(200, headerOut, val.toStyledString()); + }); }); #ifdef ENABLE_WEBRTC diff --git a/server/WebApi.h b/server/WebApi.h index e713af61..cc02535c 100755 --- a/server/WebApi.h +++ b/server/WebApi.h @@ -235,5 +235,5 @@ bool checkArgs(Args &args, const First &first, const KeyTypes &...keys) { void installWebApi(); void unInstallWebApi(); Value makeMediaSourceJson(MediaSource &media); -Value getStatisticJson(); +void getStatisticJson(const function &cb); #endif //ZLMEDIAKIT_WEBAPI_H diff --git a/server/WebHook.cpp b/server/WebHook.cpp index 3e84e5bf..497bfc66 100755 --- a/server/WebHook.cpp +++ b/server/WebHook.cpp @@ -202,12 +202,12 @@ static void reportServerKeepalive() { GET_CONFIG(float, alive_interval, Hook::kAliveInterval); g_keepalive_timer = std::make_shared(alive_interval, []() { - ArgsType body; - body["data"] = getStatisticJson(); - - //执行hook - do_http_hook(hook_server_keepalive, body, nullptr); - + getStatisticJson([](const Value &data) mutable { + ArgsType body; + body["data"] = data; + //执行hook + do_http_hook(hook_server_keepalive, body, nullptr); + }); return true; }, nullptr); } diff --git a/src/Common/config.cpp b/src/Common/config.cpp index 98ce831e..81824dd3 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -8,12 +8,12 @@ * may be found in the AUTHORS file in the root of the source tree. */ +#include #include "Common/config.h" #include "Util/util.h" #include "Util/logger.h" #include "Util/onceToken.h" #include "Util/NoticeCenter.h" -#include "Network/sockutil.h" using namespace toolkit; @@ -318,31 +318,67 @@ const string kWaitTrackReady = "wait_track_ready"; #ifdef ENABLE_MEM_DEBUG -static atomic mem_usage(0); - -uint64_t getTotalMemUsage() { - return mem_usage.load(); +extern "C" { + extern void *__real_malloc(size_t); + extern void __real_free(void *); + extern void *__real_realloc(void *ptr, size_t c); + void *__wrap_malloc(size_t c); + void __wrap_free(void *ptr); + void *__wrap_calloc(size_t __nmemb, size_t __size); + void *__wrap_realloc(void *ptr, size_t c); } -extern "C" { +class MemAllocInfo { +public: + static atomic total_mem_usage; + atomic mem_usage{0}; +}; -#include -#define MAGIC_BYTES 0xFEFDFCFB -#define MAGIC_BYTES_SIZE 4 -#define MEM_PREFIX_SIZE 8 +atomic MemAllocInfo::total_mem_usage{0}; -extern void *__real_malloc(size_t); -extern void __real_free(void *); -extern void *__real_realloc(void *ptr, size_t c); +static thread_local MemAllocInfo s_alloc_info; + +uint64_t getTotalMemUsage() { + return MemAllocInfo::total_mem_usage.load(); +} + +uint64_t getThisThreadMemUsage() { + return s_alloc_info.mem_usage.load(); +} + +#if defined(_WIN32) +#pragma pack(push, 1) +#endif // defined(_WIN32) + +class MemCookie { +public: + static constexpr uint32_t kMagic = 0xFEFDFCFB; + uint32_t magic; + uint32_t size; + MemAllocInfo *alloc_info; + char ptr; +}PACKED; + +#if defined(_WIN32) +#pragma pack(pop) +#endif // defined(_WIN32) + +#define MEM_OFFSET (sizeof(MemCookie) - 1) + +void init_cookie(MemCookie *cookie, size_t c) { + MemAllocInfo::total_mem_usage += c; + s_alloc_info.mem_usage += c; + cookie->magic = MemCookie::kMagic; + cookie->size = c; + cookie->alloc_info = &s_alloc_info; +} void *__wrap_malloc(size_t c) { - c += MEM_PREFIX_SIZE; - char *ret = (char *) __real_malloc(c); - if (ret) { - mem_usage += c; - *((uint32_t *) (ret)) = MAGIC_BYTES; - *((uint32_t *) (ret + MAGIC_BYTES_SIZE)) = c; - return ret + MEM_PREFIX_SIZE; + c += MEM_OFFSET; + auto cookie = (MemCookie *) __real_malloc(c); + if (cookie) { + init_cookie(cookie, c); + return &cookie->ptr; } return nullptr; } @@ -351,13 +387,13 @@ void __wrap_free(void *ptr) { if (!ptr) { return; } - ptr = (char *) ptr - MEM_PREFIX_SIZE; - uint32_t magic = *((uint32_t *) (ptr)); - if (magic != MAGIC_BYTES) { + auto cookie = (MemCookie *) ((char *) ptr - MEM_OFFSET); + if (cookie->magic != MemCookie::kMagic) { throw std::invalid_argument("attempt to free invalid memory"); } - mem_usage -= *((uint32_t *) ((char *) ptr + MAGIC_BYTES_SIZE)); - __real_free(ptr); + MemAllocInfo::total_mem_usage -= cookie->size; + cookie->alloc_info->mem_usage -= cookie->size; + __real_free(cookie); } void *__wrap_calloc(size_t __nmemb, size_t __size) { @@ -369,30 +405,28 @@ void *__wrap_calloc(size_t __nmemb, size_t __size) { return ret; } -void *__wrap_realloc(void *ptr, size_t c){ +void *__wrap_realloc(void *ptr, size_t c) { if (!ptr) { return malloc(c); } - c += MEM_PREFIX_SIZE; - ptr = (char *) ptr - MEM_PREFIX_SIZE; - uint32_t magic = *((uint32_t *) (ptr)); - if (magic != MAGIC_BYTES) { + auto cookie = (MemCookie *) ((char *) ptr - MEM_OFFSET); + if (cookie->magic != MemCookie::kMagic) { throw std::invalid_argument("attempt to realloc invalid memory"); } - auto old_size = *((uint32_t *) ((char *) ptr + MAGIC_BYTES_SIZE)); - char *ret = (char *) __real_realloc(ptr, c); - if (ret) { - mem_usage += c - old_size; - *((uint32_t *) (ret)) = MAGIC_BYTES; - *((uint32_t *) (ret + MAGIC_BYTES_SIZE)) = c; - return ret + MEM_PREFIX_SIZE; - } - free(ptr); - mem_usage -= old_size; - return nullptr; -} + MemAllocInfo::total_mem_usage -= cookie->size; + cookie->alloc_info->mem_usage -= cookie->size; + + c += MEM_OFFSET; + cookie = (MemCookie *) __real_realloc(cookie, c); + if (cookie) { + init_cookie(cookie, c); + return &cookie->ptr; + } + + free(cookie); + return nullptr; } void *operator new(std::size_t size) {