ruviz 0.4.2

High-performance 2D plotting library for Rust
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
//! Windows-specific memory optimization implementations

use crate::core::error::PlottingError;
use std::mem;
use std::ptr;

// Windows API types and constants
type DWORD = u32;
type DWORDLONG = u64;
type HANDLE = *mut std::ffi::c_void;
type BOOL = i32;

const TRUE: BOOL = 1;
const FALSE: BOOL = 0;

#[repr(C)]
struct MEMORYSTATUSEX {
    dwLength: DWORD,
    dwMemoryLoad: DWORD,
    ullTotalPhys: DWORDLONG,
    ullAvailPhys: DWORDLONG,
    ullTotalPageFile: DWORDLONG,
    ullAvailPageFile: DWORDLONG,
    ullTotalVirtual: DWORDLONG,
    ullAvailVirtual: DWORDLONG,
    ullAvailExtendedVirtual: DWORDLONG,
}

#[repr(C)]
struct SYSTEM_INFO {
    wProcessorArchitecture: u16,
    wReserved: u16,
    dwPageSize: DWORD,
    lpMinimumApplicationAddress: *mut std::ffi::c_void,
    lpMaximumApplicationAddress: *mut std::ffi::c_void,
    dwActiveProcessorMask: usize,
    dwNumberOfProcessors: DWORD,
    dwProcessorType: DWORD,
    dwAllocationGranularity: DWORD,
    wProcessorLevel: u16,
    wProcessorRevision: u16,
}

#[repr(C)]
struct PERFORMANCE_INFORMATION {
    cb: DWORD,
    CommitTotal: usize,
    CommitLimit: usize,
    CommitPeak: usize,
    PhysicalTotal: usize,
    PhysicalAvailable: usize,
    SystemCache: usize,
    KernelTotal: usize,
    KernelPaged: usize,
    KernelNonpaged: usize,
    PageSize: usize,
    HandleCount: DWORD,
    ProcessCount: DWORD,
    ThreadCount: DWORD,
}

// SAFETY: These are FFI declarations for stable Win32 APIs. Callers validate
// all pointers, sizes, and return codes at each call site.
unsafe extern "system" {
    fn GlobalMemoryStatusEx(lpBuffer: *mut MEMORYSTATUSEX) -> BOOL;
    fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO) -> ();
    fn GetPerformanceInfo(pPerformanceInformation: *mut PERFORMANCE_INFORMATION, cb: DWORD)
    -> BOOL;
    fn GetCurrentProcess() -> HANDLE;
    fn SetProcessWorkingSetSize(
        hProcess: HANDLE,
        dwMinimumWorkingSetSize: usize,
        dwMaximumWorkingSetSize: usize,
    ) -> BOOL;
    fn GetLogicalProcessorInformation(
        Buffer: *mut std::ffi::c_void,
        ReturnedLength: *mut DWORD,
    ) -> BOOL;
    fn GetLargePageMinimum() -> usize;
    fn VirtualAlloc(
        lpAddress: *mut std::ffi::c_void,
        dwSize: usize,
        flAllocationType: DWORD,
        flProtect: DWORD,
    ) -> *mut std::ffi::c_void;
    fn VirtualFree(lpAddress: *mut std::ffi::c_void, dwSize: usize, dwFreeType: DWORD) -> BOOL;
}

// Memory allocation constants
const MEM_COMMIT: DWORD = 0x1000;
const MEM_RESERVE: DWORD = 0x2000;
const MEM_LARGE_PAGES: DWORD = 0x20000000;
const MEM_RELEASE: DWORD = 0x8000;
const PAGE_READWRITE: DWORD = 0x04;

/// Get total system memory on Windows
pub fn get_total_memory() -> Result<u64, PlottingError> {
    // SAFETY: `memory_status` is a valid initialized struct with correct
    // `dwLength`; Windows API writes into provided mutable pointer.
    unsafe {
        let mut memory_status: MEMORYSTATUSEX = mem::zeroed();
        memory_status.dwLength = mem::size_of::<MEMORYSTATUSEX>() as DWORD;

        let result = GlobalMemoryStatusEx(&mut memory_status);
        if result != FALSE {
            Ok(memory_status.ullTotalPhys)
        } else {
            Err(PlottingError::SystemError(
                "Failed to get total memory".to_string(),
            ))
        }
    }
}

