auto_allocator/
lib.rs

1//! # Auto Allocator - Zero-Configuration Memory Optimization
2//!
3//! **Just add one line and get optimal memory performance automatically!**
4//!
5//! Auto-allocator automatically selects the best memory allocator for your platform and hardware,
6//! giving you significant performance improvements without any configuration or code changes.
7//!
8//! ## Why Auto Allocator?
9//!
10//! - **🚀 Instant Performance**: Up to 1.6x faster allocation in multi-threaded applications
11//! - **🔧 Zero Configuration**: Works perfectly out-of-the-box, no setup required
12//! - **🌍 Universal Compatibility**: Optimizes across all platforms - servers, desktop, mobile, embedded, WASM
13//! - **🧠 Platform Intelligence**: Automatically chooses the best allocator for each platform
14//! - **⚡ Production Ready**: Used safely in high-performance production environments
15//!
16//! ## Quick Start
17//!
18//! **Step 1:** Add to your `Cargo.toml`:
19//! ```toml
20//! [dependencies]
21//! auto-allocator = "*"
22//! ```
23//!
24//! **Step 2:** Add one line to your `main.rs`:
25//! ```rust,ignore
26//! use auto_allocator; // That's it! 🎉
27//!
28//! fn main() {
29//!     // Your code automatically runs with optimal memory performance
30//!     let data = vec![1, 2, 3, 4, 5];
31//!     println!("Memory allocations are now optimized!");
32//! }
33//! ```
34//!
35//! **That's literally all you need!** Auto-allocator handles everything else automatically.
36//!
37//! ## What You Get
38//!
39//! - **Linux Servers**: mimalloc for superior multi-threaded performance
40//! - **Windows/macOS**: mimalloc for desktop application speed
41//! - **Android/iOS**: Platform-optimized system allocators (Scudo/libmalloc)
42//! - **Docker/Kubernetes**: Optimized for containerized deployments
43//! - **Embedded Systems**: Automatic embedded-alloc for all no_std platforms (RISC-V, ARM, AVR, MSP430, Xtensa, etc.)
44//! - **WASM**: Compatible allocation for web applications
45//!
46//! **Security Mode Available:**
47//! ```toml
48//! auto-allocator = { version = "*", features = ["secure"] }
49//! ```
50
51#![cfg_attr(target_os = "none", no_std)]
52
53// Conditional imports for std vs no_std
54#[cfg(not(target_os = "none"))]
55use log::info;
56#[cfg(not(target_os = "none"))]
57use once_cell::sync::Lazy;
58
59use core::alloc::{GlobalAlloc, Layout};
60use core::sync::atomic::{AtomicU8, Ordering};
61#[cfg(not(target_os = "none"))]
62use core::sync::atomic::AtomicBool;
63
64// Import std-specific modules conditionally
65#[cfg(not(target_os = "none"))]
66use std::alloc;
67
68// ========== Type Definitions ==========
69
70/// Memory allocator type enumeration
71///
72/// Represents all memory allocator types supported by auto-allocator.
73/// Selection priority: mimalloc > embedded > system
74///
75/// # Performance Characteristics
76///
77/// - [`AllocatorType::MimallocSecure`] - Microsoft-developed allocator with security hardening (10% overhead)
78/// - [`AllocatorType::Mimalloc`] - Microsoft-developed allocator, optimal multi-threaded performance  
79/// - [`AllocatorType::EmbeddedHeap`] - Lightweight allocator for resource-constrained environments
80/// - [`AllocatorType::System`] - Operating system default allocator, maximum compatibility
81///
82/// # Automatic Selection Logic
83///
84/// 1. **Modern Linux**: mimalloc (if GCC 4.9+ and stdatomic.h available)
85/// 2. **Legacy Linux**: Compilation error with upgrade guidance
86/// 3. **Windows/macOS**: mimalloc (always available)
87/// 4. **Mobile/BSD**: System allocators (platform compliance)
88/// 5. **Embedded** (`target_os = "none"`): embedded-alloc (all no_std architectures)
89///
90/// # Example
91///
92/// ```rust
93/// use auto_allocator;
94///
95/// let info = auto_allocator::get_allocator_info();
96/// match info.allocator_type {
97///     auto_allocator::AllocatorType::Mimalloc => {
98///         println!("Using mimalloc - optimal performance");
99///     }
100///     auto_allocator::AllocatorType::System => {
101///         println!("Using system allocator - platform compliance");
102///     }
103///     _ => println!("Using other allocator"),
104/// }
105/// ```
106#[derive(Debug, Clone, Copy, PartialEq, Eq)]
107pub enum AllocatorType {
108
109    /// Security-hardened mimalloc allocator
110    ///
111    /// Microsoft-developed allocator with enhanced security features.
112    /// ~10% performance overhead for comprehensive heap protection.
113    /// Available when `secure` feature is enabled on compatible platforms.
114    MimallocSecure,
115
116    /// High-performance mimalloc allocator
117    ///
118    /// Microsoft-developed allocator optimized for multi-threaded workloads.
119    /// Automatically selected on modern systems with GCC 4.9+ and stdatomic.h.
120    Mimalloc,
121
122
123    /// Embedded systems allocator
124    ///
125    /// Lightweight allocator designed for resource-constrained environments.
126    /// Automatically selected on embedded architectures.
127    EmbeddedHeap,
128
129    /// System default allocator
130    ///
131    /// Operating system provided allocator, maximum compatibility.
132    /// Selected for debug builds, WASM, mobile, and platforms with optimized native allocators.
133    System,
134}
135
136/// Allocator information structure
137///
138/// Contains the currently selected allocator type, selection reason, and system information.
139/// Obtained through the [`get_allocator_info()`] function.
140///
141/// # Fields
142///
143/// - `allocator_type` - Currently used allocator type
144/// - `reason` - Detailed reason for allocator selection, including hardware information
145/// - `system_info` - System hardware and environment information
146///
147/// # Example
148///
149/// ```rust
150/// use auto_allocator;
151///
152/// let info = auto_allocator::get_allocator_info();
153/// println!("Allocator: {:?}", info.allocator_type);
154/// println!("Selection reason: {}", info.reason);
155/// println!("CPU cores: {}", info.system_info.cpu_cores);
156/// ```
157#[derive(Debug, Clone)]
158pub struct AllocatorInfo {
159    /// Currently used allocator type
160    pub allocator_type: AllocatorType,
161
162    /// Detailed reason for allocator selection
163    ///
164    /// Contains hardware detection results and selection logic explanation, for example:
165    /// "mimalloc selected by runtime hardware analysis (16 cores, 128GB total RAM)"
166    #[cfg(not(target_os = "none"))]
167    pub reason: String,
168    #[cfg(target_os = "none")]
169    pub reason: &'static str,
170
171    /// System hardware and environment information
172    pub system_info: SystemInfo,
173}
174
175/// System information structure
176///
177/// Contains runtime-detected system hardware and environment information,
178/// used for allocator selection decisions.
179///
180/// # Fields
181///
182/// - `os_type` - Operating system type (linux, macos, windows, etc.)
183/// - `cpu_cores` - CPU core count (including hyperthreaded cores)
184/// - `total_memory_bytes` - Total memory in bytes
185/// - `is_debug` - Whether this is a Debug build
186/// - `is_wasm` - Whether this is a WASM environment
187/// - `target_arch` - Target architecture (x86_64, aarch64, etc.)
188///
189/// # Example
190///
191/// ```rust
192/// use auto_allocator;
193///
194/// let info = auto_allocator::get_allocator_info();
195/// let sys = &info.system_info;
196///
197/// println!("Operating system: {}", sys.os_type);
198/// println!("CPU cores: {}", sys.cpu_cores);
199/// println!("Total memory: {}", auto_allocator::format_memory_size(sys.total_memory_bytes));
200/// ```
201#[derive(Debug, Clone)]
202pub struct SystemInfo {
203    /// Operating system type
204    ///
205    /// Examples: "linux", "macos", "windows", "unknown"
206    #[cfg(not(target_os = "none"))]
207    pub os_type: String,
208    #[cfg(target_os = "none")]
209    pub os_type: &'static str,
210
211    /// CPU core count
212    ///
213    /// Detected via `std::thread::available_parallelism()`, includes hyperthreaded core count
214    pub cpu_cores: usize,
215
216    /// Total memory in bytes
217    ///
218    /// System total physical memory, used for hardware specification assessment.
219    /// Use [`format_memory_size()`] to format as human-readable string.
220    pub total_memory_bytes: u64,
221
222    /// Whether this is a Debug build
223    ///
224    /// Debug builds automatically select system allocator for faster compilation
225    pub is_debug: bool,
226
227    /// Whether this is a WASM environment
228    ///
229    /// WASM environments automatically select system allocator for compatibility
230    pub is_wasm: bool,
231
232    /// Target architecture
233    ///
234    /// Examples: "x86_64", "aarch64", "riscv32", "wasm32"
235    #[cfg(not(target_os = "none"))]
236    pub target_arch: String,
237    #[cfg(target_os = "none")]
238    pub target_arch: &'static str,
239}
240
241// ========== Memory Formatting Utilities ==========
242
243/// High-performance memory size formatting function
244///
245/// Converts byte count to human-readable memory size string, automatically selecting appropriate units.
246/// Uses bit shift operations for performance optimization, supports memory sizes from bytes to PB level.
247///
248/// # Arguments
249///
250/// - `bytes` - The number of bytes to format
251///
252/// # Returns
253///
254/// Returns formatted string, for example:
255/// - `1024` → `"1KB"`
256/// - `1536` → `"1.5KB"`
257/// - `1073741824` → `"1GB"`
258///
259/// # Supported Units
260///
261/// - **B** - Bytes (< 1024)
262/// - **KB** - Kilobytes (1024 B)
263/// - **MB** - Megabytes (1024 KB)
264/// - **GB** - Gigabytes (1024 MB)
265/// - **TB** - Terabytes (1024 GB)
266/// - **PB** - Petabytes (1024 TB)
267///
268/// # Performance Features
269///
270/// - Uses bit shift operations instead of division for performance optimization
271/// - Hardware-optimized leading zero count instructions
272/// - Retains only 1 decimal place for improved performance
273/// - Zero-copy string construction
274///
275/// # Examples
276///
277/// ```rust
278/// use auto_allocator;
279///
280/// // Basic usage
281/// assert_eq!(auto_allocator::format_memory_size(0), "0B");
282/// assert_eq!(auto_allocator::format_memory_size(1024), "1KB");
283/// assert_eq!(auto_allocator::format_memory_size(1536), "1.5KB");
284/// assert_eq!(auto_allocator::format_memory_size(1048576), "1MB");
285/// assert_eq!(auto_allocator::format_memory_size(1073741824), "1GB");
286///
287/// // Use in combination with system information
288/// let info = auto_allocator::get_allocator_info();
289/// let memory_str = auto_allocator::format_memory_size(info.system_info.total_memory_bytes);
290/// println!("Total system memory: {}", memory_str);
291///
292/// // Display memory usage in application
293/// fn display_memory_usage() {
294///     let info = auto_allocator::get_allocator_info();
295///     println!("Memory information:");
296///     println!("  Total memory: {}", auto_allocator::format_memory_size(info.system_info.total_memory_bytes));
297/// }
298/// ```
299///
300/// # Precision Notes
301///
302/// For performance considerations, decimal places are limited to 1 digit. For scenarios
303/// requiring higher precision, it is recommended to calculate directly using byte counts.
304#[cfg(not(target_os = "none"))]
305pub fn format_memory_size(bytes: u64) -> String {
306    use std::format;
307    
308    if bytes == 0 {
309        return "0B".to_string();
310    }
311
312    // Use bit shift calculations to avoid division operations for performance improvement
313    // Each unit has a 1024x relationship, i.e., 2^10
314    const UNITS: &[&str] = &["B", "KB", "MB", "GB", "TB", "PB"];
315
316    // Use leading zero count to quickly determine appropriate unit level
317    // leading_zeros() is a hardware-optimized instruction
318    let unit_index = if bytes >= (1u64 << 50) {
319        5
320    }
321    // >= 1PB
322    else if bytes >= (1u64 << 40) {
323        4
324    }
325    // >= 1TB
326    else if bytes >= (1u64 << 30) {
327        3
328    }
329    // >= 1GB
330    else if bytes >= (1u64 << 20) {
331        2
332    }
333    // >= 1MB
334    else if bytes >= (1u64 << 10) {
335        1
336    }
337    // >= 1KB
338    else {
339        0
340    }; // < 1KB
341
342    if unit_index == 0 {
343        format!("{}B", bytes)
344    } else {
345        let shift = unit_index * 10; // Each unit is 2^10
346        let value = bytes >> shift;
347        let remainder = bytes & ((1u64 << shift) - 1);
348
349        // Calculate decimal part (retain only 1 decimal place for performance)
350        if remainder == 0 {
351            format!("{}{}", value, UNITS[unit_index])
352        } else {
353            let fraction = (remainder * 10) >> shift;
354            if fraction == 0 {
355                format!("{}{}", value, UNITS[unit_index])
356            } else {
357                format!("{}.{}{}", value, fraction, UNITS[unit_index])
358            }
359        }
360    }
361}
362
363/// Simplified memory size formatting for no_std environments
364#[cfg(target_os = "none")]
365pub fn format_memory_size(bytes: u64) -> &'static str {
366    // For embedded systems, use predefined size categories
367    if bytes == 0 {
368        "0B"
369    } else if bytes < 1024 {
370        "<1KB"
371    } else if bytes < (1024 * 1024) {
372        "~KB"
373    } else if bytes < (1024 * 1024 * 1024) {
374        "~MB"
375    } else {
376        "~GB"
377    }
378}
379
380// ========== Platform Detection ==========
381
382/// Checks if the target is an embedded platform requiring specialized allocation
383/// 
384/// Uses `target_os = "none"` as the primary indicator of embedded/no_std environments.
385/// This approach covers all current and future embedded targets automatically,
386/// including architectures like RISC-V, ARM, AVR, MSP430, Xtensa, LoongArch, etc.
387const fn is_embedded_target() -> bool {
388    cfg!(target_os = "none")
389}
390
391/// Checks if mimalloc can be used on this platform
392const fn can_use_mimalloc() -> bool {
393    cfg!(all(
394        feature = "_mimalloc",
395        any(target_os = "windows", target_os = "macos", target_os = "linux"),
396        not(target_arch = "wasm32"),
397        not(debug_assertions)
398    ))
399}
400
401/// Checks if secure mimalloc can be used on this platform
402const fn can_use_mimalloc_secure() -> bool {
403    cfg!(all(
404        feature = "_mimalloc_secure",
405        any(target_os = "windows", target_os = "macos", target_os = "linux"),
406        not(target_arch = "wasm32"),
407        not(debug_assertions)
408    ))
409}
410
411
412
413// ========== Runtime Allocator Selection ==========
414
415// Global state for allocator selection and logging  
416// ID mapping: 0=uninitialized, 1=system, 2=mimalloc, 3=jemalloc, 4=embedded, 5=mimalloc-secure
417static RUNTIME_ALLOCATOR_ID: AtomicU8 = AtomicU8::new(0);
418#[cfg(not(target_os = "none"))]
419static ALLOCATOR_LOGGED: AtomicBool = AtomicBool::new(false);
420#[cfg(not(target_os = "none"))]
421static LOG_FLUSHED: AtomicBool = AtomicBool::new(false);
422
423/// Returns allocator ID for platforms with compile-time determinable choices
424///
425/// Returns `None` for platforms requiring runtime hardware detection (desktop systems).
426/// This optimization avoids unnecessary runtime checks for 90% of platforms.
427const fn get_compile_time_allocator() -> Option<u8> {
428    if is_embedded_target() {
429        return Some(4); // embedded-alloc
430    }
431
432    if cfg!(target_arch = "wasm32") {
433        return Some(1); // system
434    }
435
436    if cfg!(debug_assertions) {
437        return Some(1); // system (debug builds)
438    }
439
440    // Platforms with superior native allocators
441    if cfg!(target_os = "android") {
442        return Some(1); // Scudo
443    }
444
445    if cfg!(target_os = "ios") {
446        return Some(1); // libmalloc
447    }
448
449    if cfg!(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")) {
450        return Some(1); // native jemalloc/security-hardened
451    }
452
453    if cfg!(any(target_os = "solaris", target_os = "illumos")) {
454        return Some(1); // libumem
455    }
456
457    None // High-performance platforms need runtime detection
458}
459
460/// Selects allocator using compile-time rules and runtime hardware detection
461fn select_allocator_by_hardware() -> u8 {
462    if let Some(allocator_id) = get_compile_time_allocator() {
463        return allocator_id;
464    }
465
466    // Only high-performance platforms reach here - need CPU core detection
467    // Use zero-allocation CPU detection to avoid infinite recursion
468    let cpu_cores = get_cpu_cores_safe();
469
470    // Multi-core systems: prefer mimalloc (secure > regular > system)
471    if cpu_cores >= 2 && can_use_mimalloc_secure() {
472        return 5; // mimalloc-secure
473    }
474
475    // Check if mimalloc is available
476    // Since build script ensures compatibility, mimalloc is available if feature is enabled
477    if cpu_cores >= 2 && can_use_mimalloc() {
478        return 2; // mimalloc
479    }
480
481    1 // system (single-core or all high-performance allocators unavailable)
482}
483
484/// Get CPU core count without allocating memory (to avoid infinite recursion)
485fn get_cpu_cores_safe() -> usize {
486    #[cfg(unix)]
487    {
488        // Use direct libc calls to avoid std allocation
489        unsafe {
490            let cores = libc::sysconf(libc::_SC_NPROCESSORS_ONLN);
491            if cores > 0 {
492                cores as usize
493            } else {
494                1
495            }
496        }
497    }
498    
499    #[cfg(windows)]
500    {
501        // Windows: Use direct WinAPI to avoid std allocation
502        use winapi::um::sysinfoapi::{GetSystemInfo, SYSTEM_INFO};
503        unsafe {
504            let mut sysinfo: SYSTEM_INFO = std::mem::zeroed();
505            GetSystemInfo(&mut sysinfo);
506            sysinfo.dwNumberOfProcessors as usize
507        }
508    }
509    
510    #[cfg(not(any(unix, windows)))]
511    {
512        // Fallback: assume multi-core for unknown platforms
513        4
514    }
515}
516
517// ========== Embedded Heap Configuration ==========
518
519// Embedded heap configuration for all no_std targets
520#[cfg(target_os = "none")]
521mod embedded_heap_config {
522    use embedded_alloc::Heap;
523    #[cfg(not(target_os = "none"))]
524    use once_cell::sync::Lazy;
525
526    // Architecture-specific heap sizes based on typical available memory
527    // These are conservative defaults that work well for most embedded applications
528    // Users can override by defining custom heap sizes in their own code
529
530    #[cfg(target_arch = "avr")]
531    pub const HEAP_SIZE: usize = 512; // AVR (Arduino Uno): 2KB total, use 512B heap (25%)
532
533    #[cfg(target_arch = "msp430")]
534    pub const HEAP_SIZE: usize = 256; // MSP430: 1KB total, use 256B heap (25%)
535
536    #[cfg(target_arch = "riscv32")]
537    pub const HEAP_SIZE: usize = 2048; // RISC-V 32-bit: typically 32KB+, use 2KB heap (6%)
538
539    #[cfg(target_arch = "riscv64")]
540    pub const HEAP_SIZE: usize = 4096; // RISC-V 64-bit: typically 128KB+, use 4KB heap (3%)
541
542    #[cfg(target_arch = "xtensa")]
543    pub const HEAP_SIZE: usize = 4096; // Xtensa (ESP32): 256KB+, use 4KB heap (1.5%)
544
545    #[cfg(target_arch = "arm")]
546    pub const HEAP_SIZE: usize = 1024; // ARM Cortex-M: typically 16KB+, use 1KB heap (6%)
547
548    // Default heap size for other embedded architectures (LoongArch, Hexagon, BPF, SPARC, etc.)
549    #[cfg(not(any(
550        target_arch = "avr",
551        target_arch = "msp430", 
552        target_arch = "riscv32",
553        target_arch = "riscv64",
554        target_arch = "xtensa",
555        target_arch = "arm"
556    )))]
557    pub const HEAP_SIZE: usize = 2048; // Conservative default for unknown architectures
558
559    // Static memory pool for embedded heap
560    // This is a conservative allocation that should work on most embedded systems
561    pub static mut HEAP_MEMORY: [u8; HEAP_SIZE] = [0; HEAP_SIZE];
562
563    // Singleton heap instance - different implementations for std vs no_std
564    #[cfg(not(target_os = "none"))]
565    pub static EMBEDDED_HEAP: Lazy<Heap> = Lazy::new(|| unsafe { Heap::new(&mut HEAP_MEMORY[..]) });
566    
567    #[cfg(target_os = "none")]
568    static mut EMBEDDED_HEAP_INSTANCE: Option<Heap> = None;
569    
570    /// Gets the embedded heap instance for no_std environments
571    /// 
572    /// This function provides access to the global embedded heap used in no_std 
573    /// environments. The heap is lazily initialized on first access with 
574    /// architecture-appropriate size defaults.
575    /// 
576    /// # Returns
577    /// 
578    /// A reference to the static embedded heap instance
579    /// 
580    /// # Safety
581    /// 
582    /// This function is only available in no_std environments (`target_os = "none"`).
583    /// The heap initialization is done safely using static guarantees.
584    #[cfg(target_os = "none")]
585    pub fn get_embedded_heap() -> &'static Heap {
586        unsafe {
587            if EMBEDDED_HEAP_INSTANCE.is_none() {
588                let heap = Heap::empty();
589                heap.init(HEAP_MEMORY.as_mut_ptr() as usize, HEAP_SIZE);
590                EMBEDDED_HEAP_INSTANCE = Some(heap);
591            }
592            EMBEDDED_HEAP_INSTANCE.as_ref().unwrap()
593        }
594    }
595}
596
597// ========== Safe Runtime Allocator Implementation ==========
598
599pub struct RuntimeAllocator;
600
601impl RuntimeAllocator {
602    #[inline]
603    fn get_allocator_id() -> u8 {
604        let current_id = RUNTIME_ALLOCATOR_ID.load(Ordering::Acquire);
605
606        if unlikely(current_id == 0) {
607            // First call, perform hardware detection and selection
608            let selected_id = select_allocator_by_hardware();
609            RUNTIME_ALLOCATOR_ID.store(selected_id, Ordering::Release);
610
611            // Record selection information (ensure only logged once)
612            Self::log_allocator_selection(selected_id);
613
614            selected_id
615        } else {
616            current_id
617        }
618    }
619
620    #[cold]
621    #[cfg(not(target_os = "none"))]
622    fn log_allocator_selection(allocator_id: u8) {
623        if ALLOCATOR_LOGGED
624            .compare_exchange(false, true, Ordering::AcqRel, Ordering::Acquire)
625            .is_ok()
626        {
627            let (name, reason) = Self::get_allocator_log_info(allocator_id);
628            record_allocator_selection(name, &reason);
629        }
630    }
631
632    #[cold]
633    #[cfg(target_os = "none")]
634    fn log_allocator_selection(_allocator_id: u8) {
635        // No logging in no_std environments
636    }
637
638    /// Get logging information based on allocator ID and compile-time platform detection
639    #[cfg(not(target_os = "none"))]
640    fn get_allocator_log_info(allocator_id: u8) -> (&'static str, String) {
641        match allocator_id {
642            5 => {
643                let system_info = collect_system_info();
644                ("mimalloc-secure", format!(
645                    "security-hardened choice - runtime detected ({} cores, {} total RAM)",
646                    system_info.cpu_cores,
647                    format_memory_size(system_info.total_memory_bytes)
648                ))
649            },
650            2 => {
651                let system_info = collect_system_info();
652                ("mimalloc", format!(
653                    "optimal performance choice - runtime detected ({} cores, {} total RAM)",
654                    system_info.cpu_cores,
655                    format_memory_size(system_info.total_memory_bytes)
656                ))
657            },
658            4 => {
659                let system_info = collect_system_info();
660                ("embedded-alloc", format!(
661                    "embedded platform - compile-time selected ({} total RAM)",
662                    format_memory_size(system_info.total_memory_bytes)
663                ))
664            },
665            _ => {
666                // System allocator - determine reason based on compile-time platform detection
667                if cfg!(debug_assertions) {
668                    let system_info = collect_system_info();
669                    ("system", format!(
670                        "debug build - compile-time selected ({} cores, {} total RAM)",
671                        system_info.cpu_cores,
672                        format_memory_size(system_info.total_memory_bytes)
673                    ))
674                } else if cfg!(target_arch = "wasm32") {
675                    let system_info = collect_system_info();
676                    ("system", format!(
677                        "WASM environment - compile-time selected ({} total RAM)",
678                        format_memory_size(system_info.total_memory_bytes)
679                    ))
680                } else if cfg!(target_os = "android") {
681                    let system_info = collect_system_info();
682                    ("system", format!(
683                        "Android Scudo allocator - compile-time selected (security-first policy) ({} cores, {} total RAM)",
684                        system_info.cpu_cores,
685                        format_memory_size(system_info.total_memory_bytes)
686                    ))
687                } else if cfg!(target_os = "ios") {
688                    let system_info = collect_system_info();
689                    ("system", format!(
690                        "iOS libmalloc allocator - compile-time selected (Apple optimized) ({} cores, {} total RAM)",
691                        system_info.cpu_cores,
692                        format_memory_size(system_info.total_memory_bytes)
693                    ))
694                } else if cfg!(any(target_os = "freebsd", target_os = "netbsd")) {
695                    let system_info = collect_system_info();
696                    ("system", format!(
697                        "BSD native jemalloc - compile-time selected (platform optimized) ({} cores, {} total RAM)",
698                        system_info.cpu_cores,
699                        format_memory_size(system_info.total_memory_bytes)
700                    ))
701                } else if cfg!(target_os = "openbsd") {
702                    let system_info = collect_system_info();
703                    ("system", format!(
704                        "OpenBSD security-hardened allocator - compile-time selected ({} cores, {} total RAM)",
705                        system_info.cpu_cores,
706                        format_memory_size(system_info.total_memory_bytes)
707                    ))
708                } else if cfg!(any(target_os = "solaris", target_os = "illumos")) {
709                    let system_info = collect_system_info();
710                    ("system", format!(
711                        "Solaris libumem allocator - compile-time selected (enterprise grade) ({} cores, {} total RAM)",
712                        system_info.cpu_cores,
713                        format_memory_size(system_info.total_memory_bytes)
714                    ))
715                } else {
716                    // High-performance platforms that fell back to system (single-core or mimalloc unavailable)
717                    let system_info = collect_system_info();
718                    ("system", format!(
719                        "runtime fallback - single-core or mimalloc unavailable ({} cores, {} total RAM)",
720                        system_info.cpu_cores,
721                        format_memory_size(system_info.total_memory_bytes)
722                    ))
723                }
724            },
725        }
726    }
727}
728
729// Branch prediction optimization
730#[inline(always)]
731fn unlikely(b: bool) -> bool {
732    #[cold]
733    fn cold() {}
734    if b {
735        cold();
736    }
737    b
738}
739
740// ========== Global Allocator Implementation - Platform-specific VTable handling ==========
741
742unsafe impl GlobalAlloc for RuntimeAllocator {
743    #[inline]
744    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
745        match Self::get_allocator_id() {
746
747            // mimalloc-secure - security-hardened allocator with 10% performance overhead
748            #[cfg(all(
749                feature = "_mimalloc_secure",
750                not(target_arch = "wasm32"),
751                not(debug_assertions),
752                not(target_os = "none")
753            ))]
754            5 => {
755                use mimalloc::MiMalloc;
756                MiMalloc.alloc(layout)
757            }
758
759            // mimalloc - high-performance allocator with compiler compatibility detection
760            #[cfg(all(
761                feature = "_mimalloc",
762                not(target_arch = "wasm32"),
763                not(debug_assertions),
764                not(target_os = "none")
765            ))]
766            2 => {
767                use mimalloc::MiMalloc;
768                MiMalloc.alloc(layout)
769            }
770
771            // embedded-alloc - for all no_std embedded platforms
772            #[cfg(all(
773                feature = "_embedded",
774                target_os = "none"
775            ))]
776            4 => {
777                // Use embedded-alloc for all no_std targets
778                #[cfg(not(target_os = "none"))]
779                {
780                    embedded_heap_config::EMBEDDED_HEAP.alloc(layout)
781                }
782                #[cfg(target_os = "none")]
783                {
784                    embedded_heap_config::get_embedded_heap().alloc(layout)
785                }
786            }
787
788            // System allocator - default fallback
789            #[cfg(not(target_os = "none"))]
790            _ => alloc::System.alloc(layout),
791            
792            #[cfg(target_os = "none")]
793            _ => core::ptr::null_mut(),
794        }
795    }
796
797    #[inline]
798    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
799        match Self::get_allocator_id() {
800
801            // mimalloc-secure - security-hardened allocator
802            #[cfg(all(
803                feature = "_mimalloc_secure",
804                not(target_arch = "wasm32"),
805                not(debug_assertions),
806                not(target_os = "none")
807            ))]
808            5 => {
809                use mimalloc::MiMalloc;
810                MiMalloc.dealloc(ptr, layout)
811            }
812
813            // mimalloc - high-performance allocator with compiler compatibility detection
814            #[cfg(all(
815                feature = "_mimalloc",
816                not(target_arch = "wasm32"),
817                not(debug_assertions),
818                not(target_os = "none")
819            ))]
820            2 => {
821                use mimalloc::MiMalloc;
822                MiMalloc.dealloc(ptr, layout)
823            }
824
825            #[cfg(all(
826                feature = "_embedded",
827                target_os = "none"
828            ))]
829            4 => {
830                // Use embedded-alloc for all no_std targets
831                #[cfg(not(target_os = "none"))]
832                {
833                    embedded_heap_config::EMBEDDED_HEAP.dealloc(ptr, layout)
834                }
835                #[cfg(target_os = "none")]
836                {
837                    embedded_heap_config::get_embedded_heap().dealloc(ptr, layout)
838                }
839            }
840
841            #[cfg(not(target_os = "none"))]
842            _ => alloc::System.dealloc(ptr, layout),
843            
844            #[cfg(target_os = "none")]
845            _ => {},
846        }
847    }
848}
849
850#[global_allocator]
851static GLOBAL: RuntimeAllocator = RuntimeAllocator;
852
853// ========== Logging System ==========
854
855#[cfg(not(target_os = "none"))]
856static PENDING_LOG_MESSAGE: Lazy<std::sync::Mutex<Option<String>>> =
857    Lazy::new(|| std::sync::Mutex::new(None));
858
859/// Records allocator selection using a dual logging strategy
860///
861/// Immediately outputs to stderr (safe during global allocator init) and 
862/// saves for later output through the logging framework when available.
863#[cfg(not(target_os = "none"))]
864fn record_allocator_selection(allocator_name: &str, reason: &str) {
865    let message = format!("Auto-allocator: {} selected - {}", allocator_name, reason);
866
867    // Immediate output to stderr (only safe method in global allocator)
868    #[cfg(unix)]
869    {
870        let stderr_message = format!("[INFO] {}\n", message);
871        unsafe {
872            libc::write(
873                2,
874                stderr_message.as_ptr() as *const libc::c_void,
875                stderr_message.len(),
876            );
877        }
878    }
879
880    // Save message, output later through logging framework
881    if let Ok(mut pending) = PENDING_LOG_MESSAGE.lock() {
882        *pending = Some(message);
883    }
884}
885
886/// Attempts to flush pending log message to the logging framework
887#[cfg(not(target_os = "none"))]
888fn try_flush_pending_log() {
889    if !LOG_FLUSHED.load(Ordering::Relaxed) {
890        if let Ok(mut pending) = PENDING_LOG_MESSAGE.lock() {
891            if let Some(message) = pending.take() {
892                let _ = std::panic::catch_unwind(|| {
893                    info!("{}", message);
894                });
895                LOG_FLUSHED.store(true, Ordering::Relaxed);
896            }
897        }
898    }
899}
900
901/// Intelligently flushes logs when the logging framework becomes available
902#[cfg(not(target_os = "none"))]
903fn smart_try_flush_log() {
904    // If already output, no need to try again
905    if LOG_FLUSHED.load(Ordering::Relaxed) {
906        return;
907    }
908
909    // Try to output log
910    try_flush_pending_log();
911
912    // If still not successful, logging framework is not yet initialized
913    // Will continue trying on next call
914}
915
916// ========== System Information Collection ==========
917
918#[cfg(not(target_os = "none"))]
919fn collect_system_info() -> SystemInfo {
920    let total_memory = get_total_memory_safe();
921    SystemInfo {
922        os_type: std::env::consts::OS.to_string(),
923        cpu_cores: std::thread::available_parallelism()
924            .map(|n| n.get())
925            .unwrap_or(1),
926        total_memory_bytes: total_memory,
927        is_debug: cfg!(debug_assertions),
928        is_wasm: cfg!(target_arch = "wasm32"),
929        target_arch: std::env::consts::ARCH.to_string(),
930    }
931}
932
933/// Simplified system info collection for no_std environments
934#[cfg(target_os = "none")]
935fn collect_system_info() -> SystemInfo {
936    let total_memory = get_total_memory_safe();
937    SystemInfo {
938        os_type: "embedded",
939        cpu_cores: 1, // Assume single core for embedded
940        total_memory_bytes: total_memory,
941        is_debug: cfg!(debug_assertions),
942        is_wasm: false,
943        target_arch: {
944            #[cfg(target_arch = "riscv32")]
945            { "riscv32" }
946            #[cfg(target_arch = "riscv64")]
947            { "riscv64" }
948            #[cfg(target_arch = "arm")]
949            { "arm" }
950            #[cfg(target_arch = "avr")]
951            { "avr" }
952            #[cfg(target_arch = "msp430")]
953            { "msp430" }
954            #[cfg(target_arch = "xtensa")]
955            { "xtensa" }
956            #[cfg(not(any(
957                target_arch = "riscv32",
958                target_arch = "riscv64", 
959                target_arch = "arm",
960                target_arch = "avr",
961                target_arch = "msp430",
962                target_arch = "xtensa"
963            )))]
964            { "unknown" }
965        },
966    }
967}
968
969/// Detects total system memory without allocating during global allocator initialization
970///
971/// Uses platform-specific APIs for servers/desktop systems and conservative defaults for embedded platforms.
972/// Critical: This function must not allocate memory as it's called during global allocator setup.
973#[allow(unreachable_code)]
974fn get_total_memory_safe() -> u64 {
975    #[cfg(target_arch = "wasm32")]
976    {
977        // WASM can dynamically detect memory through core::arch::wasm32
978        use core::arch::wasm32;
979
980        // Get current memory pages, each page is 64KB
981        let pages = wasm32::memory_size(0); // Memory index 0 is default memory
982        let total_bytes = (pages as u64) * 65536;
983
984        return total_bytes;
985    }
986
987    #[cfg(target_os = "macos")]
988    {
989        // macOS: use sysctl(HW_MEMSIZE)
990        unsafe {
991            let mut total_size: u64 = 0;
992            let mut mib = [libc::CTL_HW, libc::HW_MEMSIZE];
993            let mut len = std::mem::size_of::<u64>();
994
995            if libc::sysctl(
996                mib.as_mut_ptr(),
997                2,
998                &mut total_size as *mut _ as *mut libc::c_void,
999                &mut len,
1000                std::ptr::null_mut(),
1001                0,
1002            ) == 0
1003            {
1004                return total_size;
1005            } else {
1006                return 16u64 << 30; // Fallback: 16GB default
1007            }
1008        }
1009    }
1010
1011    #[cfg(all(target_os = "linux", not(target_arch = "wasm32")))]
1012    {
1013        // Linux: use sysinfo() system call
1014        unsafe {
1015            let mut info: libc::sysinfo = std::mem::zeroed();
1016            if libc::sysinfo(&mut info) == 0 {
1017                let total = info.totalram as u64 * info.mem_unit as u64;
1018                return total;
1019            }
1020        }
1021    }
1022
1023    #[cfg(target_os = "windows")]
1024    {
1025        use std::mem;
1026        use winapi::um::sysinfoapi::{GlobalMemoryStatusEx, MEMORYSTATUSEX};
1027        unsafe {
1028            let mut mem_status: MEMORYSTATUSEX = mem::zeroed();
1029            mem_status.dwLength = mem::size_of::<MEMORYSTATUSEX>() as u32;
1030            if GlobalMemoryStatusEx(&mut mem_status) != 0 {
1031                return mem_status.ullTotalPhys;
1032            }
1033        }
1034    }
1035
1036    // Embedded platforms: conservative memory size estimates
1037    #[cfg(target_arch = "avr")]
1038    {
1039        return 2u64 << 10; // 2KB for AVR (like Arduino Uno with 2KB RAM)
1040    }
1041
1042    #[cfg(target_arch = "msp430")]
1043    {
1044        return 1u64 << 10; // 1KB for MSP430 (typical low-power MCU)
1045    }
1046
1047    #[cfg(target_arch = "riscv32")]
1048    {
1049        return 32u64 << 10; // 32KB for RISC-V MCUs (like ESP32-C3 type devices)
1050    }
1051
1052    #[cfg(target_arch = "riscv64")]
1053    {
1054        return 128u64 << 10; // 128KB for RISC-V 64-bit systems (like our QEMU example)
1055    }
1056
1057    #[cfg(target_arch = "xtensa")]
1058    {
1059        return 256u64 << 10; // 256KB for Xtensa (like ESP32 with up to 520KB)
1060    }
1061
1062    #[cfg(all(target_arch = "arm", target_os = "none"))]
1063    {
1064        return 16u64 << 10; // 16KB for ARM Cortex-M (conservative estimate, M0+ typically has this capacity)
1065    }
1066
1067    // Default for unknown platforms
1068    2u64 << 30
1069}
1070
1071// No_std versions of log functions
1072#[cfg(target_os = "none")]
1073fn smart_try_flush_log() {
1074    // No logging in no_std
1075}
1076
1077// ========== Runtime Allocator Information ==========
1078
1079#[cfg(not(target_os = "none"))]
1080static ALLOCATOR_INFO: Lazy<AllocatorInfo> = Lazy::new(|| {
1081    let system_info = collect_system_info();
1082    let allocator_id = RUNTIME_ALLOCATOR_ID.load(Ordering::Acquire);
1083
1084    // If not yet initialized, trigger allocator selection once
1085    let final_allocator_id = if allocator_id == 0 {
1086        RuntimeAllocator::get_allocator_id()
1087    } else {
1088        allocator_id
1089    };
1090
1091    let (_, mut reason) = get_allocator_selection_result(&system_info);
1092
1093    // Determine type based on actually selected allocator ID (may differ due to feature disable)
1094    let allocator_type = match final_allocator_id {
1095        5 => AllocatorType::MimallocSecure,
1096        2 => AllocatorType::Mimalloc,
1097        4 => AllocatorType::EmbeddedHeap,
1098        _ => AllocatorType::System,
1099    };
1100
1101    // Add "selected by runtime analysis" prefix to actual allocator info, extract hardware info part
1102    let hardware_info = if reason.contains('(') && reason.contains(')') {
1103        reason
1104            .split_once('(')
1105            .and_then(|(_prefix, suffix)| suffix.split_once(')').map(|(info, _)| info))
1106            .unwrap_or("")
1107    } else {
1108        ""
1109    };
1110
1111    reason = match final_allocator_id {
1112        5 => format!(
1113            "mimalloc-secure selected by runtime hardware analysis ({})",
1114            hardware_info
1115        ),
1116        2 => format!(
1117            "mimalloc selected by runtime hardware analysis ({})",
1118            hardware_info
1119        ),
1120        4 => {
1121            // For embedded allocator, preserve the original compile-time selection info
1122            reason
1123        },
1124        _ => {
1125            // For system allocator, preserve the original detailed reason as-is
1126            // (already includes correct "compile-time selected" or platform-specific info)
1127            reason
1128        },
1129    };
1130
1131    AllocatorInfo {
1132        allocator_type,
1133        reason,
1134        system_info,
1135    }
1136});
1137
1138// Simplified allocator info for no_std
1139#[cfg(target_os = "none")]
1140static mut EMBEDDED_ALLOCATOR_INFO: Option<AllocatorInfo> = None;
1141
1142// ========== Public API ==========
1143
1144/// Ensure allocator information is ready
1145/// Internal function, ensures ALLOCATOR_INFO has been computed
1146#[cfg(not(target_os = "none"))]
1147fn ensure_allocator_info_ready() {
1148    let _ = std::panic::catch_unwind(|| {
1149        Lazy::force(&ALLOCATOR_INFO);
1150    });
1151}
1152
1153#[cfg(target_os = "none")]
1154fn ensure_allocator_info_ready() {
1155    unsafe {
1156        if EMBEDDED_ALLOCATOR_INFO.is_none() {
1157            let system_info = collect_system_info();
1158            EMBEDDED_ALLOCATOR_INFO = Some(AllocatorInfo {
1159                allocator_type: AllocatorType::EmbeddedHeap,
1160                reason: "embedded-alloc selected for no_std environment",
1161                system_info,
1162            });
1163        }
1164    }
1165}
1166
1167/// Returns information about the automatically selected allocator
1168///
1169/// Provides allocator type, selection rationale, and system information.
1170/// First call triggers hardware detection; subsequent calls return cached results.
1171///
1172/// # Example
1173///
1174/// ```rust
1175/// use auto_allocator;
1176///
1177/// let info = auto_allocator::get_allocator_info();
1178/// println!("Using: {:?}", info.allocator_type);
1179/// println!("Reason: {}", info.reason);
1180/// ```
1181#[cfg(not(target_os = "none"))]
1182pub fn get_allocator_info() -> &'static AllocatorInfo {
1183    smart_try_flush_log();
1184    ensure_allocator_info_ready();
1185    &ALLOCATOR_INFO
1186}
1187
1188#[cfg(target_os = "none")]
1189pub fn get_allocator_info() -> &'static AllocatorInfo {
1190    ensure_allocator_info_ready();
1191    unsafe { EMBEDDED_ALLOCATOR_INFO.as_ref().unwrap() }
1192}
1193
1194/// Get current allocator type
1195///
1196/// Returns the currently used allocator type, this is a simplified version of [`get_allocator_info()`].
1197/// If you only need to know the allocator type without other information, using this function is more concise.
1198///
1199/// # Return Value
1200///
1201/// Returns [`AllocatorType`] enum value, possible values:
1202/// - [`AllocatorType::Mimalloc`] - Microsoft-developed high-performance allocator
1203/// - [`AllocatorType::EmbeddedHeap`] - Embedded systems specific allocator
1204/// - [`AllocatorType::System`] - System default allocator
1205///
1206/// # Example
1207///
1208/// ```rust
1209/// use auto_allocator;
1210///
1211/// let allocator_type = auto_allocator::get_allocator_type();
1212///
1213/// // Simple allocator type check
1214/// if allocator_type == auto_allocator::AllocatorType::Mimalloc {
1215///     println!("Using high-performance mimalloc allocator");
1216/// }
1217///
1218/// // Or use match statement
1219/// match allocator_type {
1220///     auto_allocator::AllocatorType::Mimalloc => {
1221///         println!("mimalloc - optimal performance");
1222///     }
1223///     auto_allocator::AllocatorType::System => {
1224///         println!("system - maximum compatibility");
1225///     }
1226///     _ => println!("other allocator"),
1227/// }
1228/// ```
1229///
1230/// # Performance Notes
1231///
1232/// This function is slightly faster than [`get_allocator_info()`] because it only returns type information.
1233pub fn get_allocator_type() -> AllocatorType {
1234    smart_try_flush_log();
1235    ensure_allocator_info_ready();
1236    get_allocator_info().allocator_type
1237}
1238
1239/// Get allocator selection result and reason (internal function)
1240#[cfg(not(target_os = "none"))]
1241fn get_allocator_selection_result(system_info: &SystemInfo) -> (AllocatorType, String) {
1242    let total_mem = format_memory_size(system_info.total_memory_bytes);
1243
1244    if system_info.is_wasm {
1245        (
1246            AllocatorType::System,
1247            format!("system allocator - WASM environment ({} total RAM)", total_mem),
1248        )
1249    } else if system_info.is_debug {
1250        (
1251            AllocatorType::System,
1252            format!(
1253                "system allocator - debug build ({} cores, {} total RAM)",
1254                system_info.cpu_cores, total_mem
1255            ),
1256        )
1257    } else if is_embedded_target() {
1258        (
1259            AllocatorType::EmbeddedHeap,
1260            format!("embedded-alloc allocator - embedded environment ({} total RAM)", total_mem),
1261        )
1262    } else if system_info.os_type == "android" {
1263        (
1264            AllocatorType::System,
1265            format!(
1266                "Android platform - Scudo allocator (security-first, use-after-free protection) ({} cores, {} total RAM)",
1267                system_info.cpu_cores, total_mem
1268            ),
1269        )
1270    } else if system_info.os_type == "ios" {
1271        (
1272            AllocatorType::System,
1273            format!(
1274                "iOS platform - libmalloc allocator (Apple-optimized, memory pressure handling) ({} cores, {} total RAM)",
1275                system_info.cpu_cores, total_mem
1276            ),
1277        )
1278    } else if system_info.os_type == "freebsd" || system_info.os_type == "netbsd" {
1279        (
1280            AllocatorType::System,
1281            format!(
1282                "BSD platform - native jemalloc (highly optimized, deep system integration) ({} cores, {} total RAM)",
1283                system_info.cpu_cores, total_mem
1284            ),
1285        )
1286    } else if system_info.os_type == "openbsd" {
1287        (
1288            AllocatorType::System,
1289            format!(
1290                "OpenBSD platform - security-hardened allocator (exploit mitigation, aggressive hardening) ({} cores, {} total RAM)",
1291                system_info.cpu_cores, total_mem
1292            ),
1293        )
1294    } else if system_info.os_type == "solaris" || system_info.os_type == "illumos" {
1295        (
1296            AllocatorType::System,
1297            format!(
1298                "Solaris platform - libumem allocator (NUMA-aware, enterprise-grade performance) ({} cores, {} total RAM)",
1299                system_info.cpu_cores, total_mem
1300            ),
1301        )
1302    } else if system_info.cpu_cores >= 2 {
1303        (
1304            AllocatorType::Mimalloc,
1305            format!(
1306                "mimalloc allocator - high-performance multi-threaded environment ({} cores, {} total RAM)",
1307                system_info.cpu_cores, total_mem
1308            ),
1309        )
1310    } else {
1311        (
1312            AllocatorType::System,
1313            format!(
1314                "system allocator - low-performance environment ({} cores, {} total RAM)",
1315                system_info.cpu_cores, total_mem
1316            ),
1317        )
1318    }
1319}
1320
1321/// Simplified allocator selection for no_std environments
1322#[cfg(target_os = "none")]
1323fn get_allocator_selection_result(_system_info: &SystemInfo) -> (AllocatorType, &'static str) {
1324    (AllocatorType::EmbeddedHeap, "embedded-alloc selected for no_std environment")
1325}
1326
1327/// Get recommended allocator for current runtime environment
1328///
1329/// Based on current system hardware and environment re-analysis, returns recommended allocator type and selection reason.
1330/// Unlike [`get_allocator_info()`], this function re-performs hardware detection and analysis every time.
1331///
1332/// # Return Value
1333///
1334/// Returns a tuple `(AllocatorType, String)`:
1335/// - First element: recommended allocator type
1336/// - Second element: recommendation reason, including hardware information
1337///
1338/// # Usage
1339///
1340/// This function is mainly used for:
1341/// - Performance analysis and optimization recommendations
1342/// - Verifying if current allocator selection is optimal
1343/// - Re-evaluation after runtime environment changes
1344///
1345/// # Examples
1346///
1347/// ```rust
1348/// use auto_allocator;
1349///
1350/// let (recommended_type, reason) = auto_allocator::get_recommended_allocator();
1351///
1352/// println!("Recommended allocator: {:?}", recommended_type);
1353/// println!("Recommendation reason: {}", reason);
1354///
1355/// // Compare with current allocator
1356/// let current_type = auto_allocator::get_allocator_type();
1357/// if current_type == recommended_type {
1358///     println!("Current allocator is already optimal");
1359/// } else {
1360///     println!("Suggest switching to: {:?}", recommended_type);
1361/// }
1362/// ```
1363///
1364/// # Performance Notes
1365///
1366/// This function re-performs system hardware detection, with slightly higher overhead than [`get_allocator_info()`].
1367#[cfg(not(target_os = "none"))]
1368pub fn get_recommended_allocator() -> (AllocatorType, String) {
1369    smart_try_flush_log();
1370    let system_info = collect_system_info();
1371    get_allocator_selection_result(&system_info)
1372}
1373
1374#[cfg(target_os = "none")]
1375pub fn get_recommended_allocator() -> (AllocatorType, &'static str) {
1376    let system_info = collect_system_info();
1377    get_allocator_selection_result(&system_info)
1378}
1379
1380/// Check if current allocator is optimal for current environment
1381///
1382/// Compares currently used allocator with hardware environment recommended allocator,
1383/// determining if the best allocator has already been selected.
1384/// Used for performance optimization checks and configuration validation.
1385///
1386/// # Return Value
1387///
1388/// Returns a tuple `(bool, Option<String>)`:
1389/// - `(true, None)` - Current allocator is already optimal
1390/// - `(false, Some(suggestion))` - Current allocator is not optimal, includes optimization suggestion
1391///
1392/// # Usage
1393///
1394/// - **Performance audit** - Check if application uses optimal allocator
1395/// - **Environment validation** - Confirm allocator configuration in deployment environment
1396/// - **Optimization suggestions** - Get specific allocator optimization recommendations
1397/// - **Monitoring integration** - Integrate into monitoring systems to check configuration drift
1398///
1399/// # Examples
1400///
1401/// ```rust
1402/// use auto_allocator;
1403///
1404/// let (is_optimal, suggestion) = auto_allocator::check_allocator_optimization();
1405///
1406/// if is_optimal {
1407///     println!("✅ Current allocator configuration is optimal");
1408/// } else if let Some(advice) = suggestion {
1409///     println!("⚠️  Allocator configuration can be optimized:");
1410///     println!("   {}", advice);
1411/// }
1412/// ```
1413///
1414/// # Practical Application Scenarios
1415///
1416/// ```rust
1417/// use auto_allocator;
1418///
1419/// // Check allocator configuration at application startup
1420/// fn check_performance_config() {
1421///     let (is_optimal, suggestion) = auto_allocator::check_allocator_optimization();
1422///     
1423///     if !is_optimal {
1424///         eprintln!("Warning: {}", suggestion.unwrap_or_default());
1425///         eprintln!("Recommend compiling in Release mode for optimal performance");
1426///     }
1427/// }
1428///
1429/// // Validate configuration in CI/CD
1430/// fn test_allocator_optimization() {
1431///     let (is_optimal, _) = auto_allocator::check_allocator_optimization();
1432///     assert!(is_optimal, "Allocator configuration not optimized to best state");
1433/// }
1434/// ```
1435///
1436/// # Performance Notes
1437///
1438/// This function needs to re-detect hardware and compare allocators, with slightly higher overhead than simple information retrieval functions.
1439#[cfg(not(target_os = "none"))]
1440pub fn check_allocator_optimization() -> (bool, Option<String>) {
1441    smart_try_flush_log();
1442    let current = get_allocator_type();
1443    let (recommended, reason) = get_recommended_allocator();
1444
1445    if current == recommended {
1446        (true, None)
1447    } else {
1448        let suggestion = format!(
1449            "Current: {:?}, Recommended: {:?} ({})",
1450            current, recommended, reason
1451        );
1452        (false, Some(suggestion))
1453    }
1454}
1455
1456#[cfg(target_os = "none")]
1457pub fn check_allocator_optimization() -> (bool, Option<&'static str>) {
1458    // In no_std, always optimal (embedded-alloc)
1459    (true, None)
1460}
1461
1462// WASM environment initialization
1463#[cfg(target_arch = "wasm32")]
1464use wasm_bindgen::prelude::*;
1465
1466/// Automatically initializes allocator information when WASM module loads
1467///
1468/// This function is called automatically via `#[wasm_bindgen(start)]` - no manual invocation needed.
1469#[cfg(target_arch = "wasm32")]
1470#[wasm_bindgen(start)]
1471pub fn wasm_auto_init() {
1472    ensure_allocator_info_ready();
1473}
1474