Skip to content

Commit df69b95

Browse files
authored
Support memory builtin service (#2505)
* Support TCMalloc builtin service * Support memory service
1 parent 313258e commit df69b95

File tree

8 files changed

+154
-1
lines changed

8 files changed

+154
-1
lines changed

src/brpc/builtin/index_service.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ void IndexService::default_method(::google::protobuf::RpcController* controller,
165165
<< Path("/threads", html_addr) << " : Check pstack"
166166
<< (!FLAGS_enable_threads_service ? " (disabled)" : "") << NL
167167
<< Path("/dir", html_addr) << " : Browse directories and files"
168-
<< (!FLAGS_enable_dir_service ? " (disabled)" : "") << NL;
168+
<< (!FLAGS_enable_dir_service ? " (disabled)" : "") << NL
169+
<< Path("/memory", html_addr) << " : Get malloc allocator information" << NL;
169170
if (use_html) {
170171
os << "</body></html>";
171172
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
#include "butil/time.h"
19+
#include "butil/logging.h"
20+
#include "brpc/controller.h" // Controller
21+
#include "brpc/closure_guard.h" // ClosureGuard
22+
#include "brpc/builtin/memory_service.h"
23+
#include "brpc/details/tcmalloc_extension.h"
24+
25+
namespace brpc {
26+
27+
DEFINE_int32(max_tc_stats_buf_len, 32 * 1024, "max length of TCMalloc stats");
28+
BRPC_VALIDATE_GFLAG(max_tc_stats_buf_len, PositiveInteger);
29+
30+
static inline void get_tcmalloc_num_prop(MallocExtension* malloc_ext,
31+
const char* prop_name,
32+
butil::IOBufBuilder& os) {
33+
size_t value;
34+
if (malloc_ext->GetNumericProperty(prop_name, &value)) {
35+
os << prop_name << ": " << value << "\n";
36+
}
37+
}
38+
39+
static void get_tcmalloc_memory_info(butil::IOBuf& out) {
40+
MallocExtension* malloc_ext = MallocExtension::instance();
41+
butil::IOBufBuilder os;
42+
os << "------------------------------------------------\n";
43+
get_tcmalloc_num_prop(malloc_ext, "generic.total_physical_bytes", os);
44+
get_tcmalloc_num_prop(malloc_ext, "generic.current_allocated_bytes", os);
45+
get_tcmalloc_num_prop(malloc_ext, "generic.heap_size", os);
46+
get_tcmalloc_num_prop(malloc_ext, "tcmalloc.current_total_thread_cache_bytes", os);
47+
get_tcmalloc_num_prop(malloc_ext, "tcmalloc.central_cache_free_bytes", os);
48+
get_tcmalloc_num_prop(malloc_ext, "tcmalloc.transfer_cache_free_bytes", os);
49+
get_tcmalloc_num_prop(malloc_ext, "tcmalloc.thread_cache_free_bytes", os);
50+
get_tcmalloc_num_prop(malloc_ext, "tcmalloc.pageheap_free_bytes", os);
51+
get_tcmalloc_num_prop(malloc_ext, "tcmalloc.pageheap_unmapped_bytes", os);
52+
53+
int32_t len = FLAGS_max_tc_stats_buf_len;
54+
std::unique_ptr<char[]> buf(new char[len]);
55+
malloc_ext->GetStats(buf.get(), len);
56+
os << buf.get();
57+
58+
os.move_to(out);
59+
}
60+
61+
void MemoryService::default_method(::google::protobuf::RpcController* cntl_base,
62+
const ::brpc::MemoryRequest*,
63+
::brpc::MemoryResponse*,
64+
::google::protobuf::Closure* done) {
65+
ClosureGuard done_guard(done);
66+
auto cntl = static_cast<Controller*>(cntl_base);
67+
cntl->http_response().set_content_type("text/plain");
68+
butil::IOBuf& resp = cntl->response_attachment();
69+
70+
if (IsTCMallocEnabled()) {
71+
butil::IOBufBuilder os;
72+
get_tcmalloc_memory_info(resp);
73+
} else {
74+
resp.append("tcmalloc is not enabled");
75+
cntl->http_response().set_status_code(HTTP_STATUS_FORBIDDEN);
76+
return;
77+
}
78+
}
79+
80+
} // namespace brpc

src/brpc/builtin/memory_service.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
#ifndef BRPC_MALLOC_SERVICE_H
19+
#define BRPC_MALLOC_SERVICE_H
20+
21+
#include "brpc/builtin_service.pb.h"
22+
23+
namespace brpc {
24+
25+
class MemoryService : public memory {
26+
public:
27+
void default_method(::google::protobuf::RpcController* cntl_base,
28+
const ::brpc::MemoryRequest* request,
29+
::brpc::MemoryResponse* response,
30+
::google::protobuf::Closure* done) override;
31+
};
32+
33+
} // namespace brpc
34+
35+
36+
#endif // BRPC_MALLOC_SERVICE_H

src/brpc/builtin_service.proto

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ message VLogRequest {}
6161
message VLogResponse {}
6262
message MetricsRequest {}
6363
message MetricsResponse {}
64+
message MemoryRequest {}
65+
message MemoryResponse {}
6466
message BadMethodRequest {
6567
required string service_name = 1;
6668
}
@@ -169,3 +171,7 @@ service rpcz {
169171
service dir {
170172
rpc default_method(DirRequest) returns (DirResponse);
171173
}
174+
175+
service memory {
176+
rpc default_method(MemoryRequest) returns (MemoryResponse);
177+
}

src/brpc/details/tcmalloc_extension.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ bool IsHeapProfilerEnabled() {
5050
return MallocExtension::instance() != NULL;
5151
}
5252

53+
bool IsTCMallocEnabled() {
54+
return IsHeapProfilerEnabled();
55+
}
56+
5357
static bool check_TCMALLOC_SAMPLE_PARAMETER() {
5458
char* str = getenv("TCMALLOC_SAMPLE_PARAMETER");
5559
if (str == NULL) {

src/brpc/details/tcmalloc_extension.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,5 +315,7 @@ class PERFTOOLS_DLL_DECL MallocExtension {
315315
// True iff heap profiler is enabled.
316316
bool IsHeapProfilerEnabled();
317317

318+
bool IsTCMallocEnabled();
319+
318320
// True iff TCMALLOC_SAMPLE_PARAMETER is set in environment.
319321
bool has_TCMALLOC_SAMPLE_PARAMETER();

src/brpc/server.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
#include "brpc/builtin/sockets_service.h" // SocketsService
6666
#include "brpc/builtin/hotspots_service.h" // HotspotsService
6767
#include "brpc/builtin/prometheus_metrics_service.h"
68+
#include "brpc/builtin/memory_service.h"
6869
#include "brpc/details/method_status.h"
6970
#include "brpc/load_balancer.h"
7071
#include "brpc/naming_service.h"
@@ -528,6 +529,10 @@ int Server::AddBuiltinServices() {
528529
LOG(ERROR) << "Fail to add ThreadsService";
529530
return -1;
530531
}
532+
if (AddBuiltinService(new (std::nothrow) MemoryService)) {
533+
LOG(ERROR) << "Fail to add MemoryService";
534+
return -1;
535+
}
531536

532537
#if !BRPC_WITH_GLOG
533538
if (AddBuiltinService(new (std::nothrow) VLogService)) {

test/brpc_builtin_service_unittest.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "brpc/builtin/bthreads_service.h" // BthreadsService
5151
#include "brpc/builtin/ids_service.h" // IdsService
5252
#include "brpc/builtin/sockets_service.h" // SocketsService
53+
#include "brpc/builtin/memory_service.h"
5354
#include "brpc/builtin/common.h"
5455
#include "brpc/builtin/bad_method_service.h"
5556
#include "echo.pb.h"
@@ -902,3 +903,21 @@ TEST_F(BuiltinServiceTest, sockets) {
902903
CheckContent(cntl, "fd=-1");
903904
}
904905
}
906+
907+
TEST_F(BuiltinServiceTest, memory) {
908+
brpc::MemoryService service;
909+
brpc::MemoryRequest req;
910+
brpc::MemoryResponse res;
911+
brpc::Controller cntl;
912+
ClosureChecker done;
913+
service.default_method(&cntl, &req, &res, &done);
914+
EXPECT_FALSE(cntl.Failed());
915+
CheckContent(cntl, "generic.current_allocated_bytes");
916+
CheckContent(cntl, "generic.heap_size");
917+
CheckContent(cntl, "tcmalloc.current_total_thread_cache_bytes");
918+
CheckContent(cntl, "tcmalloc.central_cache_free_bytes");
919+
CheckContent(cntl, "tcmalloc.transfer_cache_free_bytes");
920+
CheckContent(cntl, "tcmalloc.thread_cache_free_bytes");
921+
CheckContent(cntl, "tcmalloc.pageheap_free_bytes");
922+
CheckContent(cntl, "tcmalloc.pageheap_unmapped_bytes");
923+
}

0 commit comments

Comments
 (0)