pf2 0.5.0 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +3 -3
- data/ext/pf2/src/lib.rs +2 -0
- data/ext/pf2/src/ruby_internal_apis.rs +9 -2
- data/ext/pf2/src/session/configuration.rs +8 -1
- data/ext/pf2/src/session/ruby_object.rs +7 -3
- data/ext/pf2/src/session.rs +27 -7
- data/ext/pf2/src/signal_scheduler.rs +1 -0
- data/ext/pf2/src/signal_scheduler_unsupported_platform.rs +39 -0
- data/lib/pf2/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 66bf1eb8d6457621a04819a8d100bdb109bf1fd7b4820eb1423a85dcfb91799c
|
4
|
+
data.tar.gz: b1046c04ae8a2a0630d3bd2ed86c4dc645a9ca42c8038bfaaee0be4c71dbec78
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5e8854a44c477c42dc9baa0a5b2cd95e19cd09a3c41fad0e950e7de6bd88ff90bf6a3d8e7b61c43c966976211047d5ecb6da11fbe5cba6460ab456186856e2b8
|
7
|
+
data.tar.gz: 8d577d2502f38dab61d3ab130f2555b314667c414ec13b2829f2e7fdf0ddf1f114310d560806685145e5ce65f7f24cc50f834f9fc6eb2b1e0d7763b8ebe69d5f
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.5.2] - 2024-07-13
|
4
|
+
|
5
|
+
### Fixed
|
6
|
+
|
7
|
+
- Properly default to TimerThread scheduler on non-Linux environments.
|
8
|
+
|
9
|
+
|
10
|
+
## [0.5.1] - 2024-03-25
|
11
|
+
|
12
|
+
### Fixed
|
13
|
+
|
14
|
+
- Fixed compilation on non-Linux environments.
|
15
|
+
|
3
16
|
|
4
17
|
## [0.5.0] - 2024-03-25
|
5
18
|
|
data/README.md
CHANGED
@@ -58,7 +58,7 @@ File.write("my_program.pf2profile", profile)
|
|
58
58
|
Profiles can be visualized using the [Firefox Profiler](https://profiler.firefox.com/).
|
59
59
|
|
60
60
|
```console
|
61
|
-
$ pf2 -o report.json my_program.pf2profile
|
61
|
+
$ pf2 report -o report.json my_program.pf2profile
|
62
62
|
```
|
63
63
|
|
64
64
|
### Configuration
|
@@ -108,9 +108,9 @@ Schedulers determine when to execute sample collection, based on configuration (
|
|
108
108
|
|
109
109
|
#### SignalScheduler (Linux-only)
|
110
110
|
|
111
|
-
The first is the `SignalScheduler`, based on POSIX timers. Pf2 will use this scheduler when possible. SignalScheduler creates a POSIX timer for each Ruby Thread (the underlying pthread to be more accurate) using `timer_create(
|
111
|
+
The first is the `SignalScheduler`, based on POSIX timers. Pf2 will use this scheduler when possible. SignalScheduler creates a POSIX timer for each Ruby Thread (the underlying pthread to be more accurate) using `timer_create(2)`. This leaves the actual time-keeping to the OS, which is capable of tracking accurate per-thread CPU time usage.
|
112
112
|
|
113
|
-
When the specified interval has arrived (the timer has _expired_), the OS delivers us a SIGALRM (note: Unlike `setitimer(2)`, `timer_create(
|
113
|
+
When the specified interval has arrived (the timer has _expired_), the OS delivers us a SIGALRM (note: Unlike `setitimer(2)`, `timer_create(2)` allows us to choose which signal to be delivered, and Pf2 uses SIGALRM regardless of time mode). This is why the scheduler is named SignalScheduler.
|
114
114
|
|
115
115
|
Signals are directed to Ruby Threads' underlying pthread, effectively "pausing" the Thread's activity. This routing is done using `SIGEV_THREAD_ID`, which is a Linux-only feature. Sample collection is done in the signal handler, which is expected to be more _accurate_, capturing the paused Thread's activity.
|
116
116
|
|
data/ext/pf2/src/lib.rs
CHANGED
@@ -1,13 +1,20 @@
|
|
1
1
|
#![allow(non_snake_case)]
|
2
2
|
#![allow(non_camel_case_types)]
|
3
3
|
|
4
|
-
use libc::{clockid_t,
|
4
|
+
use libc::{clockid_t, pthread_t};
|
5
5
|
use rb_sys::{rb_check_typeddata, rb_data_type_struct, RTypedData, VALUE};
|
6
6
|
use std::ffi::{c_char, c_int, c_void};
|
7
7
|
use std::mem::MaybeUninit;
|
8
8
|
|
9
|
-
|
9
|
+
#[cfg(target_os = "linux")]
|
10
|
+
use libc::pthread_getcpuclockid;
|
11
|
+
|
12
|
+
#[cfg(not(target_os = "linux"))]
|
13
|
+
pub unsafe fn pthread_getcpuclockid(thread: pthread_t, clk_id: *mut clockid_t) -> c_int {
|
14
|
+
unimplemented!()
|
15
|
+
}
|
10
16
|
|
17
|
+
// Types and structs from Ruby 3.4.0.
|
11
18
|
#[repr(C)]
|
12
19
|
pub struct rb_callable_method_entry_struct {
|
13
20
|
/* same fields with rb_method_entry_t */
|
@@ -6,9 +6,16 @@ use rb_sys::*;
|
|
6
6
|
|
7
7
|
use crate::util::cstr;
|
8
8
|
|
9
|
+
#[cfg(target_os = "linux")]
|
9
10
|
pub const DEFAULT_SCHEDULER: Scheduler = Scheduler::Signal;
|
10
|
-
|
11
|
+
#[cfg(target_os = "linux")]
|
11
12
|
pub const DEFAULT_TIME_MODE: TimeMode = TimeMode::CpuTime;
|
13
|
+
#[cfg(not(target_os = "linux"))]
|
14
|
+
pub const DEFAULT_SCHEDULER: Scheduler = Scheduler::TimerThread;
|
15
|
+
#[cfg(not(target_os = "linux"))]
|
16
|
+
pub const DEFAULT_TIME_MODE: TimeMode = TimeMode::WallTime;
|
17
|
+
|
18
|
+
pub const DEFAULT_INTERVAL: Duration = Duration::from_millis(49);
|
12
19
|
|
13
20
|
#[derive(Clone, Debug)]
|
14
21
|
pub struct Configuration {
|
@@ -1,7 +1,7 @@
|
|
1
1
|
use std::ffi::{c_int, c_void};
|
2
2
|
use std::mem;
|
3
3
|
use std::mem::ManuallyDrop;
|
4
|
-
use std::ptr::null_mut;
|
4
|
+
use std::ptr::{addr_of, null_mut};
|
5
5
|
|
6
6
|
use rb_sys::*;
|
7
7
|
|
@@ -43,7 +43,7 @@ impl SessionRubyObject {
|
|
43
43
|
// Extract the SessionRubyObject struct from a Ruby object
|
44
44
|
unsafe fn get_struct_from(obj: VALUE) -> ManuallyDrop<Box<Self>> {
|
45
45
|
unsafe {
|
46
|
-
let ptr = rb_check_typeddata(obj,
|
46
|
+
let ptr = rb_check_typeddata(obj, addr_of!(RBDATA));
|
47
47
|
ManuallyDrop::new(Box::from_raw(ptr as *mut SessionRubyObject))
|
48
48
|
}
|
49
49
|
}
|
@@ -55,7 +55,11 @@ impl SessionRubyObject {
|
|
55
55
|
let rb_mPf2: VALUE = rb_define_module(cstr!("Pf2"));
|
56
56
|
let rb_cSession = rb_define_class_under(rb_mPf2, cstr!("Session"), rb_cObject);
|
57
57
|
// Wrap the struct into a Ruby object
|
58
|
-
rb_data_typed_object_wrap(
|
58
|
+
rb_data_typed_object_wrap(
|
59
|
+
rb_cSession,
|
60
|
+
Box::into_raw(obj) as *mut c_void,
|
61
|
+
addr_of!(RBDATA),
|
62
|
+
)
|
59
63
|
}
|
60
64
|
|
61
65
|
unsafe extern "C" fn dmark(ptr: *mut c_void) {
|
data/ext/pf2/src/session.rs
CHANGED
@@ -16,7 +16,10 @@ use self::configuration::Configuration;
|
|
16
16
|
use self::new_thread_watcher::NewThreadWatcher;
|
17
17
|
use crate::profile::Profile;
|
18
18
|
use crate::scheduler::Scheduler;
|
19
|
+
#[cfg(target_os = "linux")]
|
19
20
|
use crate::signal_scheduler::SignalScheduler;
|
21
|
+
#[cfg(not(target_os = "linux"))]
|
22
|
+
use crate::signal_scheduler_unsupported_platform::SignalScheduler;
|
20
23
|
use crate::timer_thread_scheduler::TimerThreadScheduler;
|
21
24
|
use crate::util::*;
|
22
25
|
|
@@ -90,12 +93,17 @@ impl Session {
|
|
90
93
|
)),
|
91
94
|
};
|
92
95
|
|
96
|
+
let running = Arc::new(AtomicBool::new(false));
|
97
|
+
|
93
98
|
let new_thread_watcher = match threads {
|
94
99
|
configuration::Threads::All => {
|
95
100
|
let scheduler = Arc::clone(&scheduler);
|
101
|
+
let running = Arc::clone(&running);
|
96
102
|
Some(NewThreadWatcher::watch(move |thread: VALUE| {
|
97
|
-
|
98
|
-
|
103
|
+
if running.load(Ordering::Relaxed) {
|
104
|
+
log::debug!("New Ruby thread detected: {:?}", thread);
|
105
|
+
scheduler.on_new_thread(thread);
|
106
|
+
}
|
99
107
|
}))
|
100
108
|
}
|
101
109
|
configuration::Threads::Targeted(_) => None,
|
@@ -105,7 +113,7 @@ impl Session {
|
|
105
113
|
configuration,
|
106
114
|
scheduler,
|
107
115
|
profile,
|
108
|
-
running
|
116
|
+
running,
|
109
117
|
new_thread_watcher,
|
110
118
|
}
|
111
119
|
}
|
@@ -176,15 +184,27 @@ impl Session {
|
|
176
184
|
let ptr = rb_string_value_ptr(&mut str);
|
177
185
|
CStr::from_ptr(ptr).to_str().unwrap()
|
178
186
|
};
|
179
|
-
|
180
|
-
|
187
|
+
let scheduler =
|
188
|
+
configuration::Scheduler::from_str(specified_scheduler).unwrap_or_else(|_| {
|
189
|
+
// Raise an ArgumentError if the mode is invalid
|
190
|
+
unsafe {
|
191
|
+
rb_raise(
|
192
|
+
rb_eArgError,
|
193
|
+
cstr!("Invalid scheduler. Valid values are ':signal' and ':timer_thread'."),
|
194
|
+
)
|
195
|
+
}
|
196
|
+
});
|
197
|
+
|
198
|
+
// Raise an ArgumentError if the scheduler is not supported on the current platform
|
199
|
+
if !cfg!(target_os = "linux") && scheduler == configuration::Scheduler::Signal {
|
181
200
|
unsafe {
|
182
201
|
rb_raise(
|
183
202
|
rb_eArgError,
|
184
|
-
cstr!("
|
203
|
+
cstr!("Signal scheduler is not supported on this platform."),
|
185
204
|
)
|
186
205
|
}
|
187
|
-
}
|
206
|
+
}
|
207
|
+
scheduler
|
188
208
|
}
|
189
209
|
|
190
210
|
pub fn start(&mut self) -> VALUE {
|
@@ -0,0 +1,39 @@
|
|
1
|
+
use std::sync::{Arc, RwLock};
|
2
|
+
|
3
|
+
use crate::profile::Profile;
|
4
|
+
use crate::scheduler::Scheduler;
|
5
|
+
use crate::session::configuration::Configuration;
|
6
|
+
|
7
|
+
pub struct SignalScheduler {}
|
8
|
+
|
9
|
+
impl Scheduler for SignalScheduler {
|
10
|
+
fn start(&self) -> rb_sys::VALUE {
|
11
|
+
unimplemented!()
|
12
|
+
}
|
13
|
+
|
14
|
+
fn stop(&self) -> rb_sys::VALUE {
|
15
|
+
unimplemented!()
|
16
|
+
}
|
17
|
+
|
18
|
+
fn on_new_thread(&self, thread: rb_sys::VALUE) {
|
19
|
+
unimplemented!()
|
20
|
+
}
|
21
|
+
|
22
|
+
fn dmark(&self) {
|
23
|
+
unimplemented!()
|
24
|
+
}
|
25
|
+
|
26
|
+
fn dfree(&self) {
|
27
|
+
unimplemented!()
|
28
|
+
}
|
29
|
+
|
30
|
+
fn dsize(&self) -> rb_sys::size_t {
|
31
|
+
unimplemented!()
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
impl SignalScheduler {
|
36
|
+
pub fn new(configuration: &Configuration, profile: Arc<RwLock<Profile>>) -> Self {
|
37
|
+
unimplemented!()
|
38
|
+
}
|
39
|
+
}
|
data/lib/pf2/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pf2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daisuke Aritomo
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2024-
|
10
|
+
date: 2024-07-12 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: rake-compiler
|
@@ -177,6 +177,7 @@ files:
|
|
177
177
|
- ext/pf2/src/session/ruby_object.rs
|
178
178
|
- ext/pf2/src/siginfo_t.c
|
179
179
|
- ext/pf2/src/signal_scheduler.rs
|
180
|
+
- ext/pf2/src/signal_scheduler_unsupported_platform.rs
|
180
181
|
- ext/pf2/src/timer_thread_scheduler.rs
|
181
182
|
- ext/pf2/src/util.rs
|
182
183
|
- lib/pf2.rb
|