Skip to content

Commit 28dd7a3

Browse files
authored
feat: add explain perf support for query performance analysis (#18251)
* feat: add query level flamegraph generation * chore: pprof-rs * chore: remove `analyze` and split to an interpreter * chore: refine file structure * refactor: use TrackingPayload manage thread local flag
1 parent 646f7ef commit 28dd7a3

33 files changed

+672
-29
lines changed

Cargo.lock

Lines changed: 51 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ petgraph = { version = "0.6.2", features = ["serde-1"] }
432432
pin-project = "1"
433433
pin-project-lite = "0.2.9"
434434
poem = { version = "3.0", features = ["openssl-tls", "multipart", "compression", "cookie"] }
435-
pprof = { version = "0.14.0", features = [
435+
pprof = { git = "https://github.com/datafuse-extras/pprof-rs", rev = "fe22b23", features = [
436436
"flamegraph",
437437
"protobuf-codec",
438438
"protobuf",

licenserc.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ excludes = [
4141
"**/*.yapf",
4242
"**/*.test",
4343
"**/*.txt",
44+
"**/*.html"
4445
]
4546

4647
[properties]

src/common/base/src/base/profiling.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ impl Profiling {
3232
}
3333

3434
pub async fn report(&self) -> Result<pprof::Report> {
35-
let guard = pprof::ProfilerGuard::new(self.frequency)
35+
let guard = pprof::ProfilerGuardBuilder::default()
36+
.frequency(self.frequency)
37+
.blocklist(&["libc", "libgcc", "pthread", "vdso"])
38+
.build()
3639
.map_err(|e| ErrorCode::UnknownException(e.to_string()))?;
3740
tokio::time::sleep(self.duration).await;
3841
guard

src/common/base/src/runtime/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub mod error_info;
1919
mod global_runtime;
2020
mod memory;
2121
pub mod metrics;
22+
mod perf;
2223
pub mod profile;
2324
#[allow(clippy::module_inception)]
2425
mod runtime;
@@ -44,6 +45,8 @@ pub use memory::OutOfLimit;
4445
pub use memory::ParentMemStat;
4546
pub use memory::GLOBAL_MEM_STAT;
4647
pub use memory::GLOBAL_QUERIES_MANAGER;
48+
pub use perf::QueryPerf;
49+
pub use perf::QueryPerfGuard;
4750
pub use runtime::block_on;
4851
pub use runtime::execute_futures_in_parallel;
4952
pub use runtime::spawn;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Flamegraph</title>
6+
<style>body {
7+
margin: 0;
8+
padding: 0;
9+
overflow: hidden;
10+
}</style>
11+
</head>
12+
<body>
13+
{{SVG_CONTENT}}
14+
</body>
15+
</html>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Query Performance Flamegraphs</title>
6+
<style>
7+
body {
8+
font-family: Arial, sans-serif;
9+
margin: 20px;
10+
background-color: #f5f5f5;
11+
}
12+
13+
.flamegraph-container {
14+
/* --- Start of centering rules --- */
15+
max-width: 1200px; /* Set a max width for the container */
16+
margin-left: auto; /* Automatically calculate left margin */
17+
margin-right: auto; /* Automatically calculate right margin */
18+
/* --- End of centering rules --- */
19+
20+
margin-bottom: 30px;
21+
background-color: white;
22+
border-radius: 8px;
23+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
24+
overflow: hidden;
25+
}
26+
27+
.flamegraph-header {
28+
background-color: #4a90e2;
29+
color: white;
30+
padding: 15px;
31+
font-size: 18px;
32+
font-weight: bold;
33+
}
34+
35+
.flamegraph-content iframe {
36+
width: 100%;
37+
border: none;
38+
display: block;
39+
}
40+
</style>
41+
</head>
42+
<body>
43+
<h1>Query Performance Flamegraphs</h1>
44+
45+
{{CURRENT_NODE_IFRAME}}
46+
47+
{{OTHER_NODES_IFRAMES}}
48+
49+
<script>
50+
function resizeIframe(iframe) {
51+
// A small delay can help ensure the content has been fully rendered
52+
// before calculating its height, especially for complex SVGs.
53+
setTimeout(() => {
54+
try {
55+
const body = iframe.contentWindow.document.body;
56+
const svg = body.querySelector('svg');
57+
if (svg) {
58+
iframe.style.height = svg.scrollHeight + 'px';
59+
} else if (body && body.scrollHeight > 0) {
60+
iframe.style.height = body.scrollHeight + 'px';
61+
}
62+
} catch (e) {
63+
console.error("Failed to resize iframe:", e);
64+
}
65+
}, 150);
66+
}
67+
</script>
68+
</body>
69+
</html>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2021 Datafuse Labs
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
mod query_perf;
16+
17+
pub use query_perf::QueryPerf;
18+
pub use query_perf::QueryPerfGuard;

0 commit comments

Comments
 (0)