be/src/runtime/be_proc_monitor.cpp
Line | Count | Source |
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 "runtime/be_proc_monitor.h" |
19 | | |
20 | | #include <fmt/format.h> |
21 | | #include <glog/logging.h> |
22 | | #include <sys/stat.h> |
23 | | #include <unistd.h> |
24 | | |
25 | | #include <deque> |
26 | | #include <filesystem> |
27 | | #include <fstream> |
28 | | #include <map> |
29 | | #include <nlohmann/json.hpp> |
30 | | |
31 | 34 | std::string BeProcMonitor::get_be_thread_info() { |
32 | 34 | int32_t pid = getpid(); |
33 | 34 | std::string proc_path = fmt::format("/proc/{}/task", pid); |
34 | 34 | if (access(proc_path.c_str(), F_OK) != 0) { |
35 | 0 | LOG(WARNING) << "be proc path " << proc_path << " not exists."; |
36 | 0 | return ""; |
37 | 0 | } |
38 | | |
39 | 34 | std::map<std::string, int> thread_num_map; |
40 | | |
41 | 34 | int total_thread_count = 0; |
42 | 34 | int distinct_thread_name_count = 0; |
43 | 89.5k | for (const auto& entry : std::filesystem::directory_iterator(proc_path)) { |
44 | 89.5k | const std::string tid_path = entry.path().string(); |
45 | 89.5k | std::string thread_name_path = tid_path + "/comm"; |
46 | 89.5k | struct stat st; |
47 | | // == 0 means exists |
48 | 89.5k | if (stat(thread_name_path.c_str(), &st) == 0) { |
49 | | // NOTE: there is no need to close std::ifstream, it's called during deconstruction. |
50 | | // refer:https://stackoverflow.com/questions/748014/do-i-need-to-manually-close-an-ifstream |
51 | 89.5k | std::ifstream file(thread_name_path.c_str()); |
52 | 89.5k | if (!file.is_open()) { |
53 | 0 | continue; |
54 | 0 | } |
55 | 89.5k | std::stringstream str_buf; |
56 | 89.5k | str_buf << file.rdbuf(); |
57 | 89.5k | std::string thread_name = str_buf.str(); |
58 | 89.5k | thread_name.erase(std::remove(thread_name.begin(), thread_name.end(), '\n'), |
59 | 89.5k | thread_name.end()); |
60 | | |
61 | 89.5k | if (thread_num_map.find(thread_name) != thread_num_map.end()) { |
62 | 85.4k | thread_num_map[thread_name]++; |
63 | 85.4k | } else { |
64 | 4.10k | distinct_thread_name_count++; |
65 | 4.10k | thread_num_map.emplace(thread_name, 1); |
66 | 4.10k | } |
67 | 89.5k | total_thread_count++; |
68 | 89.5k | } |
69 | 89.5k | } |
70 | | |
71 | 34 | std::deque<std::pair<std::string, int>> ordered_list(thread_num_map.begin(), |
72 | 34 | thread_num_map.end()); |
73 | 34 | std::sort(ordered_list.begin(), ordered_list.end(), |
74 | 24.8k | [](const auto& lhs, const auto& rhs) { return lhs.second > rhs.second; }); |
75 | | |
76 | 34 | ordered_list.push_front( |
77 | 34 | std::make_pair("distinct_thread_name_count", distinct_thread_name_count)); |
78 | 34 | ordered_list.push_front(std::make_pair("total_thread_count", total_thread_count)); |
79 | 34 | ordered_list.push_front(std::make_pair("be_process_id", pid)); |
80 | | |
81 | 34 | nlohmann::json js = nlohmann::json::array(); |
82 | 4.20k | for (const auto& p : ordered_list) { |
83 | 4.20k | js.push_back({p.first, p.second}); |
84 | 4.20k | } |
85 | | |
86 | 34 | std::string output_json_str = js.dump(); |
87 | 34 | return output_json_str; |
88 | 34 | } |