]> git.proxmox.com Git - ceph.git/blame - ceph/src/perfglue/heap_profiler.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / perfglue / heap_profiler.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2011 New Dream Network/Sage Weil <sage@newdream.net>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15#include "acconfig.h"
16
17// Use the newer gperftools header locations if available.
18// If not, fall back to the old (gperftools < 2.0) locations.
19
20#include <gperftools/heap-profiler.h>
21#include <gperftools/malloc_extension.h>
22
23#include "heap_profiler.h"
24#include "common/environment.h"
25#include "common/LogClient.h"
26#include "global/global_context.h"
27#include "common/debug.h"
28
29#define dout_context g_ceph_context
30
31bool ceph_using_tcmalloc()
32{
33 return true;
34}
35
36void ceph_heap_profiler_init()
37{
38 // Two other interesting environment variables to set are:
39 // HEAP_PROFILE_ALLOCATION_INTERVAL, HEAP_PROFILE_INUSE_INTERVAL
40 if (get_env_bool("CEPH_HEAP_PROFILER_INIT")) {
41 ceph_heap_profiler_start();
42 }
43}
44
45void ceph_heap_profiler_stats(char *buf, int length)
46{
47 MallocExtension::instance()->GetStats(buf, length);
48}
49
50void ceph_heap_release_free_memory()
51{
52 MallocExtension::instance()->ReleaseFreeMemory();
53}
54
11fdf7f2
TL
55double ceph_heap_get_release_rate()
56{
57 return MallocExtension::instance()->GetMemoryReleaseRate();
58}
59
60void ceph_heap_set_release_rate(double val)
61{
62 MallocExtension::instance()->SetMemoryReleaseRate(val);
63}
64
7c673cae
FG
65bool ceph_heap_get_numeric_property(
66 const char *property, size_t *value)
67{
68 return MallocExtension::instance()->GetNumericProperty(
69 property,
70 value);
71}
72
73bool ceph_heap_set_numeric_property(
74 const char *property, size_t value)
75{
76 return MallocExtension::instance()->SetNumericProperty(
77 property,
78 value);
79}
80
81bool ceph_heap_profiler_running()
82{
83#ifdef HAVE_LIBTCMALLOC
84 return IsHeapProfilerRunning();
85#else
86 return false;
87#endif
88}
89
90static void get_profile_name(char *profile_name, int profile_name_len)
91{
11fdf7f2
TL
92#if __GNUC__ && __GNUC__ >= 8
93#pragma GCC diagnostic push
94 // Don't care, it doesn't matter, and we can't do anything about it.
95#pragma GCC diagnostic ignored "-Wformat-truncation"
96#endif
97
7c673cae 98 char path[PATH_MAX];
11fdf7f2 99 snprintf(path, sizeof(path), "%s", g_conf()->log_file.c_str());
7c673cae
FG
100 char *last_slash = rindex(path, '/');
101
102 if (last_slash == NULL) {
103 snprintf(profile_name, profile_name_len, "./%s.profile",
11fdf7f2 104 g_conf()->name.to_cstr());
7c673cae
FG
105 }
106 else {
107 last_slash[1] = '\0';
108 snprintf(profile_name, profile_name_len, "%s/%s.profile",
11fdf7f2 109 path, g_conf()->name.to_cstr());
7c673cae 110 }
11fdf7f2
TL
111#if __GNUC__ && __GNUC__ >= 8
112#pragma GCC diagnostic pop
113#endif
7c673cae
FG
114}
115
116void ceph_heap_profiler_start()
117{
118#ifdef HAVE_LIBTCMALLOC
119 char profile_name[PATH_MAX];
120 get_profile_name(profile_name, sizeof(profile_name));
121 generic_dout(0) << "turning on heap profiler with prefix "
122 << profile_name << dendl;
123 HeapProfilerStart(profile_name);
124#endif
125}
126
127void ceph_heap_profiler_stop()
128{
129#ifdef HAVE_LIBTCMALLOC
130 HeapProfilerStop();
131#endif
132}
133
134void ceph_heap_profiler_dump(const char *reason)
135{
136#ifdef HAVE_LIBTCMALLOC
137 HeapProfilerDump(reason);
138#endif
139}
140
141#define HEAP_PROFILER_STATS_SIZE 2048
142
143void ceph_heap_profiler_handle_command(const std::vector<std::string>& cmd,
144 ostream& out)
145{
146#ifdef HAVE_LIBTCMALLOC
147 if (cmd.size() == 1 && cmd[0] == "dump") {
148 if (!ceph_heap_profiler_running()) {
149 out << "heap profiler not running; can't dump";
150 return;
151 }
152 char heap_stats[HEAP_PROFILER_STATS_SIZE];
153 ceph_heap_profiler_stats(heap_stats, sizeof(heap_stats));
11fdf7f2 154 out << g_conf()->name << " dumping heap profile now.\n"
7c673cae
FG
155 << heap_stats;
156 ceph_heap_profiler_dump("admin request");
157 } else if (cmd.size() == 1 && cmd[0] == "start_profiler") {
158 ceph_heap_profiler_start();
11fdf7f2 159 out << g_conf()->name << " started profiler";
7c673cae
FG
160 } else if (cmd.size() == 1 && cmd[0] == "stop_profiler") {
161 ceph_heap_profiler_stop();
11fdf7f2 162 out << g_conf()->name << " stopped profiler";
7c673cae
FG
163 } else if (cmd.size() == 1 && cmd[0] == "release") {
164 ceph_heap_release_free_memory();
11fdf7f2
TL
165 out << g_conf()->name << " releasing free RAM back to system.";
166 } else if (cmd.size() == 1 && cmd[0] == "get_release_rate") {
167 out << g_conf()->name << " release rate: "
168 << std::setprecision(4) << ceph_heap_get_release_rate() << "\n";
169 } else if (cmd.size() == 2 && cmd[0] == "set_release_rate") {
170 try {
171 double val = std::stod(cmd[1]);
172 ceph_heap_set_release_rate(val);
173 out << g_conf()->name << " release rate changed to: "
174 << std::setprecision(4) << ceph_heap_get_release_rate() << "\n";
175 } catch (...) {
176 out << g_conf()->name << " *** need an numerical value. ";
177 }
7c673cae
FG
178 } else
179#endif
180 if (cmd.size() == 1 && cmd[0] == "stats") {
181 char heap_stats[HEAP_PROFILER_STATS_SIZE];
182 ceph_heap_profiler_stats(heap_stats, sizeof(heap_stats));
11fdf7f2 183 out << g_conf()->name << " tcmalloc heap stats:"
7c673cae
FG
184 << heap_stats;
185 } else {
186 out << "unknown command " << cmd;
187 }
188}