Skip to content

Commit

Permalink
[opt](cpu-profile) enable cpu profile in BE webui (apache#40330)
Browse files Browse the repository at this point in the history
Visit `be_ip:webserver_port/cpu`
You can get cpu profile like this:
<img width="736" alt="image"
src="https://github.com/user-attachments/assets/05da73ca-c02a-4ec3-a2fb-83ef80ff9553">

or

![img_v3_02ec_e8d45934-ddaf-45de-818e-a7e4899ec7cg](https://github.com/user-attachments/assets/6b1a4e15-a219-456b-9d1f-e3be88177db5)
  • Loading branch information
morningman authored Sep 5, 2024
1 parent 4b6881f commit 16e3c78
Show file tree
Hide file tree
Showing 12 changed files with 1,818 additions and 52 deletions.
1 change: 1 addition & 0 deletions .licenserc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,5 @@ header:
- "pytest/sys/data"
- "pytest/deploy/*.conf"
- "tools/jeprof"
- "tools/FlameGraph/*"
comment: on-failure
10 changes: 9 additions & 1 deletion LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -725,4 +725,12 @@ Apache 2.0, Copyright 2023 SAP SE or an SAP affiliate company, Johannes Bechberg

This project is maintained by the SapMachine team at SAP SE

----------------------------------------------------------------------------------
----------------------------------------------------------------------------------

be/tools/FlameGraph/*.pl: COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0

Unless otherwise noted, all files in this distribution are released
under the Common Development and Distribution License (CDDL).
Exceptions are noted within the associated source files.

----------------------------------------------------------------------------------
11 changes: 7 additions & 4 deletions be/src/http/action/pprof_actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
!defined(THREAD_SANITIZER) && !defined(USE_JEMALLOC)
#include <gperftools/heap-profiler.h> // IWYU pragma: keep
#include <gperftools/malloc_extension.h> // IWYU pragma: keep
#include <gperftools/profiler.h> // IWYU pragma: keep
#endif
#if !defined(__SANITIZE_ADDRESS__) && !defined(ADDRESS_SANITIZER) && !defined(LEAK_SANITIZER) && \
!defined(THREAD_SANITIZER)
#include <gperftools/profiler.h> // IWYU pragma: keep
#endif
#include <stdio.h>

Expand Down Expand Up @@ -141,8 +144,7 @@ class ProfileAction : public HttpHandlerWithAuth {
};

void ProfileAction::handle(HttpRequest* req) {
#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || defined(THREAD_SANITIZER) || \
defined(USE_JEMALLOC)
#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || defined(THREAD_SANITIZER)
std::string str = "CPU profiling is not available with address sanitizer or jemalloc builds.";
HttpChannel::send_reply(req, str);
#else
Expand Down Expand Up @@ -178,6 +180,7 @@ void ProfileAction::handle(HttpRequest* req) {
prof_file.close();
std::string str = ss.str();
HttpChannel::send_reply(req, str);
return;
}

// text type. we will return readable content via http response
Expand All @@ -193,7 +196,7 @@ void ProfileAction::handle(HttpRequest* req) {
std::string svg_file_content;
std::string flamegraph_install_dir =
std::string(std::getenv("DORIS_HOME")) + "/tools/FlameGraph/";
Status st = PprofUtils::generate_flamegraph(30, flamegraph_install_dir, false,
Status st = PprofUtils::generate_flamegraph(seconds, flamegraph_install_dir, false,
&svg_file_content);
if (!st.ok()) {
HttpChannel::send_reply(req, st.to_string());
Expand Down
21 changes: 9 additions & 12 deletions be/src/http/default_path_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,7 @@ void heap_handler(const WebPageHandler::ArgumentMap& args, std::stringstream* ou
void cpu_handler(const WebPageHandler::ArgumentMap& args, std::stringstream* output) {
(*output) << "<h2>CPU Profile</h2>" << std::endl;

#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || defined(THREAD_SANITIZER) || \
defined(USE_JEMALLOC)
#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || defined(THREAD_SANITIZER)
(*output) << "<pre>" << std::endl;
(*output) << "CPU profiling is not available with address sanitizer builds." << std::endl;
(*output) << "</pre>" << std::endl;
Expand Down Expand Up @@ -315,7 +314,8 @@ void cpu_handler(const WebPageHandler::ArgumentMap& args, std::stringstream* out
<< std::endl;
(*output) << "And you need to download the FlameGraph and place it under 'be/tools/FlameGraph'."
<< std::endl;
(*output) << "Finally, check if the following files exist" << std::endl;
(*output) << "Finally, check if the following files exist. And should be executable."
<< std::endl;
(*output) << std::endl;
(*output) << " be/tools/FlameGraph/stackcollapse-perf.pl" << std::endl;
(*output) << " be/tools/FlameGraph/flamegraph.pl" << std::endl;
Expand All @@ -335,9 +335,6 @@ void cpu_handler(const WebPageHandler::ArgumentMap& args, std::stringstream* out
<< std::endl;
(*output) << " <br/>" << std::endl;
(*output) << " <div id=\"cpuResult\"><pre id=\"cpuContent\"></pre></div>" << std::endl;
(*output) << " <br/>" << std::endl;
(*output) << " <div id=\"cpuResultGraph\"><pre id=\"cpuContentGraph\"></pre></div>"
<< std::endl;
(*output) << "</div>" << std::endl;

// for text profile
Expand All @@ -350,36 +347,36 @@ void cpu_handler(const WebPageHandler::ArgumentMap& args, std::stringstream* out
(*output) << " type: \"GET\"," << std::endl;
(*output) << " dataType: \"text\"," << std::endl;
(*output) << " url: \"pprof/profile?type=text\"," << std::endl;
(*output) << " timeout: 60000," << std::endl;
(*output) << " timeout: 120000," << std::endl;
(*output) << " success: function (result) {" << std::endl;
(*output) << " document.getElementById(\"cpuContent\").innerText = result;"
<< std::endl;
(*output) << " }" << std::endl;
(*output) << " ," << std::endl;
(*output) << " error: function (result) {" << std::endl;
(*output) << " alert(result);" << std::endl;
(*output) << " alert(JSON.stringify(result));" << std::endl;
(*output) << " }" << std::endl;
(*output) << " ," << std::endl;
(*output) << " });" << std::endl;
(*output) << "});" << std::endl;

// for graph profile
(*output) << "$('#getCpuGraph').click(function () {" << std::endl;
(*output) << " document.getElementById(\"cpuContentGraph\").innerText = \"Sampling... (30 "
(*output) << " document.getElementById(\"cpuContent\").innerText = \"Sampling... (30 "
"seconds)\";"
<< std::endl;
(*output) << " $.ajax({" << std::endl;
(*output) << " type: \"GET\"," << std::endl;
(*output) << " dataType: \"text\"," << std::endl;
(*output) << " url: \"pprof/profile?type=flamegraph\"," << std::endl;
(*output) << " timeout: 60000," << std::endl;
(*output) << " timeout: 120000," << std::endl;
(*output) << " success: function (result) {" << std::endl;
(*output) << " document.getElementById(\"cpuResultGraph\").innerHTML = result;"
(*output) << " document.getElementById(\"cpuContent\").innerHTML = result;"
<< std::endl;
(*output) << " }" << std::endl;
(*output) << " ," << std::endl;
(*output) << " error: function (result) {" << std::endl;
(*output) << " alert(result);" << std::endl;
(*output) << " alert(JSON.stringify(result));" << std::endl;
(*output) << " }" << std::endl;
(*output) << " ," << std::endl;
(*output) << " });" << std::endl;
Expand Down
4 changes: 4 additions & 0 deletions be/src/util/pprof_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ Status PprofUtils::get_readable_profile(const std::string& file_or_content, bool
std::string final_cmd =
pprof_cmd + strings::Substitute(" --text $0 $1", self_cmdline, final_file);
AgentUtils util;
LOG(INFO) << "begin to run command: " << final_cmd;
bool rc = util.exec_cmd(final_cmd, &cmd_output, false);

// delete raw file
Expand Down Expand Up @@ -158,6 +159,7 @@ Status PprofUtils::generate_flamegraph(int32_t sample_seconds,

AgentUtils util;
std::string cmd_output;
LOG(INFO) << "begin to run command: " << cmd.str();
bool rc = util.exec_cmd(cmd.str(), &cmd_output);
if (!rc) {
static_cast<void>(io::global_local_filesystem()->delete_file(tmp_file.str()));
Expand All @@ -174,6 +176,7 @@ Status PprofUtils::generate_flamegraph(int32_t sample_seconds,
std::stringstream gen_cmd;
gen_cmd << perf_cmd << " script -i " << tmp_file.str() << " | " << stackcollapse_perf_pl
<< " | " << flamegraph_pl << " > " << graph_file.str();
LOG(INFO) << "begin to run command: " << gen_cmd.str();
rc = util.exec_cmd(gen_cmd.str(), &res_content);
if (!rc) {
static_cast<void>(io::global_local_filesystem()->delete_file(tmp_file.str()));
Expand All @@ -185,6 +188,7 @@ Status PprofUtils::generate_flamegraph(int32_t sample_seconds,
std::stringstream gen_cmd;
gen_cmd << perf_cmd << " script -i " << tmp_file.str() << " | " << stackcollapse_perf_pl
<< " | " << flamegraph_pl;
LOG(INFO) << "begin to run command: " << gen_cmd.str();
rc = util.exec_cmd(gen_cmd.str(), &res_content, false);
if (!rc) {
static_cast<void>(io::global_local_filesystem()->delete_file(tmp_file.str()));
Expand Down
2 changes: 1 addition & 1 deletion be/src/vec/exec/scan/vfile_scanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,7 @@ Status VFileScanner::_get_next_reader() {
std::unique_ptr<ParquetReader> parquet_reader = ParquetReader::create_unique(
_profile, *_params, range, _state->query_options().batch_size,
const_cast<cctz::time_zone*>(&_state->timezone_obj()), _io_ctx.get(), _state,
_shoudl_enable_file_meta_cache() ? ExecEnv::GetInstance()->file_meta_cache()
_should_enable_file_meta_cache() ? ExecEnv::GetInstance()->file_meta_cache()
: nullptr,
_state->query_options().enable_parquet_lazy_mat);
{
Expand Down
2 changes: 1 addition & 1 deletion be/src/vec/exec/scan/vfile_scanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ class VFileScanner : public VScanner {
// 1. max_external_file_meta_cache_num is > 0
// 2. the file number is less than 1/3 of cache's capacibility
// Otherwise, the cache miss rate will be high
bool _shoudl_enable_file_meta_cache() {
bool _should_enable_file_meta_cache() {
return config::max_external_file_meta_cache_num > 0 &&
_split_source->num_scan_ranges() < config::max_external_file_meta_cache_num / 3;
}
Expand Down
4 changes: 3 additions & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,8 @@ if [[ "${OUTPUT_BE_BINARY}" -eq 1 ]]; then
install -d "${DORIS_OUTPUT}/be/bin" \
"${DORIS_OUTPUT}/be/conf" \
"${DORIS_OUTPUT}/be/lib" \
"${DORIS_OUTPUT}/be/www"
"${DORIS_OUTPUT}/be/www" \
"${DORIS_OUTPUT}/be/tools/FlameGraph"

cp -r -p "${DORIS_HOME}/be/output/bin"/* "${DORIS_OUTPUT}/be/bin"/
cp -r -p "${DORIS_HOME}/be/output/conf"/* "${DORIS_OUTPUT}/be/conf"/
Expand Down Expand Up @@ -801,6 +802,7 @@ EOF
fi

cp -r -p "${DORIS_HOME}/webroot/be"/* "${DORIS_OUTPUT}/be/www"/
cp -r -p "${DORIS_HOME}/tools/FlameGraph"/* "${DORIS_OUTPUT}/be/tools/FlameGraph"/
if [[ "${STRIP_DEBUG_INFO}" = "ON" ]]; then
cp -r -p "${DORIS_HOME}/be/output/lib/debug_info" "${DORIS_OUTPUT}/be/lib"/
fi
Expand Down
65 changes: 33 additions & 32 deletions dist/LICENSE-dist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1503,35 +1503,36 @@ LGPL -- licenes/LICENSE-LGPL.txt
* gsasl: 1.10.0/1.8.0

Other dependencies:
* libevent: 2.1.12 -- license/LICENSE-libevent.txt
* openssl: 1.1.1s -- license/LICENSE-openssl.txt
* gflag: 2.2.2 -- license/LICENSE-gflag.txt
* glog: 0.4.0 -- license/LICENSE-glog.txt
* gtest: 1.11.0 -- license/LICENSE-gtest.txt
* snappy: 1.1.8 -- license/LICENSE-snappy.txt
* gperftools: 2.9.1 -- license/LICENSE-gperftools.txt
* zlib: 1.2.11 -- license/LICENSE-zlib.txt
* lz4: 1.9.3 -- license/LICENSE-lz4.txt
* bzip2: 1.0.8 -- license/LICENSE-bzip2.txt
* rapidjson@1a803826 -- license/LICENSE-rapidjson.txt
* curl: 7.79.0 -- license/LICENSE-curl.txt
* re2: 2021-02-02 -- license/LICENSE-re2.txt
* hyperscan: 5.4.0 -- license/LICENSE-hyperscan.txt
* vectorscan: 5.4.7 -- license/LICENSE-vectorscan.txt
* boost: 1.73.0 -- license/LICENSE-boost.txt
* unixodbc: 2.3.7 -- license/LICENSE-unixodbc.txt
* leveldb: 1.23 -- license/LICENSE-leveldb.txt
* cyrus-sasl: 2.1.27 -- license/LICENSE-cyrus-sasl.txt
* librdkafka: 1.8.2 -- license/LICENSE-librdkafka.txt
* zstd: 1.5.2 -- license/LICENSE-zstd.txt
* brotli: 1.0.9 -- license/LICENSE-brotli.txt
* bitshuffle: 0.5.1 -- license/LICENSE-bigshuffle.txt
* fmt: 7.1.3 -- license/LICENSE-fmt.txt
* jemalloc: 5.3.0 -- license/LICENSE-jemolloc.txt
* lzma@master -- license/LICENSE-lzma.txt
* libdivide: 5.0 -- license/LICENSE-libdivide.txt
* pdqsort: 0.0.0+git20180419 -- license/LICENSE-pdqsort.txt
* breakpad@38ee0be -- license/LICENSE-breakpod.txt
* xsimd: xmid@e9234cd6 -- license/LICENSE-xsimd.txt
* xxhash: 0.8.1 -- license/LICENSE-xxhash.txt
* concurrentqueue: 1.0.3 -- license/LICENSE-concurrentqueue.txt
* libevent: 2.1.12 -- licenses/LICENSE-libevent.txt
* openssl: 1.1.1s -- licenses/LICENSE-openssl.txt
* gflag: 2.2.2 -- licenses/LICENSE-gflag.txt
* glog: 0.4.0 -- licenses/LICENSE-glog.txt
* gtest: 1.11.0 -- licenses/LICENSE-gtest.txt
* snappy: 1.1.8 -- licenses/LICENSE-snappy.txt
* gperftools: 2.9.1 -- licenses/LICENSE-gperftools.txt
* zlib: 1.2.11 -- licenses/LICENSE-zlib.txt
* lz4: 1.9.3 -- licenses/LICENSE-lz4.txt
* bzip2: 1.0.8 -- licenses/LICENSE-bzip2.txt
* rapidjson@1a803826 -- licenses/LICENSE-rapidjson.txt
* curl: 7.79.0 -- licenses/LICENSE-curl.txt
* re2: 2021-02-02 -- licenses/LICENSE-re2.txt
* hyperscan: 5.4.0 -- licenses/LICENSE-hyperscan.txt
* vectorscan: 5.4.7 -- licenses/LICENSE-vectorscan.txt
* boost: 1.73.0 -- licenses/LICENSE-boost.txt
* unixodbc: 2.3.7 -- licenses/LICENSE-unixodbc.txt
* leveldb: 1.23 -- licenses/LICENSE-leveldb.txt
* cyrus-sasl: 2.1.27 -- licenses/LICENSE-cyrus-sasl.txt
* librdkafka: 1.8.2 -- licenses/LICENSE-librdkafka.txt
* zstd: 1.5.2 -- licenses/LICENSE-zstd.txt
* brotli: 1.0.9 -- licenses/LICENSE-brotli.txt
* bitshuffle: 0.5.1 -- licenses/LICENSE-bigshuffle.txt
* fmt: 7.1.3 -- licenses/LICENSE-fmt.txt
* jemalloc: 5.3.0 -- licenses/LICENSE-jemolloc.txt
* lzma@master -- licenses/LICENSE-lzma.txt
* libdivide: 5.0 -- licenses/LICENSE-libdivide.txt
* pdqsort: 0.0.0+git20180419 -- licenses/LICENSE-pdqsort.txt
* breakpad@38ee0be -- licenses/LICENSE-breakpod.txt
* xsimd: xmid@e9234cd6 -- licenses/LICENSE-xsimd.txt
* xxhash: 0.8.1 -- licenses/LICENSE-xxhash.txt
* concurrentqueue: 1.0.3 -- licenses/LICENSE-concurrentqueue.txt
* FlameGraph -- licenses/LICENSE-CDDL-1.0.txt
13 changes: 13 additions & 0 deletions tools/FlameGraph/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
These 2 files:

- flamegraph.pl
- stackcollapse-perf.pl

are copied from:

https://github.com/brendangregg/FlameGraph/blob/master/flamegraph.pl
https://github.com/brendangregg/FlameGraph/blob/master/stackcollapse-perf.pl

which are under license:

https://github.com/brendangregg/FlameGraph/blob/master/docs/cddl1.txt
Loading

0 comments on commit 16e3c78

Please sign in to comment.