This is an automated email from the ASF dual-hosted git repository.
xikai pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-horaedb.git
The following commit(s) were added to refs/heads/main by this push:
new d7239ed8 feat: add system_stats lib to collect system stats (#1442)
d7239ed8 is described below
commit d7239ed8d6b2d7bafbd4843133b6b28d22275451
Author: WEI Xikai <[email protected]>
AuthorDate: Wed Jan 17 17:18:34 2024 +0800
feat: add system_stats lib to collect system stats (#1442)
## Rationale
Part of #1438. The preparations for reporting system statistics.
## Detailed Changes
- Add a new component called `system_stats` to helps collect system
statistics.
- Introduce a dependency [`sysinfo`](https://crates.io/crates/sysinfo).
## Test Plan
Add a new unit test.
---
Cargo.lock | 119 ++++++++++++++++-
Cargo.toml | 4 +-
components/skiplist/Cargo.toml | 2 -
components/{skiplist => system_stats}/Cargo.toml | 19 +--
components/system_stats/src/lib.rs | 158 +++++++++++++++++++++++
5 files changed, 277 insertions(+), 25 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index 9e29407d..5c08c3e5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3233,7 +3233,7 @@ dependencies = [
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
- "windows",
+ "windows 0.47.0",
]
[[package]]
@@ -4292,6 +4292,15 @@ dependencies = [
"tokio",
]
+[[package]]
+name = "ntapi"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
+dependencies = [
+ "winapi",
+]
+
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
@@ -5704,9 +5713,9 @@ dependencies = [
[[package]]
name = "rayon"
-version = "1.7.0"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
dependencies = [
"either",
"rayon-core",
@@ -5714,14 +5723,12 @@ dependencies = [
[[package]]
name = "rayon-core"
-version = "1.11.0"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
dependencies = [
- "crossbeam-channel",
"crossbeam-deque 0.8.3",
"crossbeam-utils 0.8.15",
- "num_cpus",
]
[[package]]
@@ -6871,6 +6878,20 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
+[[package]]
+name = "sysinfo"
+version = "0.30.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fb4f3438c8f6389c864e61221cbc97e9bca98b4daf39a5beb7bea660f528bb2"
+dependencies = [
+ "cfg-if 1.0.0",
+ "core-foundation-sys",
+ "libc",
+ "ntapi",
+ "once_cell",
+ "windows 0.52.0",
+]
+
[[package]]
name = "system_catalog"
version = "1.2.6-alpha"
@@ -6893,6 +6914,14 @@ dependencies = [
"trace_metric",
]
+[[package]]
+name = "system_stats"
+version = "1.2.6-alpha"
+dependencies = [
+ "sysinfo",
+ "tokio",
+]
+
[[package]]
name = "table_engine"
version = "1.2.6-alpha"
@@ -8028,6 +8057,25 @@ dependencies = [
"windows-targets 0.47.0",
]
+[[package]]
+name = "windows"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
+dependencies = [
+ "windows-core",
+ "windows-targets 0.52.0",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+dependencies = [
+ "windows-targets 0.52.0",
+]
+
[[package]]
name = "windows-sys"
version = "0.45.0"
@@ -8091,6 +8139,21 @@ dependencies = [
"windows_x86_64_msvc 0.48.0",
]
+[[package]]
+name = "windows-targets"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.0",
+ "windows_aarch64_msvc 0.52.0",
+ "windows_i686_gnu 0.52.0",
+ "windows_i686_msvc 0.52.0",
+ "windows_x86_64_gnu 0.52.0",
+ "windows_x86_64_gnullvm 0.52.0",
+ "windows_x86_64_msvc 0.52.0",
+]
+
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
@@ -8109,6 +8172,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
+
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
@@ -8127,6 +8196,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
+
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
@@ -8145,6 +8220,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
+
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
@@ -8163,6 +8244,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
+
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
@@ -8181,6 +8268,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
+
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
@@ -8199,6 +8292,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
+
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
@@ -8217,6 +8316,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
+
[[package]]
name = "winnow"
version = "0.4.1"
diff --git a/Cargo.toml b/Cargo.toml
index 24a9b13a..9813f1c5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -53,6 +53,7 @@ members = [
"components/sampling_cache",
"components/size_ext",
"components/skiplist",
+ "components/system_stats",
"components/table_kv",
"components/test_util",
"components/time_ext",
@@ -164,7 +165,7 @@ router = { path = "router" }
runtime = { path = "components/runtime" }
sampling_cache = { path = "components/sampling_cache" }
snafu = { version = "0.6.10", features = ["backtraces"] }
-serde = "1.0"
+serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.60"
server = { path = "server" }
size_ext = { path = "components/size_ext" }
@@ -173,6 +174,7 @@ slog = "2.7"
spin = "0.9.6"
sqlparser = { version = "0.35", features = ["serde"] }
system_catalog = { path = "system_catalog" }
+system_statis = { path = "component/system_stats" }
table_engine = { path = "table_engine" }
table_kv = { path = "components/table_kv" }
tempfile = "3.1.0"
diff --git a/components/skiplist/Cargo.toml b/components/skiplist/Cargo.toml
index 544915ab..84b0a5ce 100644
--- a/components/skiplist/Cargo.toml
+++ b/components/skiplist/Cargo.toml
@@ -36,8 +36,6 @@ rand = { workspace = true }
[dev-dependencies]
criterion = { workspace = true }
yatp = { git = "https://github.com/tikv/yatp.git", rev =
"4b71f8abd86890f0d1e95778c2b6bf5a9ee4c502" }
-# [target.'cfg(not(target_env = "msvc"))'.dev-dependencies]
-# tikv-jemallocator = "0.4.0"
[[bench]]
name = "bench"
diff --git a/components/skiplist/Cargo.toml b/components/system_stats/Cargo.toml
similarity index 66%
copy from components/skiplist/Cargo.toml
copy to components/system_stats/Cargo.toml
index 544915ab..b4ab6112 100644
--- a/components/skiplist/Cargo.toml
+++ b/components/system_stats/Cargo.toml
@@ -16,8 +16,8 @@
# under the License.
[package]
-name = "skiplist"
-authors = ["Jay Lee <[email protected]>", "HoraeDB Authors"]
+name = "system_stats"
+authors = ["HoraeDB Authors"]
[package.license]
workspace = true
@@ -29,16 +29,5 @@ workspace = true
workspace = true
[dependencies]
-arena = { workspace = true }
-bytes = { workspace = true }
-rand = { workspace = true }
-
-[dev-dependencies]
-criterion = { workspace = true }
-yatp = { git = "https://github.com/tikv/yatp.git", rev =
"4b71f8abd86890f0d1e95778c2b6bf5a9ee4c502" }
-# [target.'cfg(not(target_env = "msvc"))'.dev-dependencies]
-# tikv-jemallocator = "0.4.0"
-
-[[bench]]
-name = "bench"
-harness = false
+sysinfo = { version = "0.30", default-features = false }
+tokio = { workspace = true }
diff --git a/components/system_stats/src/lib.rs
b/components/system_stats/src/lib.rs
new file mode 100644
index 00000000..a5680bfc
--- /dev/null
+++ b/components/system_stats/src/lib.rs
@@ -0,0 +1,158 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// Helps to collect and report statistics about the system.
+
+use std::{sync::Mutex, time::Duration};
+
+pub use sysinfo::LoadAvg;
+use sysinfo::{Cpu, CpuRefreshKind, MemoryRefreshKind, RefreshKind, System};
+
+/// The stats about the system.
+#[derive(Debug)]
+pub struct SystemStats {
+ /// The usage's range is [0, 1.0]
+ pub cpu_usage: f32,
+ /// The memory is counted in byte.
+ pub used_memory: u64,
+ /// The memory is counted in byte.
+ pub total_memory: u64,
+ pub load_avg: LoadAvg,
+}
+
+/// Collect the stats of the system for reporting.
+///
+/// One background thread will be spawned to run stats collection.
+pub struct SystemStatsCollector {
+ total_memory: u64,
+ system: Mutex<System>,
+}
+
+pub type ErrorMessage = String;
+
+impl SystemStatsCollector {
+ /// Create an new collector for the system stats.
+ pub fn try_new() -> Result<Self, ErrorMessage> {
+ if !sysinfo::IS_SUPPORTED_SYSTEM {
+ return Err("Unsupported system to collect system
metrics".to_string());
+ }
+
+ let system = System::new_with_specifics(Self::make_mem_refresh_kind());
+ Ok(Self {
+ total_memory: system.total_memory(),
+ system: Mutex::new(system),
+ })
+ }
+
+ /// Collect the system stats for `observe_dur`.
+ ///
+ /// The [`sysinfo::MINIMUM_CPU_UPDATE_INTERVAL`] will be used if
+ /// `observe_dur` is smaller.
+ pub async fn collect_and_report(&self, observe_dur: Duration) ->
SystemStats {
+ {
+ let mut system = self.system.lock().unwrap();
+ system.refresh_specifics(Self::make_cpu_refresh_kind());
+ }
+
+ let wait_dur = sysinfo::MINIMUM_CPU_UPDATE_INTERVAL.max(observe_dur);
+ tokio::time::sleep(wait_dur).await;
+
+ let mut system = self.system.lock().unwrap();
+ system.refresh_specifics(Self::make_cpu_and_mem_refresh_kind());
+
+ SystemStats {
+ cpu_usage: self.compute_cpu_usage(system.cpus()),
+ used_memory: system.used_memory(),
+ total_memory: self.total_memory,
+ load_avg: System::load_average(),
+ }
+ }
+
+ // Refresh and compute the latest cpu usage.
+ fn compute_cpu_usage(&self, cpus: &[Cpu]) -> f32 {
+ let mut num_cpus = 0;
+ let mut total_cpu_usage = 0.0;
+ let valid_cpus = cpus.iter().filter(|v| !v.cpu_usage().is_nan());
+ for cpu in valid_cpus {
+ total_cpu_usage += cpu.cpu_usage();
+ num_cpus += 1;
+ }
+
+ if num_cpus != 0 {
+ total_cpu_usage / (num_cpus as f32) / 100.0
+ } else {
+ 0f32
+ }
+ }
+
+ #[inline]
+ fn make_mem_refresh_kind() -> RefreshKind {
+ let mem_refresh_kind = MemoryRefreshKind::new().with_ram();
+ RefreshKind::new().with_memory(mem_refresh_kind)
+ }
+
+ #[inline]
+ fn make_cpu_refresh_kind() -> RefreshKind {
+ let cpu_refresh_kind = CpuRefreshKind::new().with_cpu_usage();
+ RefreshKind::new().with_cpu(cpu_refresh_kind)
+ }
+
+ #[inline]
+ fn make_cpu_and_mem_refresh_kind() -> RefreshKind {
+ let cpu_refresh_kind = CpuRefreshKind::new().with_cpu_usage();
+ let mem_refresh_kind = MemoryRefreshKind::new().with_ram();
+ RefreshKind::new()
+ .with_cpu(cpu_refresh_kind)
+ .with_memory(mem_refresh_kind)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ fn check_system_stats(stats: &SystemStats) {
+ assert!(stats.total_memory > 0);
+ assert!(stats.used_memory > 0);
+ assert!(stats.used_memory < stats.total_memory);
+ assert!(stats.cpu_usage > 0.0);
+ assert!(stats.load_avg.one > 0.0);
+ assert!(stats.load_avg.five > 0.0);
+ assert!(stats.load_avg.fifteen > 0.0);
+ }
+
+ #[tokio::test]
+ async fn test_normal_case() {
+ let collector = SystemStatsCollector::try_new().unwrap();
+ let stats = collector
+ .collect_and_report(Duration::from_millis(500))
+ .await;
+ check_system_stats(&stats);
+
+ let mut all_cpu_usages = Vec::with_capacity(5);
+ for _ in 0..5 {
+ let new_stats = collector
+ .collect_and_report(Duration::from_millis(200))
+ .await;
+ check_system_stats(&new_stats);
+ all_cpu_usages.push(new_stats.cpu_usage);
+ }
+
+ // Ensure the stats will be updated for every collection.
+ assert!(all_cpu_usages.into_iter().any(|v| v != stats.cpu_usage));
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]