diff --git a/Cargo.lock b/Cargo.lock index c20cc9837f..796ee621b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1369,7 +1369,6 @@ dependencies = [ "dynasmrt", "env_logger 0.11.6", "http", - "lazy_static", "libc 0.2.177", "libdd-alloc", "libdd-common", diff --git a/profiling/Cargo.toml b/profiling/Cargo.toml index b6440e5d36..e202fbce48 100644 --- a/profiling/Cargo.toml +++ b/profiling/Cargo.toml @@ -30,7 +30,6 @@ libdd-profiling = { path = "../libdatadog/libdd-profiling" } libdd-common = { path = "../libdatadog/libdd-common" } libdd-library-config-ffi = { path = "../libdatadog/libdd-library-config-ffi" } env_logger = { version = "0.11", default-features = false } -lazy_static = { version = "1.4" } libc = "0.2" # TRACE set to max to support runtime configuration. log = { version = "0.4", features = ["max_level_trace", "release_max_level_trace"]} diff --git a/profiling/src/allocation/allocation_ge84.rs b/profiling/src/allocation/allocation_ge84.rs index 7e9cf6bc00..418acb91c9 100644 --- a/profiling/src/allocation/allocation_ge84.rs +++ b/profiling/src/allocation/allocation_ge84.rs @@ -4,10 +4,10 @@ use crate::allocation::{ use crate::bindings as zend; use crate::PROFILER_NAME; use core::ptr; -use lazy_static::lazy_static; use libc::{c_char, c_int, c_void, size_t}; use log::{debug, trace, warn}; use std::sync::atomic::Ordering::Relaxed; +use std::sync::LazyLock; #[cfg(php_debug)] use libc::c_uint; @@ -94,9 +94,7 @@ fn alloc_prof_needs_disabled_for_jit(version: u32) -> bool { (80400..80407).contains(&version) } -lazy_static! { - static ref JIT_ENABLED: bool = unsafe { zend::ddog_php_jit_enabled() }; -} +static JIT_ENABLED: LazyLock = LazyLock::new(|| unsafe { zend::ddog_php_jit_enabled() }); pub fn alloc_prof_ginit() { unsafe { zend::ddog_php_opcache_init_handle() }; diff --git a/profiling/src/allocation/allocation_le83.rs b/profiling/src/allocation/allocation_le83.rs index b88e7b68cc..c36de739e9 100644 --- a/profiling/src/allocation/allocation_le83.rs +++ b/profiling/src/allocation/allocation_le83.rs @@ -7,10 +7,10 @@ use crate::bindings::{ }; use crate::{RefCellExt, PROFILER_NAME, REQUEST_LOCALS}; use core::ptr; -use lazy_static::lazy_static; use libc::{c_char, c_int, c_void, size_t}; use log::{debug, trace, warn}; use std::sync::atomic::Ordering::Relaxed; +use std::sync::LazyLock; #[cfg(feature = "debug_stats")] use crate::allocation::{ALLOCATION_PROFILING_COUNT, ALLOCATION_PROFILING_SIZE}; @@ -77,9 +77,7 @@ fn alloc_prof_needs_disabled_for_jit(version: u32) -> bool { || (80400..80407).contains(&version) } -lazy_static! { - static ref JIT_ENABLED: bool = unsafe { zend::ddog_php_jit_enabled() }; -} +static JIT_ENABLED: LazyLock = LazyLock::new(|| unsafe { zend::ddog_php_jit_enabled() }); pub fn alloc_prof_ginit() { unsafe { zend::ddog_php_opcache_init_handle() }; diff --git a/profiling/src/lib.rs b/profiling/src/lib.rs index 4e7e23bb1f..d651d43ee4 100644 --- a/profiling/src/lib.rs +++ b/profiling/src/lib.rs @@ -35,7 +35,6 @@ use bindings::{ use clocks::*; use core::ffi::{c_char, c_int, CStr}; use core::ptr; -use lazy_static::lazy_static; use libdd_common::{cstr, tag, tag::Tag}; use log::{debug, error, info, trace, warn}; use profiling::{LocalRootSpanResourceMessage, Profiler, VmInterrupt}; @@ -44,7 +43,7 @@ use std::borrow::Cow; use std::cell::{BorrowError, BorrowMutError, RefCell}; use std::ops::{Deref, DerefMut}; use std::sync::atomic::{AtomicBool, AtomicU32, Ordering}; -use std::sync::{Arc, Once, OnceLock}; +use std::sync::{Arc, LazyLock, Once, OnceLock}; use std::thread::{AccessError, LocalKey}; use std::time::{Duration, Instant}; use uuid::Uuid; @@ -75,73 +74,73 @@ static mut RUNTIME_PHP_VERSION: &str = { } }; -lazy_static! { - /// # Safety - /// The first time this is accessed must be after config is initialized in - /// the first RINIT and before mshutdown! - static ref GLOBAL_TAGS: Vec = { - let mut tags = vec![ - tag!("language", "php"), - tag!("profiler_version", env!("PROFILER_VERSION")), - // SAFETY: calling getpid() is safe. - Tag::new("process_id", unsafe { libc::getpid() }.to_string()) - .expect("process_id tag to be valid"), - Tag::new("runtime-id", runtime_id().to_string()).expect("runtime-id tag to be valid"), - ]; - - // This should probably be "language_version", but this is the - // standardized tag name. - // SAFETY: PHP_VERSION is safe to access in rinit (only - // mutated during minit). - add_tag(&mut tags, "runtime_version", unsafe { RUNTIME_PHP_VERSION }); - add_tag(&mut tags, "php.sapi", SAPI.as_ref()); - // In case we ever add PHP debug build support, we should add `zend-zts-debug` and - // `zend-nts-debug`. For the time being we only support `zend-zts-ndebug` and - // `zend-nts-ndebug` - let runtime_engine = if cfg!(php_zts) { - "zend-zts-ndebug" - } else { - "zend-nts-ndebug" - }; - add_tag(&mut tags, "runtime_engine", runtime_engine); - tags +/// # Safety +/// The first time this is accessed must be after config is initialized in +/// the first RINIT and before mshutdown! +static GLOBAL_TAGS: LazyLock> = LazyLock::new(|| { + let mut tags = vec![ + tag!("language", "php"), + tag!("profiler_version", env!("PROFILER_VERSION")), + // SAFETY: calling getpid() is safe. + Tag::new("process_id", unsafe { libc::getpid() }.to_string()) + .expect("process_id tag to be valid"), + Tag::new("runtime-id", runtime_id().to_string()).expect("runtime-id tag to be valid"), + ]; + + // This should probably be "language_version", but this is the + // standardized tag name. + // SAFETY: PHP_VERSION is safe to access in rinit (only + // mutated during minit). + add_tag(&mut tags, "runtime_version", unsafe { RUNTIME_PHP_VERSION }); + add_tag(&mut tags, "php.sapi", SAPI.as_ref()); + // In case we ever add PHP debug build support, we should add `zend-zts-debug` and + // `zend-nts-debug`. For the time being we only support `zend-zts-ndebug` and + // `zend-nts-ndebug` + let runtime_engine = if cfg!(php_zts) { + "zend-zts-ndebug" + } else { + "zend-nts-ndebug" }; + add_tag(&mut tags, "runtime_engine", runtime_engine); + tags +}); - /// The Server API the profiler is running under. - static ref SAPI: Sapi = { - #[cfg(not(test))] - { - // SAFETY: sapi_module is initialized before minit and there should be - // no concurrent threads. - let sapi_module = unsafe { zend::sapi_module }; - if sapi_module.name.is_null() { - panic!("the sapi_module's name is a null pointer"); - } - - // SAFETY: value has been checked for NULL; I haven't checked that the - // engine ensures its length is less than `isize::MAX`, but it is a - // risk I'm willing to take. - let sapi_name = unsafe { CStr::from_ptr(sapi_module.name) }; - Sapi::from_name(sapi_name.to_string_lossy().as_ref()) - } - // When running `cargo test` we do not link against PHP, so `zend::sapi_name` is not - // available and we just return `Sapi::Unkown` - #[cfg(test)] - { - Sapi::Unknown +/// The Server API the profiler is running under. +static SAPI: LazyLock = LazyLock::new(|| { + #[cfg(not(test))] + { + // SAFETY: sapi_module is initialized before minit and there should be + // no concurrent threads. + let sapi_module = unsafe { zend::sapi_module }; + if sapi_module.name.is_null() { + panic!("the sapi_module's name is a null pointer"); } - }; - // SAFETY: PROFILER_NAME is a byte slice that satisfies the safety requirements. - // Panic: we own this string and it should be UTF8 (see PROFILER_NAME above). - static ref PROFILER_NAME_STR: &'static str = PROFILER_NAME.to_str().unwrap(); + // SAFETY: value has been checked for NULL; I haven't checked that the + // engine ensures its length is less than `isize::MAX`, but it is a + // risk I'm willing to take. + let sapi_name = unsafe { CStr::from_ptr(sapi_module.name) }; + Sapi::from_name(sapi_name.to_string_lossy().as_ref()) + } + // When running `cargo test` we do not link against PHP, so `zend::sapi_name` is not + // available and we just return `Sapi::Unkown` + #[cfg(test)] + { + Sapi::Unknown + } +}); + +// SAFETY: PROFILER_NAME is a byte slice that satisfies the safety requirements. +// Panic: we own this string and it should be UTF8 (see PROFILER_NAME above). +static PROFILER_NAME_STR: LazyLock<&'static str> = LazyLock::new(|| PROFILER_NAME.to_str().unwrap()); - // SAFETY: PROFILER_VERSION is a byte slice that satisfies the safety requirements. - static ref PROFILER_VERSION_STR: &'static str = unsafe { CStr::from_ptr(PROFILER_VERSION.as_ptr() as *const c_char) } +// SAFETY: PROFILER_VERSION is a byte slice that satisfies the safety requirements. +static PROFILER_VERSION_STR: LazyLock<&'static str> = LazyLock::new(|| { + unsafe { CStr::from_ptr(PROFILER_VERSION.as_ptr() as *const c_char) } .to_str() // Panic: we own this string and it should be UTF8 (see PROFILER_VERSION above). - .unwrap(); -} + .unwrap() +}); /// The runtime ID, which is basically a universally unique "pid". This makes /// it almost const, the exception being to re-initialize it from a child fork @@ -472,6 +471,7 @@ trait RefCellExt { where F: FnOnce(&mut T) -> R; + #[inline] fn borrow_or_false(&'static self, f: F) -> bool where F: FnOnce(&T) -> bool, @@ -479,6 +479,7 @@ trait RefCellExt { self.try_with_borrow(f).unwrap_or(false) } + #[inline] fn borrow_mut_or_false(&'static self, f: F) -> bool where F: FnOnce(&mut T) -> bool, @@ -488,6 +489,7 @@ trait RefCellExt { } impl RefCellExt for LocalKey> { + #[inline] fn try_with_borrow(&'static self, f: F) -> Result where F: FnOnce(&T) -> R, @@ -497,6 +499,7 @@ impl RefCellExt for LocalKey> { })??) } + #[inline] fn try_with_borrow_mut(&'static self, f: F) -> Result where F: FnOnce(&mut T) -> R, diff --git a/profiling/src/sapi.rs b/profiling/src/sapi.rs index 5dd0400f62..5d45f72e56 100644 --- a/profiling/src/sapi.rs +++ b/profiling/src/sapi.rs @@ -1,12 +1,10 @@ use crate::zend::sapi_request_info; use log::warn; use std::borrow::Cow; -use std::collections::HashMap; use std::ffi::{CStr, OsStr}; use std::fmt::{Display, Formatter}; use std::os::unix::ffi::OsStrExt; use std::path::Path; -use std::sync::OnceLock; // todo: unify with ../component/sapi #[derive(Copy, Clone, Eq, PartialEq)] @@ -27,25 +25,18 @@ pub enum Sapi { impl Sapi { pub fn from_name(name: &str) -> Sapi { - static SAPIS: OnceLock> = OnceLock::new(); - let sapis = SAPIS.get_or_init(|| { - HashMap::from_iter([ - ("apache2handler", Sapi::Apache2Handler), - ("cgi-fcgi", Sapi::CgiFcgi), - ("cli", Sapi::Cli), - ("cli-server", Sapi::CliServer), - ("embed", Sapi::Embed), - ("frankenphp", Sapi::FrankenPHP), - ("fpm-fcgi", Sapi::FpmFcgi), - ("litespeed", Sapi::Litespeed), - ("phpdbg", Sapi::PhpDbg), - ("tea", Sapi::Tea), - ]) - }); - - match sapis.get(name) { - None => Sapi::Unknown, - Some(sapi) => *sapi, + match name { + "apache2handler" => Sapi::Apache2Handler, + "cgi-fcgi" => Sapi::CgiFcgi, + "cli" => Sapi::Cli, + "cli-server" => Sapi::CliServer, + "embed" => Sapi::Embed, + "frankenphp" => Sapi::FrankenPHP, + "fpm-fcgi" => Sapi::FpmFcgi, + "litespeed" => Sapi::Litespeed, + "phpdbg" => Sapi::PhpDbg, + "tea" => Sapi::Tea, + _ => Sapi::Unknown, } }