| **ceph** **health** *{detail}*
-| **ceph** **heap** [ *dump* \| *start_profiler* \| *stop_profiler* \| *release* \| *stats* ] ...
+| **ceph** **heap** [ *dump* \| *start_profiler* \| *stop_profiler* \| *release* \| *get_release_rate* \| *set_release_rate* \| *stats* ] ...
| **ceph** **injectargs** *<injectedargs>* [ *<injectedargs>*... ]
Usage::
- ceph heap dump|start_profiler|stop_profiler|release|stats
+ ceph heap dump|start_profiler|stop_profiler|stats
+Subcommand ``release`` to make TCMalloc to releases no-longer-used memory back to the kernel at once.
+
+Usage::
+
+ ceph heap release
+
+Subcommand ``(get|set)_release_rate`` get or set the TCMalloc memory release rate. TCMalloc releases
+no-longer-used memory back to the kernel gradually. the rate controls how quickly this happens.
+Increase this setting to make TCMalloc to return unused memory more frequently. 0 means never return
+memory to system, 1 means wait for 1000 pages after releasing a page to system. It is ``1.0`` by default..
+
+Usage::
+
+ ceph heap get_release_rate|set_release_rate {<val>}
injectargs
----------
cmd_getval(cct, cmdmap, "heapcmd", heapcmd);
vector<string> heapcmd_vec;
get_str_vec(heapcmd, heapcmd_vec);
+ string value;
+ if (cmd_getval(cct, cmdmap, "value", value))
+ heapcmd_vec.push_back(value);
ceph_heap_profiler_handle_command(heapcmd_vec, ds);
}
} else if (prefix == "cpu_profiler") {
// XXX 1-element vector, change at callee or make vector here?
vector<string> heapcmd_vec;
get_str_vec(heapcmd, heapcmd_vec);
+ string value;
+ if (cmd_getval(g_ceph_context, cmdmap, "value", value))
+ heapcmd_vec.push_back(value);
ceph_heap_profiler_handle_command(heapcmd_vec, ds);
rdata.append(ds);
rs = "";
r = admin_socket->register_command( "heap",
"heap " \
- "name=heapcmd,type=CephString",
+ "name=heapcmd,type=CephString " \
+ "name=value,type=CephString,req=false",
asok_hook,
"show heap usage info (available only if "
"compiled with tcmalloc)");
"osd", "rw")
COMMAND("flush_pg_stats", "flush pg stats", "osd", "rw")
COMMAND("heap " \
- "name=heapcmd,type=CephChoices,strings=dump|start_profiler|stop_profiler|release|stats", \
- "show heap usage info (available only if compiled with tcmalloc)", \
+ "name=heapcmd,type=CephChoices,strings="\
+ "dump|start_profiler|stop_profiler|release|get_release_rate|set_release_rate|stats " \
+ "name=value,type=CephString,req=false",
+ "show heap usage info (available only if compiled with tcmalloc)",
"osd", "rw")
COMMAND("debug dump_missing " \
"name=filename,type=CephFilepath",
if (!cmd_getval(&cct, cmdmap, "heapcmd", cmd)) {
os << "unable to get value for command \"" << cmd << "\"";
return -EINVAL;
- }
+ }
std::vector<std::string> cmd_vec;
get_str_vec(cmd, cmd_vec);
+
+ string val;
+ if (cmd_getval(&cct, cmdmap, "value", val)) {
+ cmd_vec.push_back(val);
+ }
ceph_heap_profiler_handle_command(cmd_vec, os);
void ceph_heap_release_free_memory() { return; }
+double ceph_heap_get_release_rate() { return 0; }
+
+void ceph_heap_set_release_rate(double value) { return; }
+
bool ceph_heap_profiler_running() { return false; }
void ceph_heap_profiler_start() { return; }
MallocExtension::instance()->ReleaseFreeMemory();
}
+double ceph_heap_get_release_rate()
+{
+ return MallocExtension::instance()->GetMemoryReleaseRate();
+}
+
+void ceph_heap_set_release_rate(double val)
+{
+ MallocExtension::instance()->SetMemoryReleaseRate(val);
+}
+
bool ceph_heap_get_numeric_property(
const char *property, size_t *value)
{
} else if (cmd.size() == 1 && cmd[0] == "release") {
ceph_heap_release_free_memory();
out << g_conf()->name << " releasing free RAM back to system.";
+ } else if (cmd.size() == 1 && cmd[0] == "get_release_rate") {
+ out << g_conf()->name << " release rate: "
+ << std::setprecision(4) << ceph_heap_get_release_rate() << "\n";
+ } else if (cmd.size() == 2 && cmd[0] == "set_release_rate") {
+ try {
+ double val = std::stod(cmd[1]);
+ ceph_heap_set_release_rate(val);
+ out << g_conf()->name << " release rate changed to: "
+ << std::setprecision(4) << ceph_heap_get_release_rate() << "\n";
+ } catch (...) {
+ out << g_conf()->name << " *** need an numerical value. ";
+ }
} else
#endif
if (cmd.size() == 1 && cmd[0] == "stats") {
void ceph_heap_release_free_memory();
+double ceph_heap_get_release_rate();
+
+void ceph_heap_get_release_rate(double value);
+
bool ceph_heap_profiler_running();
void ceph_heap_profiler_start();