/// Get available system memory on Windows
pub fn get_available_memory() -> Result<u64, PlottingError> {
    // SAFETY: same contract as `get_total_memory`; output buffer and size are valid.
    unsafe {
        let mut memory_status: MEMORYSTATUSEX = mem::zeroed();
        memory_status.dwLength = mem::size_of::<MEMORYSTATUSEX>() as DWORD;

        let result = GlobalMemoryStatusEx(&mut memory_status);
        if result != FALSE {
            Ok(memory_status.ullAvailPhys)
        } else {
            Err(PlottingError::SystemError(
                "Failed to get available memory".to_string(),
            ))
        }
    }
}

/// Get detailed memory status on Windows
pub fn get_memory_status() -> Result<WindowsMemoryStatus, PlottingError> {
    // SAFETY: same contract as `get_total_memory`; output buffer and size are valid.
    unsafe {
        let mut memory_status: MEMORYSTATUSEX = mem::zeroed();
        memory_status.dwLength = mem::size_of::<MEMORYSTATUSEX>() as DWORD;

        let result = GlobalMemoryStatusEx(&mut memory_status);
        if result != FALSE {
            Ok(WindowsMemoryStatus {
                memory_load: memory_status.dwMemoryLoad,
                total_physical: memory_status.ullTotalPhys,
                available_physical: memory_status.ullAvailPhys,
                total_page_file: memory_status.ullTotalPageFile,
                available_page_file: memory_status.ullAvailPageFile,
                total_virtual: memory_status.ullTotalVirtual,
                available_virtual: memory_status.ullAvailVirtual,
                available_extended_virtual: memory_status.ullAvailExtendedVirtual,
            })
        } else {
            Err(PlottingError::SystemError(
                "Failed to get memory status".to_string(),
            ))
        }
    }
}

/// Get performance information on Windows
pub fn get_performance_info() -> Result<WindowsPerformanceInfo, PlottingError> {
    // SAFETY: `perf_info` is properly sized and mutable for `GetPerformanceInfo`.
    unsafe {
        let mut perf_info: PERFORMANCE_INFORMATION = mem::zeroed();
        perf_info.cb = mem::size_of::<PERFORMANCE_INFORMATION>() as DWORD;

        let result = GetPerformanceInfo(&mut perf_info, perf_info.cb);
        if result != FALSE {
            Ok(WindowsPerformanceInfo {
                commit_total: perf_info.CommitTotal * perf_info.PageSize,
                commit_limit: perf_info.CommitLimit * perf_info.PageSize,
                commit_peak: perf_info.CommitPeak * perf_info.PageSize,
                physical_total: perf_info.PhysicalTotal * perf_info.PageSize,
                physical_available: perf_info.PhysicalAvailable * perf_info.PageSize,
                system_cache: perf_info.SystemCache * perf_info.PageSize,
                kernel_total: perf_info.KernelTotal * perf_info.PageSize,
                kernel_paged: perf_info.KernelPaged * perf_info.PageSize,
                kernel_nonpaged: perf_info.KernelNonpaged * perf_info.PageSize,
                page_size: perf_info.PageSize,
                handle_count: perf_info.HandleCount,
                process_count: perf_info.ProcessCount,
                thread_count: perf_info.ThreadCount,
            })
        } else {
            Err(PlottingError::SystemError(
                "Failed to get performance info".to_string(),
            ))
        }
    }
}

/// Get system information on Windows
pub fn get_system_info() -> Result<WindowsSystemInfo, PlottingError> {
    // SAFETY: `GetSystemInfo` expects a valid mutable pointer to `SYSTEM_INFO`.
    unsafe {
        let mut sys_info: SYSTEM_INFO = mem::zeroed();
        GetSystemInfo(&mut sys_info);

        Ok(WindowsSystemInfo {
            processor_architecture: sys_info.wProcessorArchitecture,
            page_size: sys_info.dwPageSize as usize,
            minimum_application_address: sys_info.lpMinimumApplicationAddress as usize,
            maximum_application_address: sys_info.lpMaximumApplicationAddress as usize,
            active_processor_mask: sys_info.dwActiveProcessorMask,
            number_of_processors: sys_info.dwNumberOfProcessors as usize,
            processor_type: sys_info.dwProcessorType,
            allocation_granularity: sys_info.dwAllocationGranularity as usize,
            processor_level: sys_info.wProcessorLevel,
            processor_revision: sys_info.wProcessorRevision,
        })
    }
}

/// Check if huge pages are supported on Windows
pub fn check_hugepage_support() -> bool {
    check_large_page_support()
}

