1
1
mod interrupts;
2
2
mod sample_type_filter;
3
3
pub mod stack_walking;
4
+ mod system_profiler;
4
5
mod thread_utils;
5
6
mod uploader;
6
7
7
8
pub use interrupts:: * ;
8
9
pub use sample_type_filter:: * ;
9
10
pub use stack_walking:: * ;
11
+ pub use system_profiler:: * ;
10
12
use uploader:: * ;
11
13
12
14
#[ cfg( all( php_has_fibers, not( test) ) ) ]
@@ -26,12 +28,10 @@ use datadog_profiling::api::{
26
28
use datadog_profiling:: exporter:: Tag ;
27
29
use datadog_profiling:: internal:: Profile as InternalProfile ;
28
30
use log:: { debug, info, trace, warn} ;
29
- use once_cell:: sync:: OnceCell ;
30
31
use std:: borrow:: Cow ;
31
32
use std:: collections:: HashMap ;
32
33
use std:: hash:: Hash ;
33
34
use std:: intrinsics:: transmute;
34
- use std:: mem:: forget;
35
35
use std:: num:: NonZeroI64 ;
36
36
use std:: sync:: atomic:: { AtomicBool , AtomicPtr , AtomicU32 , Ordering } ;
37
37
use std:: sync:: { Arc , Barrier } ;
@@ -58,10 +58,6 @@ pub const NO_TIMESTAMP: i64 = 0;
58
58
// magnitude for the capacity.
59
59
const UPLOAD_CHANNEL_CAPACITY : usize = 8 ;
60
60
61
- /// The global profiler. Profiler gets made during the first rinit after an
62
- /// minit, and is destroyed on mshutdown.
63
- static mut PROFILER : OnceCell < Profiler > = OnceCell :: new ( ) ;
64
-
65
61
/// Order this array this way:
66
62
/// 1. Always enabled types.
67
63
/// 2. On by default types.
@@ -520,21 +516,6 @@ const DDPROF_TIME: &str = "ddprof_time";
520
516
const DDPROF_UPLOAD : & str = "ddprof_upload" ;
521
517
522
518
impl Profiler {
523
- /// Will initialize the `PROFILER` OnceCell and makes sure that only one thread will do so.
524
- pub fn init ( system_settings : & mut SystemSettings ) {
525
- // SAFETY: the `get_or_init` access is a thread-safe API, and the
526
- // PROFILER is not being mutated outside single-threaded phases such
527
- // as minit/mshutdown.
528
- unsafe { PROFILER . get_or_init ( || Profiler :: new ( system_settings) ) } ;
529
- }
530
-
531
- pub fn get ( ) -> Option < & ' static Profiler > {
532
- // SAFETY: the `get` access is a thread-safe API, and the PROFILER is
533
- // not being mutated outside single-threaded phases such as minit and
534
- // mshutdown.
535
- unsafe { PROFILER . get ( ) }
536
- }
537
-
538
519
pub fn new ( system_settings : & mut SystemSettings ) -> Self {
539
520
let fork_barrier = Arc :: new ( Barrier :: new ( 3 ) ) ;
540
521
let interrupt_manager = Arc :: new ( InterruptManager :: new ( ) ) ;
@@ -644,19 +625,6 @@ impl Profiler {
644
625
. map_err ( Box :: new)
645
626
}
646
627
647
- /// Begins the shutdown process. To complete it, call [Profiler::shutdown].
648
- /// Note that you must call [Profiler::shutdown] afterwards; it's two
649
- /// parts of the same operation. It's split so you (or other extensions)
650
- /// can do something while the other threads finish up.
651
- pub fn stop ( timeout : Duration ) {
652
- // SAFETY: the `get_mut` access is a thread-safe API, and the PROFILER
653
- // is not being mutated outside single-threaded phases such as minit
654
- // and mshutdown.
655
- if let Some ( profiler) = unsafe { PROFILER . get_mut ( ) } {
656
- profiler. join_and_drop_sender ( timeout) ;
657
- }
658
- }
659
-
660
628
pub fn join_and_drop_sender ( & mut self , timeout : Duration ) {
661
629
debug ! ( "Stopping profiler." ) ;
662
630
@@ -685,20 +653,6 @@ impl Profiler {
685
653
std:: mem:: swap ( & mut self . upload_sender , & mut empty_sender) ;
686
654
}
687
655
688
- /// Completes the shutdown process; to start it, call [Profiler::stop]
689
- /// before calling [Profiler::shutdown].
690
- /// Note the timeout is per thread, and there may be multiple threads.
691
- ///
692
- /// Safety: only safe to be called in `SHUTDOWN`/`MSHUTDOWN` phase
693
- pub fn shutdown ( timeout : Duration ) {
694
- // SAFETY: the `take` access is a thread-safe API, and the PROFILER is
695
- // not being mutated outside single-threaded phases such as minit and
696
- // mshutdown.
697
- if let Some ( profiler) = unsafe { PROFILER . take ( ) } {
698
- profiler. join_collector_and_uploader ( timeout) ;
699
- }
700
- }
701
-
702
656
pub fn join_collector_and_uploader ( self , timeout : Duration ) {
703
657
if self . should_join . load ( Ordering :: SeqCst ) {
704
658
thread_utils:: join_timeout (
@@ -718,34 +672,6 @@ impl Profiler {
718
672
}
719
673
}
720
674
721
- /// Throws away the profiler and moves it to uninitialized.
722
- ///
723
- /// In a forking situation, the currently active profiler may not be valid
724
- /// because it has join handles and other state shared by other threads,
725
- /// and threads are not copied when the process is forked.
726
- /// Additionally, if we've hit certain other issues like not being able to
727
- /// determine the return type of the pcntl_fork function, we don't know if
728
- /// we're the parent or child.
729
- /// So, we throw away the current profiler and forget it, which avoids
730
- /// running the destructor. Yes, this will leak some memory.
731
- ///
732
- /// # Safety
733
- /// Must be called when no other thread is using the PROFILER object. That
734
- /// includes this thread in some kind of recursive manner.
735
- pub unsafe fn kill ( ) {
736
- // SAFETY: see this function's safety conditions.
737
- if let Some ( mut profiler) = PROFILER . take ( ) {
738
- // Drop some things to reduce memory.
739
- profiler. interrupt_manager = Arc :: new ( InterruptManager :: new ( ) ) ;
740
- profiler. message_sender = crossbeam_channel:: bounded ( 0 ) . 0 ;
741
- profiler. upload_sender = crossbeam_channel:: bounded ( 0 ) . 0 ;
742
-
743
- // But we're not 100% sure everything is safe to drop, notably the
744
- // join handles, so we leak the rest.
745
- forget ( profiler)
746
- }
747
- }
748
-
749
675
/// Collect a stack sample with elapsed wall time. Collects CPU time if
750
676
/// it's enabled and available.
751
677
pub fn collect_time ( & self , execute_data : * mut zend_execute_data , interrupt_count : u32 ) {
0 commit comments