Add mallocinfo mode to getmemoryinfo
RPC
This adds a mode argument to `getmemoryinfo`. By default the output will remain the same. However if a mode argument of `mallocinfo` is provided the result of glibc `malloc_info` (if available) will be returned as a string, as-is. This is useful for tracking heap usage over time or troubleshooting memory fragmentation issues.
This commit is contained in:
parent
5c1a958124
commit
e141aa4ba6
2 changed files with 54 additions and 7 deletions
|
@ -566,6 +566,13 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/socket.h>]],
|
||||||
[ AC_MSG_RESULT(no)]
|
[ AC_MSG_RESULT(no)]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dnl Check for malloc_info (for memory statistics information in getmemoryinfo)
|
||||||
|
AC_MSG_CHECKING(for getmemoryinfo)
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <malloc.h>]],
|
||||||
|
[[ int f = malloc_info(0, NULL); ]])],
|
||||||
|
[ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_MALLOC_INFO, 1,[Define this symbol if you have malloc_info]) ],
|
||||||
|
[ AC_MSG_RESULT(no)]
|
||||||
|
)
|
||||||
|
|
||||||
AC_MSG_CHECKING([for visibility attribute])
|
AC_MSG_CHECKING([for visibility attribute])
|
||||||
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#ifdef HAVE_MALLOC_INFO
|
||||||
|
#include <malloc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <boost/assign/list_of.hpp>
|
#include <boost/assign/list_of.hpp>
|
||||||
|
|
||||||
|
@ -485,16 +488,39 @@ static UniValue RPCLockedMemoryInfo()
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_MALLOC_INFO
|
||||||
|
static std::string RPCMallocInfo()
|
||||||
|
{
|
||||||
|
char *ptr = nullptr;
|
||||||
|
size_t size = 0;
|
||||||
|
FILE *f = open_memstream(&ptr, &size);
|
||||||
|
if (f) {
|
||||||
|
malloc_info(0, f);
|
||||||
|
fclose(f);
|
||||||
|
if (ptr) {
|
||||||
|
std::string rv(ptr, size);
|
||||||
|
free(ptr);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
UniValue getmemoryinfo(const JSONRPCRequest& request)
|
UniValue getmemoryinfo(const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
/* Please, avoid using the word "pool" here in the RPC interface or help,
|
/* Please, avoid using the word "pool" here in the RPC interface or help,
|
||||||
* as users will undoubtedly confuse it with the other "memory pool"
|
* as users will undoubtedly confuse it with the other "memory pool"
|
||||||
*/
|
*/
|
||||||
if (request.fHelp || request.params.size() != 0)
|
if (request.fHelp || request.params.size() > 1)
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"getmemoryinfo\n"
|
"getmemoryinfo (\"mode\")\n"
|
||||||
"Returns an object containing information about memory usage.\n"
|
"Returns an object containing information about memory usage.\n"
|
||||||
"\nResult:\n"
|
"Arguments:\n"
|
||||||
|
"1. \"mode\" determines what kind of information is returned. This argument is optional, the default mode is \"stats\".\n"
|
||||||
|
" - \"stats\" returns general statistics about memory usage in the daemon.\n"
|
||||||
|
" - \"mallocinfo\" returns an XML string describing low-level heap state (only available if compiled with glibc 2.10+).\n"
|
||||||
|
"\nResult (mode \"stats\"):\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" \"locked\": { (json object) Information about locked memory manager\n"
|
" \"locked\": { (json object) Information about locked memory manager\n"
|
||||||
" \"used\": xxxxx, (numeric) Number of bytes used\n"
|
" \"used\": xxxxx, (numeric) Number of bytes used\n"
|
||||||
|
@ -505,13 +531,27 @@ UniValue getmemoryinfo(const JSONRPCRequest& request)
|
||||||
" \"chunks_free\": xxxxx, (numeric) Number unused chunks\n"
|
" \"chunks_free\": xxxxx, (numeric) Number unused chunks\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
"\nResult (mode \"mallocinfo\"):\n"
|
||||||
|
"\"<malloc version=\"1\">...\"\n"
|
||||||
"\nExamples:\n"
|
"\nExamples:\n"
|
||||||
+ HelpExampleCli("getmemoryinfo", "")
|
+ HelpExampleCli("getmemoryinfo", "")
|
||||||
+ HelpExampleRpc("getmemoryinfo", "")
|
+ HelpExampleRpc("getmemoryinfo", "")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
std::string mode = (request.params.size() < 1 || request.params[0].isNull()) ? "stats" : request.params[0].get_str();
|
||||||
|
if (mode == "stats") {
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
obj.push_back(Pair("locked", RPCLockedMemoryInfo()));
|
obj.push_back(Pair("locked", RPCLockedMemoryInfo()));
|
||||||
return obj;
|
return obj;
|
||||||
|
} else if (mode == "mallocinfo") {
|
||||||
|
#ifdef HAVE_MALLOC_INFO
|
||||||
|
return RPCMallocInfo();
|
||||||
|
#else
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "mallocinfo is only available when compiled with glibc 2.10+");
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown mode " + mode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue echo(const JSONRPCRequest& request)
|
UniValue echo(const JSONRPCRequest& request)
|
||||||
|
@ -531,7 +571,7 @@ static const CRPCCommand commands[] =
|
||||||
{ // category name actor (function) okSafeMode
|
{ // category name actor (function) okSafeMode
|
||||||
// --------------------- ------------------------ ----------------------- ----------
|
// --------------------- ------------------------ ----------------------- ----------
|
||||||
{ "control", "getinfo", &getinfo, true, {} }, /* uses wallet if enabled */
|
{ "control", "getinfo", &getinfo, true, {} }, /* uses wallet if enabled */
|
||||||
{ "control", "getmemoryinfo", &getmemoryinfo, true, {} },
|
{ "control", "getmemoryinfo", &getmemoryinfo, true, {"mode"} },
|
||||||
{ "util", "validateaddress", &validateaddress, true, {"address"} }, /* uses wallet if enabled */
|
{ "util", "validateaddress", &validateaddress, true, {"address"} }, /* uses wallet if enabled */
|
||||||
{ "util", "createmultisig", &createmultisig, true, {"nrequired","keys"} },
|
{ "util", "createmultisig", &createmultisig, true, {"nrequired","keys"} },
|
||||||
{ "util", "verifymessage", &verifymessage, true, {"address","signature","message"} },
|
{ "util", "verifymessage", &verifymessage, true, {"address","signature","message"} },
|
||||||
|
|
Loading…
Reference in a new issue