/// Check if large pages are supported on Windows
pub fn check_large_page_support() -> bool {
    // SAFETY: `GetLargePageMinimum` has no preconditions.
    unsafe {
        let min_large_page = GetLargePageMinimum();
        min_large_page > 0
    }
}

/// Get minimum large page size on Windows
pub fn get_large_page_minimum() -> usize {
    // SAFETY: `GetLargePageMinimum` has no preconditions.
    unsafe { GetLargePageMinimum() }
}

/// Configure working set size for the current process
pub fn configure_working_set(
    min_size: Option<usize>,
    max_size: Option<usize>,
) -> Result<(), PlottingError> {
    // SAFETY: `GetCurrentProcess` returns a pseudo handle valid for this process,
    // and the working set sizes are passed directly as documented values.
    unsafe {
        let process = GetCurrentProcess();
        let min_ws = min_size.unwrap_or(0);
        let max_ws = max_size.unwrap_or(0);

        let result = SetProcessWorkingSetSize(process, min_ws, max_ws);
        if result != FALSE {
            Ok(())
        } else {
            Err(PlottingError::SystemError(
                "Failed to configure working set size".to_string(),
            ))
        }
    }
}

/// Get NUMA node count on Windows
pub fn get_numa_nodes() -> usize {
    // This is a simplified implementation
    // A full implementation would use GetLogicalProcessorInformationEx
    // SAFETY: first call passes null buffer to query required size; second call
    // uses a valid allocated buffer and checks API result.
    unsafe {
        let mut buffer_length: DWORD = 0;

        // First call to get required buffer size
        GetLogicalProcessorInformation(ptr::null_mut(), &mut buffer_length);

        if buffer_length == 0 {
            return 1; // Default to single NUMA node
        }

        let mut buffer = vec![0u8; buffer_length as usize];
        let result = GetLogicalProcessorInformation(
            buffer.as_mut_ptr() as *mut std::ffi::c_void,
            &mut buffer_length,
        );

        if result != FALSE {
            // Parse the processor information to count NUMA nodes
            // This is simplified - in practice you'd parse SYSTEM_LOGICAL_PROCESSOR_INFORMATION
            // structures to count NumaNode relationships
            let estimated_nodes = (buffer_length as usize / 48).max(1); // Rough estimate
            estimated_nodes.min(64) // Cap at reasonable maximum
        } else {
            1 // Default single NUMA node
        }
    }
}

/// Allocate large page memory on Windows
pub fn allocate_large_pages(size: usize) -> Result<*mut std::ffi::c_void, PlottingError> {
    if !check_large_page_support() {
        return Err(PlottingError::SystemError(
            "Large pages not supported".to_string(),
        ));
    }

    // SAFETY: `VirtualAlloc` is called with documented flags; null result is handled.
    unsafe {
        let ptr = VirtualAlloc(
            ptr::null_mut(),
            size,
            MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES,
            PAGE_READWRITE,
        );

        if ptr.is_null() {
            Err(PlottingError::SystemError(
                "Failed to allocate large pages".to_string(),
            ))
        } else {
            Ok(ptr)
        }
    }
}

/// Free large page memory on Windows
pub fn free_large_pages(ptr: *mut std::ffi::c_void) -> Result<(), PlottingError> {
    // SAFETY: caller provides a pointer returned by `VirtualAlloc`; `VirtualFree`
    // return value is checked.
    unsafe {
        let result = VirtualFree(ptr, 0, MEM_RELEASE);
        if result != FALSE {
            Ok(())
        } else {
            Err(PlottingError::SystemError(
                "Failed to free large pages".to_string(),
            ))
        }
    }
}

/// Get memory pressure level on Windows
pub fn get_memory_pressure() -> Result<MemoryPressureLevel, PlottingError> {
    let memory_status = get_memory_status()?;
    let perf_info = get_performance_info()?;

    // Calculate memory pressure based on multiple factors
    let physical_pressure = memory_status.memory_load as f64 / 100.0;
    let commit_pressure = perf_info.commit_total as f64 / perf_info.commit_limit as f64;

    let overall_pressure = physical_pressure.max(commit_pressure);

    let pressure_level = if overall_pressure > 0.95 {
        MemoryPressureLevel::Critical
    } else if overall_pressure > 0.85 {
        MemoryPressureLevel::High
    } else if overall_pressure > 0.70 {
        MemoryPressureLevel::Medium
    } else {
        MemoryPressureLevel::Low
    };

    Ok(pressure_level)
}

