• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use crate::executor::async_pool::AsyncPoolSpawner;
15 use crate::executor::{AsyncHandle, Runtime};
16 
17 /// User can get some message from Runtime during running.
18 ///
19 /// # Example
20 /// ```no_run
21 /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
22 ///     .build()
23 ///     .unwrap();
24 /// let metrics = runtime.metrics();
25 /// ```
26 pub struct Metrics<'a> {
27     runtime: &'a Runtime,
28 }
29 
30 /// List of workers state.
31 #[derive(Debug)]
32 pub struct WorkList {
33     /// The set of index of the park workers
34     pub park: Vec<usize>,
35     /// The set of index of the active workers
36     pub active: Vec<usize>,
37 }
38 
39 impl Metrics<'_> {
40     const ACTIVE_STATE: usize = 3;
41 
new(runtime: &Runtime) -> Metrics42     pub(crate) fn new(runtime: &Runtime) -> Metrics {
43         Metrics { runtime }
44     }
45 
46     /// Returns workers num
47     ///
48     /// # Example
49     /// ```
50     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
51     ///     .build()
52     ///     .unwrap();
53     /// let metrics = runtime.metrics();
54     /// println!("Runtime's workers_num:{}", metrics.workers_num());
55     /// ```
workers_num(&self) -> usize56     pub fn workers_num(&self) -> usize {
57         match &self.runtime.async_spawner {
58             #[cfg(feature = "current_thread_runtime")]
59             AsyncHandle::CurrentThread(_) => 1,
60             AsyncHandle::MultiThread(spawner) => spawner.exe_mng_info.num_workers,
61         }
62     }
63 
64     /// Returns park workers num
65     ///
66     /// Runtime build by `new_current_thread()` will return None.
67     ///
68     /// # Example
69     /// ```
70     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
71     ///     .build()
72     ///     .unwrap();
73     /// let metrics = runtime.metrics();
74     /// println!(
75     ///     "Runtime's park_workers_num:{:?}",
76     ///     metrics.park_workers_num()
77     /// );
78     /// ```
park_workers_num(&self) -> Option<usize>79     pub fn park_workers_num(&self) -> Option<usize> {
80         match &self.runtime.async_spawner {
81             #[cfg(feature = "current_thread_runtime")]
82             AsyncHandle::CurrentThread(_) => None,
83             AsyncHandle::MultiThread(spawner) => {
84                 Some(Self::workers_state_statistic(spawner).park.len())
85             }
86         }
87     }
88 
89     /// Returns active workers num
90     ///
91     /// Runtime build by `new_current_thread()` will return None.
92     ///
93     /// # Example
94     /// ```
95     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
96     ///     .build()
97     ///     .unwrap();
98     /// let metrics = runtime.metrics();
99     /// println!(
100     ///     "Runtime's active_workers_num:{:?}",
101     ///     metrics.active_workers_num()
102     /// );
103     /// ```
active_workers_num(&self) -> Option<usize>104     pub fn active_workers_num(&self) -> Option<usize> {
105         match &self.runtime.async_spawner {
106             #[cfg(feature = "current_thread_runtime")]
107             AsyncHandle::CurrentThread(_) => None,
108             AsyncHandle::MultiThread(spawner) => {
109                 Some(Self::workers_state_statistic(spawner).active.len())
110             }
111         }
112     }
113 
114     /// Returns park workers index list
115     ///
116     /// Runtime build by `new_current_thread()` will return None.
117     ///
118     /// # Example
119     /// ```
120     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
121     ///     .build()
122     ///     .unwrap();
123     /// let metrics = runtime.metrics();
124     /// println!(
125     ///     "Runtime's park_workers_list:{:?}",
126     ///     metrics.park_workers_list()
127     /// );
128     /// ```
park_workers_list(&self) -> Option<Vec<usize>>129     pub fn park_workers_list(&self) -> Option<Vec<usize>> {
130         match &self.runtime.async_spawner {
131             #[cfg(feature = "current_thread_runtime")]
132             AsyncHandle::CurrentThread(_) => None,
133             AsyncHandle::MultiThread(spawner) => Some(Self::workers_state_statistic(spawner).park),
134         }
135     }
136 
137     /// Returns active workers index list
138     ///
139     /// Runtime build by `new_current_thread()` will return None.
140     ///
141     /// # Example
142     /// ```
143     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
144     ///     .build()
145     ///     .unwrap();
146     /// let metrics = runtime.metrics();
147     /// println!(
148     ///     "Runtime's active_workers_list:{:?}",
149     ///     metrics.active_workers_list()
150     /// );
151     /// ```
active_workers_list(&self) -> Option<Vec<usize>>152     pub fn active_workers_list(&self) -> Option<Vec<usize>> {
153         match &self.runtime.async_spawner {
154             #[cfg(feature = "current_thread_runtime")]
155             AsyncHandle::CurrentThread(_) => None,
156             AsyncHandle::MultiThread(spawner) => {
157                 Some(Self::workers_state_statistic(spawner).active)
158             }
159         }
160     }
161 
162     /// Returns park/active workers index list
163     ///
164     /// Runtime build by `new_current_thread()` will return None.
165     ///
166     /// # Example
167     /// ```
168     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
169     ///     .build()
170     ///     .unwrap();
171     /// let metrics = runtime.metrics();
172     /// println!(
173     ///     "Runtime's overall_workers_list:{:?}",
174     ///     metrics.overall_workers_list()
175     /// );
176     /// ```
overall_workers_list(&self) -> Option<WorkList>177     pub fn overall_workers_list(&self) -> Option<WorkList> {
178         match &self.runtime.async_spawner {
179             #[cfg(feature = "current_thread_runtime")]
180             AsyncHandle::CurrentThread(_) => None,
181             AsyncHandle::MultiThread(spawner) => Some(Self::workers_state_statistic(spawner)),
182         }
183     }
184 
workers_state_statistic(spawner: &AsyncPoolSpawner) -> WorkList185     fn workers_state_statistic(spawner: &AsyncPoolSpawner) -> WorkList {
186         let mut park = vec![];
187         let mut active = vec![];
188 
189         let parkers = spawner.exe_mng_info.get_handles().read().unwrap();
190         for i in 0..parkers.len() {
191             match parkers.get(i).unwrap().get_state() {
192                 Self::ACTIVE_STATE => active.push(i),
193                 _ => park.push(i),
194             }
195         }
196 
197         WorkList { park, active }
198     }
199 
200     /// Returns global queue length
201     ///
202     /// # Example
203     /// ```
204     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
205     ///     .build()
206     ///     .unwrap();
207     /// let metrics = runtime.metrics();
208     /// println!(
209     ///     "Runtime's global_queue_length:{}",
210     ///     metrics.global_queue_length()
211     /// );
212     /// ```
global_queue_length(&self) -> usize213     pub fn global_queue_length(&self) -> usize {
214         match &self.runtime.async_spawner {
215             #[cfg(feature = "current_thread_runtime")]
216             AsyncHandle::CurrentThread(spawner) => spawner.scheduler.inner.lock().unwrap().len(),
217             AsyncHandle::MultiThread(spawner) => spawner.exe_mng_info.global.get_len(),
218         }
219     }
220 
221     /// Returns the total number of task which has entered global queue
222     ///
223     /// This value will only increment, not decrease.
224     ///
225     /// # Example
226     /// ```
227     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
228     ///     .build()
229     ///     .unwrap();
230     /// let metrics = runtime.metrics();
231     /// println!(
232     ///     "Runtime's global_queue_total_task_count:{}",
233     ///     metrics.global_queue_total_task_count()
234     /// );
235     /// ```
global_queue_total_task_count(&self) -> u64236     pub fn global_queue_total_task_count(&self) -> u64 {
237         match &self.runtime.async_spawner {
238             #[cfg(feature = "current_thread_runtime")]
239             AsyncHandle::CurrentThread(spawner) => spawner
240                 .scheduler
241                 .count
242                 .load(std::sync::atomic::Ordering::Acquire),
243             AsyncHandle::MultiThread(spawner) => spawner.exe_mng_info.global.get_count(),
244         }
245     }
246 
247     /// Returns the given worker thread length
248     ///
249     /// Runtime build by `new_current_thread()` will return None.
250     ///
251     /// # Example
252     /// ```
253     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
254     ///     .build()
255     ///     .unwrap();
256     /// let metrics = runtime.metrics();
257     /// println!("Runtime's worker_task_len:{:?}", metrics.worker_task_len(0));
258     /// ```
worker_task_len(&self, index: usize) -> Option<usize>259     pub fn worker_task_len(&self, index: usize) -> Option<usize> {
260         match &self.runtime.async_spawner {
261             #[cfg(feature = "current_thread_runtime")]
262             AsyncHandle::CurrentThread(_) => None,
263             AsyncHandle::MultiThread(spawner) => match spawner.get_worker(index) {
264                 Ok(worker) => {
265                     let len = unsafe { worker.get_inner_ptr().run_queue.len() as usize };
266                     Some(len)
267                 }
268                 Err(_) => panic!("out of index"),
269             },
270         }
271     }
272 
273     /// Returns the total number of task which has entered the given worker
274     /// thread
275     ///
276     /// This value will only increment, not decrease.
277     /// Runtime build by `new_current_thread()` will return None.
278     ///
279     /// # Example
280     /// ```
281     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
282     ///     .build()
283     ///     .unwrap();
284     /// let metrics = runtime.metrics();
285     /// println!(
286     ///     "Runtime's worker_total_task_count:{:?}",
287     ///     metrics.worker_total_task_count(0)
288     /// );
289     /// ```
worker_total_task_count(&self, index: usize) -> Option<u64>290     pub fn worker_total_task_count(&self, index: usize) -> Option<u64> {
291         match &self.runtime.async_spawner {
292             #[cfg(feature = "current_thread_runtime")]
293             AsyncHandle::CurrentThread(_) => None,
294             AsyncHandle::MultiThread(spawner) => match spawner.get_worker(index) {
295                 Ok(worker) => {
296                     let len = unsafe { worker.get_inner_ptr().run_queue.count() };
297                     Some(len)
298                 }
299                 Err(_) => panic!("out of index"),
300             },
301         }
302     }
303 
304     /// Returns the number of task the given worker thread length has been
305     /// polled.
306     ///
307     /// This value will only increment, not decrease.
308     /// Runtime build by `new_current_thread()` will return None.
309     ///
310     /// # Example
311     /// ```
312     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
313     ///     .build()
314     ///     .unwrap();
315     /// let metrics = runtime.metrics();
316     /// println!(
317     ///     "Runtime's worker_poll_count:{:?}",
318     ///     metrics.worker_poll_count(0)
319     /// );
320     /// ```
worker_poll_count(&self, index: usize) -> Option<usize>321     pub fn worker_poll_count(&self, index: usize) -> Option<usize> {
322         match &self.runtime.async_spawner {
323             #[cfg(feature = "current_thread_runtime")]
324             AsyncHandle::CurrentThread(_) => None,
325             AsyncHandle::MultiThread(spawner) => match spawner.get_worker(index) {
326                 Ok(worker) => {
327                     let len = unsafe { worker.get_inner_ptr().count as usize };
328                     Some(len)
329                 }
330                 Err(_) => panic!("out of index"),
331             },
332         }
333     }
334 
335     /// Returns the times of steals.
336     ///
337     /// This value will only increment, not decrease.
338     /// Runtime build by `new_current_thread()` will return None.
339     ///
340     /// # Example
341     /// ```
342     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
343     ///     .build()
344     ///     .unwrap();
345     /// let metrics = runtime.metrics();
346     /// println!("Runtime's steal_times:{:?}", metrics.steal_times());
347     /// ```
steal_times(&self) -> Option<u64>348     pub fn steal_times(&self) -> Option<u64> {
349         match &self.runtime.async_spawner {
350             #[cfg(feature = "current_thread_runtime")]
351             AsyncHandle::CurrentThread(_) => None,
352             AsyncHandle::MultiThread(spawner) => Some(spawner.exe_mng_info.get_steal_times()),
353         }
354     }
355 
356     /// Returns the number of times the given worker get tasks from the global
357     /// queue.
358     ///
359     /// This value will only increment, not decrease.
360     /// Runtime build by `new_current_thread()` will return None.
361     ///
362     /// # Example
363     /// ```
364     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
365     ///     .build()
366     ///     .unwrap();
367     /// let metrics = runtime.metrics();
368     /// println!(
369     ///     "Runtime's worker_get_task_from_global_count:{:?}",
370     ///     metrics.worker_get_task_from_global_count(0)
371     /// );
372     /// ```
worker_get_task_from_global_count(&self, index: usize) -> Option<u64>373     pub fn worker_get_task_from_global_count(&self, index: usize) -> Option<u64> {
374         match &self.runtime.async_spawner {
375             #[cfg(feature = "current_thread_runtime")]
376             AsyncHandle::CurrentThread(_) => None,
377             AsyncHandle::MultiThread(spawner) => match spawner.get_worker(index) {
378                 Ok(worker) => {
379                     let len = unsafe { worker.get_inner_ptr().run_queue.task_from_global_count() };
380                     Some(len)
381                 }
382                 Err(_) => panic!("out of index"),
383             },
384         }
385     }
386 
387     /// Returns the number of times the given worker push a task on the global
388     /// queue.
389     ///
390     /// This value will only increment, not decrease.
391     /// Runtime build by `new_current_thread()` will return None.
392     ///
393     /// # Example
394     /// ```
395     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
396     ///     .build()
397     ///     .unwrap();
398     /// let metrics = runtime.metrics();
399     /// println!(
400     ///     "Runtime's worker_push_task_to_global_count:{:?}",
401     ///     metrics.worker_push_task_to_global_count(0)
402     /// );
403     /// ```
worker_push_task_to_global_count(&self, index: usize) -> Option<u64>404     pub fn worker_push_task_to_global_count(&self, index: usize) -> Option<u64> {
405         match &self.runtime.async_spawner {
406             #[cfg(feature = "current_thread_runtime")]
407             AsyncHandle::CurrentThread(_) => None,
408             AsyncHandle::MultiThread(spawner) => match spawner.get_worker(index) {
409                 Ok(worker) => {
410                     let len = unsafe { worker.get_inner_ptr().run_queue.task_to_global_count() };
411                     Some(len)
412                 }
413                 Err(_) => panic!("out of index"),
414             },
415         }
416     }
417 
418     /// Returns the number of IO events which has been registered in Driver.
419     ///
420     /// This value will only increment, not decrease.
421     ///
422     /// # Example
423     /// ```
424     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
425     ///     .build()
426     ///     .unwrap();
427     /// let metrics = runtime.metrics();
428     /// println!(
429     ///     "Runtime's fd_registered_count:{}",
430     ///     metrics.fd_registered_count()
431     /// );
432     /// ```
433     #[cfg(feature = "net")]
fd_registered_count(&self) -> u64434     pub fn fd_registered_count(&self) -> u64 {
435         self.runtime.get_handle().get_registered_count()
436     }
437 
438     /// Returns the number of IO events which has been readied in Driver.
439     ///
440     /// This value will only increment, not decrease.
441     ///
442     /// # Example
443     /// ```
444     /// let runtime = ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
445     ///     .build()
446     ///     .unwrap();
447     /// let metrics = runtime.metrics();
448     /// println!(
449     ///     "Runtime's io_driver_ready_count:{}",
450     ///     metrics.io_driver_ready_count()
451     /// );
452     /// ```
453     #[cfg(feature = "net")]
io_driver_ready_count(&self) -> u64454     pub fn io_driver_ready_count(&self) -> u64 {
455         self.runtime.get_handle().get_ready_count()
456     }
457 }
458