remotery/lib.rs
1//! Remotery is a realtime CPU/GPU profiler with a viewer that runs in a web browser.
2//! This lib is a [Rust](https://www.rust-lang.org) wrapper around the C API provided by Remotery and the original
3//! repo over here https://github.com/Celtoys/Remotery
4//!
5pub mod error;
6mod remotery_ffi;
7mod cfixed_string;
8use std::ptr;
9use std::os::raw::c_void;
10use error::RemoteryError;
11use cfixed_string::CFixedString;
12
13/// Holds the main instance for Remotery
14pub struct Remotery {
15 instance: *mut c_void,
16}
17
18#[derive(Clone, Copy)]
19/// Sample flags to decide how profiling info should be handled
20pub enum SampleFlags {
21 /// Default behaviour
22 Default,
23 /// Search parent for same-named samples and merge timing instead of adding a new sample
24 Aggregate,
25}
26
27impl Remotery {
28 /// Creates the global instance (with in the C lib that this code wraps) this code needs to be
29 /// called before any of the other code is being called and the instance will be dropped when
30 /// it goes out of scope so it's suggested to call this early in the main entry point of your
31 /// program (such as ``main``)
32 ///
33 /// # Examples
34 ///
35 /// ```ignore
36 /// let _remotery = Remotery::create_global_instance().unwrap_or_else(|e| {
37 /// panic!(e);
38 /// });
39 /// ```
40 ///
41 pub fn create_global_instance() -> Result<Remotery, RemoteryError> {
42 let mut instance = 0 as *mut c_void;
43
44 let res = unsafe {
45 remotery_ffi::_rmt_CreateGlobalInstance(&mut instance)
46 };
47
48 if res != 0 {
49 return Err(error::get_error(res));
50 }
51
52 Ok(Remotery { instance: instance })
53 }
54
55 ///
56 /// Begin a cpu sample. Notice that this call needs to be paired with ``end_cpu_sample``.
57 /// It's also possible to use ```RemoteryScope``` that will call end_cpu_scope when the scop ends.
58 ///
59 /// # Examples
60 /// ```ignore
61 /// Remotery::begin_cpu_sample("my_function", SampleFlags::Default);
62 /// // some code to profile here
63 /// Remotery::end_cpu_sample();
64 /// ```
65 ///
66 pub fn begin_cpu_sample(name: &str, flags: SampleFlags) {
67 // TODO: As we send 0 as last parameter which is hash caching this will always recalculate
68 // the hash which adds some slight overhead. Would be nice if that could be solved somehow.
69 unsafe {
70 let temp_str = CFixedString::from_str(name);
71 remotery_ffi::_rmt_BeginCPUSample(temp_str.as_ptr(), flags as u32, ptr::null_mut());
72 }
73 }
74
75 /// Ends a cpu sample. Notice that this needs to be paired with ``begin_cpu_sample`` as seen above.
76 pub fn end_cpu_sample() {
77 unsafe {
78 remotery_ffi::_rmt_EndCPUSample();
79 }
80 }
81
82 /// Setts the name of the current thread that makes it easier to identify it in the Remotery UI
83 ///
84 /// # Examples
85 ///
86 /// ```ignore
87 /// Remotery::set_current_thread_name("my_thread_name");
88 /// ```
89 ///
90 pub fn set_current_thread_name(name: &str) {
91 unsafe {
92 let temp_str = CFixedString::from_str(name);
93 remotery_ffi::_rmt_SetCurrentThreadName(temp_str.as_ptr());
94 }
95 }
96
97 ///
98 /// Can be used to log text to the remotery ui
99 ///
100 pub fn log_text(text: &str) {
101 unsafe {
102 let temp_str = CFixedString::from_str(text);
103 remotery_ffi::_rmt_LogText(temp_str.as_ptr());
104 }
105 }
106}
107
108/// Scopes allows you to profile a bit of code and the end_cpu_sample will be called once it goes out of scope
109pub struct RemoteryScope;
110
111impl RemoteryScope {
112 ///
113 /// Begin a new Scope which auto calls ``end_cpu_scope`` once the scope ends
114 ///
115 /// # Examples
116 ///
117 /// ```ignore
118 /// let _scope = RemoteryScope::new("my_function", SampleFlags::Default);
119 /// ```
120 pub fn new(name: &str, flags: SampleFlags) -> RemoteryScope {
121 Remotery::begin_cpu_sample(name, flags);
122 RemoteryScope {}
123 }
124}
125
126impl Drop for RemoteryScope {
127 fn drop(&mut self) {
128 Remotery::end_cpu_sample()
129 }
130}
131
132impl Drop for Remotery {
133 fn drop(&mut self) {
134 if self.instance == ptr::null_mut() {
135 return
136 }
137
138 unsafe {
139 remotery_ffi::_rmt_DestroyGlobalInstance(self.instance);
140 }
141 }
142}
143