Skip to content

Commit e386a36

Browse files
v0y4g3rshuiyisong
andauthored
feat: add HTTP endpoint to control prof.gdump feature (#6999)
* feat/gdump: ### Add Support for Jemalloc Gdump Flag - **`jemalloc.rs`**: Introduced `PROF_GDUMP` constant and added functions `set_gdump_active` and `is_gdump_active` to manage the gdump flag. - **`error.rs`**: Added error handling for reading and updating the jemalloc gdump flag with `ReadGdump` and `UpdateGdump` errors. - **`lib.rs`**: Exposed `is_gdump_active` and `set_gdump_active` functions for non-Windows platforms. - **`http.rs`**: Added HTTP routes for checking and toggling the jemalloc gdump flag status. - **`mem_prof.rs`**: Implemented handlers `gdump_toggle_handler` and `gdump_status_handler` for managing gdump flag via HTTP requests. Signed-off-by: Lei, HUANG <[email protected]> * Update docs/how-to/how-to-profile-memory.md Co-authored-by: shuiyisong <[email protected]> * fix: typo in docs Signed-off-by: Lei, HUANG <[email protected]> --------- Signed-off-by: Lei, HUANG <[email protected]> Co-authored-by: shuiyisong <[email protected]>
1 parent d8563ba commit e386a36

File tree

6 files changed

+109
-1
lines changed

6 files changed

+109
-1
lines changed

docs/how-to/how-to-profile-memory.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ curl -X POST localhost:4000/debug/prof/mem/activate
7171

7272
# Deactivate heap profiling
7373
curl -X POST localhost:4000/debug/prof/mem/deactivate
74+
75+
# Activate gdump feature that dumps memory profiling data every time virtual memory usage exceeds previous maximum value.
76+
curl -X POST localhost:4000/debug/prof/mem/gdump -d 'activate=true'
77+
78+
# Deactivate gdump.
79+
curl -X POST localhost:4000/debug/prof/mem/gdump -d 'activate=false'
80+
81+
# Retrieve current gdump status.
82+
curl -X GET localhost:4000/debug/prof/mem/gdump
7483
```
7584

7685
### Dump memory profiling data

src/common/mem-prof/src/jemalloc.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use crate::error::{FlamegraphSnafu, ParseJeHeapSnafu, Result};
3232
const PROF_DUMP: &[u8] = b"prof.dump\0";
3333
const OPT_PROF: &[u8] = b"opt.prof\0";
3434
const PROF_ACTIVE: &[u8] = b"prof.active\0";
35+
const PROF_GDUMP: &[u8] = b"prof.gdump\0";
3536

3637
pub async fn dump_profile() -> Result<Vec<u8>> {
3738
ensure!(is_prof_enabled()?, ProfilingNotEnabledSnafu);
@@ -119,3 +120,16 @@ fn is_prof_enabled() -> Result<bool> {
119120
// safety: OPT_PROF variable, if present, is always a boolean value.
120121
Ok(unsafe { tikv_jemalloc_ctl::raw::read::<bool>(OPT_PROF).context(ReadOptProfSnafu)? })
121122
}
123+
124+
pub fn set_gdump_active(active: bool) -> Result<()> {
125+
ensure!(is_prof_enabled()?, ProfilingNotEnabledSnafu);
126+
unsafe {
127+
tikv_jemalloc_ctl::raw::update(PROF_GDUMP, active).context(error::UpdateGdumpSnafu)?;
128+
}
129+
Ok(())
130+
}
131+
132+
pub fn is_gdump_active() -> Result<bool> {
133+
// safety: PROF_GDUMP, if present, is a boolean value.
134+
unsafe { Ok(tikv_jemalloc_ctl::raw::read::<bool>(PROF_GDUMP).context(error::ReadGdumpSnafu)?) }
135+
}

src/common/mem-prof/src/jemalloc/error.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@ pub enum Error {
7171
#[snafu(source)]
7272
error: tikv_jemalloc_ctl::Error,
7373
},
74+
75+
#[snafu(display("Failed to read jemalloc gdump flag"))]
76+
ReadGdump {
77+
#[snafu(source)]
78+
error: tikv_jemalloc_ctl::Error,
79+
},
80+
81+
#[snafu(display("Failed to update jemalloc gdump flag"))]
82+
UpdateGdump {
83+
#[snafu(source)]
84+
error: tikv_jemalloc_ctl::Error,
85+
},
7486
}
7587

7688
impl ErrorExt for Error {
@@ -84,6 +96,8 @@ impl ErrorExt for Error {
8496
Error::ActivateProf { .. } => StatusCode::Internal,
8597
Error::DeactivateProf { .. } => StatusCode::Internal,
8698
Error::ReadProfActive { .. } => StatusCode::Internal,
99+
Error::ReadGdump { .. } => StatusCode::Internal,
100+
Error::UpdateGdump { .. } => StatusCode::Internal,
87101
}
88102
}
89103

src/common/mem-prof/src/lib.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ mod jemalloc;
1919
#[cfg(not(windows))]
2020
pub use jemalloc::{
2121
activate_heap_profile, deactivate_heap_profile, dump_flamegraph, dump_pprof, dump_profile,
22-
is_heap_profile_active,
22+
is_gdump_active, is_heap_profile_active, set_gdump_active,
2323
};
2424

2525
#[cfg(windows)]
@@ -51,3 +51,13 @@ pub fn deactivate_heap_profile() -> error::Result<()> {
5151
pub fn is_heap_profile_active() -> error::Result<bool> {
5252
error::ProfilingNotSupportedSnafu.fail()
5353
}
54+
55+
#[cfg(windows)]
56+
pub fn is_gdump_active() -> error::Result<bool> {
57+
error::ProfilingNotSupportedSnafu.fail()
58+
}
59+
60+
#[cfg(windows)]
61+
pub fn set_gdump_active(_: bool) -> error::Result<()> {
62+
error::ProfilingNotSupportedSnafu.fail()
63+
}

src/servers/src/http.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,11 @@ impl HttpServer {
924924
.route(
925925
"/mem/status",
926926
routing::get(mem_prof::heap_prof_status_handler),
927+
) // jemalloc gdump flag status and toggle
928+
.route(
929+
"/mem/gdump",
930+
routing::get(mem_prof::gdump_status_handler)
931+
.post(mem_prof::gdump_toggle_handler),
927932
),
928933
),
929934
))

src/servers/src/http/mem_prof.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
#[cfg(feature = "mem-prof")]
16+
use axum::Form;
1517
#[cfg(feature = "mem-prof")]
1618
use axum::extract::Query;
1719
use axum::http::StatusCode;
@@ -127,3 +129,57 @@ pub async fn heap_prof_status_handler() -> crate::error::Result<impl IntoRespons
127129
"The 'mem-prof' feature is disabled",
128130
))
129131
}
132+
133+
#[cfg(feature = "mem-prof")]
134+
#[derive(Deserialize)]
135+
pub struct GdumpToggleForm {
136+
activate: bool,
137+
}
138+
139+
#[cfg(feature = "mem-prof")]
140+
#[axum_macros::debug_handler]
141+
pub async fn gdump_toggle_handler(
142+
Form(form): Form<GdumpToggleForm>,
143+
) -> crate::error::Result<impl IntoResponse> {
144+
use snafu::ResultExt;
145+
146+
use crate::error::DumpProfileDataSnafu;
147+
148+
common_mem_prof::set_gdump_active(form.activate).context(DumpProfileDataSnafu)?;
149+
150+
let msg = if form.activate {
151+
"gdump activated"
152+
} else {
153+
"gdump deactivated"
154+
};
155+
Ok((StatusCode::OK, msg))
156+
}
157+
158+
#[cfg(not(feature = "mem-prof"))]
159+
#[axum_macros::debug_handler]
160+
pub async fn gdump_toggle_handler() -> crate::error::Result<impl IntoResponse> {
161+
Ok((
162+
StatusCode::NOT_IMPLEMENTED,
163+
"The 'mem-prof' feature is disabled",
164+
))
165+
}
166+
167+
#[cfg(feature = "mem-prof")]
168+
#[axum_macros::debug_handler]
169+
pub async fn gdump_status_handler() -> crate::error::Result<impl IntoResponse> {
170+
use snafu::ResultExt;
171+
172+
use crate::error::DumpProfileDataSnafu;
173+
174+
let is_active = common_mem_prof::is_gdump_active().context(DumpProfileDataSnafu)?;
175+
Ok((StatusCode::OK, format!("{{\"active\": {}}}", is_active)))
176+
}
177+
178+
#[cfg(not(feature = "mem-prof"))]
179+
#[axum_macros::debug_handler]
180+
pub async fn gdump_status_handler() -> crate::error::Result<impl IntoResponse> {
181+
Ok((
182+
StatusCode::NOT_IMPLEMENTED,
183+
"The 'mem-prof' feature is disabled",
184+
))
185+
}

0 commit comments

Comments
 (0)