#[derive(Debug, Clone)]
pub struct WindowsMemoryStatus {
    pub memory_load: u32,                // Percent of memory in use
    pub total_physical: u64,             // Total physical memory
    pub available_physical: u64,         // Available physical memory
    pub total_page_file: u64,            // Total page file size
    pub available_page_file: u64,        // Available page file
    pub total_virtual: u64,              // Total virtual address space
    pub available_virtual: u64,          // Available virtual address space
    pub available_extended_virtual: u64, // Available extended virtual
}

#[derive(Debug, Clone)]
pub struct WindowsPerformanceInfo {
    pub commit_total: usize,       // Current committed memory
    pub commit_limit: usize,       // Maximum committed memory
    pub commit_peak: usize,        // Peak committed memory
    pub physical_total: usize,     // Total physical memory
    pub physical_available: usize, // Available physical memory
    pub system_cache: usize,       // System cache memory
    pub kernel_total: usize,       // Total kernel memory
    pub kernel_paged: usize,       // Paged kernel memory
    pub kernel_nonpaged: usize,    // Non-paged kernel memory
    pub page_size: usize,          // System page size
    pub handle_count: u32,         // System handle count
    pub process_count: u32,        // Process count
    pub thread_count: u32,         // Thread count
}

#[derive(Debug, Clone)]
pub struct WindowsSystemInfo {
    pub processor_architecture: u16,
    pub page_size: usize,
    pub minimum_application_address: usize,
    pub maximum_application_address: usize,
    pub active_processor_mask: usize,
    pub number_of_processors: usize,
    pub processor_type: u32,
    pub allocation_granularity: usize,
    pub processor_level: u16,
    pub processor_revision: u16,
}

#[derive(Debug, Clone)]
pub enum MemoryPressureLevel {
    Low,
    Medium,
    High,
    Critical,
}

/// Windows-specific memory optimization recommendations
pub fn get_windows_optimization_recommendations(
    memory_status: &WindowsMemoryStatus,
    perf_info: &WindowsPerformanceInfo,
) -> Vec<String> {
    let mut recommendations = Vec::new();

    // High memory usage
    if memory_status.memory_load > 85 {
        recommendations
            .push("High memory usage detected. Consider reducing memory consumption.".to_string());
    }

    // Page file pressure
    let page_file_usage = (perf_info.commit_total as f64) / (perf_info.commit_limit as f64);
    if page_file_usage > 0.8 {
        recommendations.push(
            "High page file usage. Consider increasing page file size or adding more RAM."
                .to_string(),
        );
    }

    // Fragmentation indicators
    let virtual_fragmentation = (memory_status.total_virtual - memory_status.available_virtual)
        as f64
        / memory_status.total_virtual as f64;
    if virtual_fragmentation > 0.7 {
        recommendations.push(
            "Virtual address space fragmentation detected. Consider process restart.".to_string(),
        );
    }

    // Large page recommendations
    if check_large_page_support() && memory_status.total_physical > 8 * 1024 * 1024 * 1024 {
        recommendations.push(
            "Large pages supported. Consider using large pages for large allocations.".to_string(),
        );
    }

    // Working set optimization
    if perf_info.physical_available < perf_info.physical_total / 10 {
        recommendations.push(
            "Low available physical memory. Consider optimizing working set size.".to_string(),
        );
    }

    recommendations
}

/// Configure low fragmentation heap for better small allocation performance
pub fn enable_low_fragmentation_heap() -> Result<(), PlottingError> {
    // This would typically be done through HeapSetInformation
    // For now, return success as it's usually enabled by default on modern Windows
    Ok(())
}

/// Get heap fragmentation information
pub fn get_heap_fragmentation_info() -> Result<HeapFragmentationInfo, PlottingError> {
    // This is a placeholder implementation
    // A full implementation would use HeapWalk and related APIs
    Ok(HeapFragmentationInfo {
        total_heap_size: 0,
        committed_size: 0,
        uncommitted_size: 0,
        fragmentation_percentage: 0.0,
        largest_free_block: 0,
    })
}

/// Check if memory mapping is supported on Windows
pub fn check_memory_mapping_support() -> Result<bool, PlottingError> {
    // On Windows, memory mapping is always supported
    Ok(true)
}

#[derive(Debug, Clone)]
pub struct HeapFragmentationInfo {
    pub total_heap_size: usize,
    pub committed_size: usize,
    pub uncommitted_size: usize,
    pub fragmentation_percentage: f64,
    pub largest_free_block: usize,
}