@@ -32,9 +32,7 @@ impl MemoryUsage {
32
32
allocated: Bytes ( jemalloc_ctl:: stats:: allocated:: read( ) . unwrap( ) as isize ) ,
33
33
}
34
34
} else if #[ cfg( all( target_os = "linux" , target_env = "gnu" ) ) ] {
35
- // Note: This is incredibly slow.
36
- let alloc = unsafe { libc:: mallinfo( ) } . uordblks as isize ;
37
- MemoryUsage { allocated: Bytes ( alloc) }
35
+ memusage_linux( )
38
36
} else if #[ cfg( windows) ] {
39
37
// There doesn't seem to be an API for determining heap usage, so we try to
40
38
// approximate that by using the Commit Charge value.
@@ -58,6 +56,37 @@ impl MemoryUsage {
58
56
}
59
57
}
60
58
59
+ #[ cfg( all( target_os = "linux" , target_env = "gnu" ) ) ]
60
+ fn memusage_linux ( ) -> MemoryUsage {
61
+ // Linux/glibc has 2 APIs for allocator introspection that we can use: mallinfo and mallinfo2.
62
+ // mallinfo uses `int` fields and cannot handle memory usage exceeding 2 GB.
63
+ // mallinfo2 is very recent, so its presence needs to be detected at runtime.
64
+ // Both are abysmally slow.
65
+
66
+ use std:: ffi:: CStr ;
67
+ use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
68
+
69
+ static MALLINFO2 : AtomicUsize = AtomicUsize :: new ( 1 ) ;
70
+
71
+ let mut mallinfo2 = MALLINFO2 . load ( Ordering :: Relaxed ) ;
72
+ if mallinfo2 == 1 {
73
+ let cstr = CStr :: from_bytes_with_nul ( b"mallinfo2\0 " ) . unwrap ( ) ;
74
+ mallinfo2 = unsafe { libc:: dlsym ( libc:: RTLD_DEFAULT , cstr. as_ptr ( ) ) } as usize ;
75
+ // NB: races don't matter here, since they'll always store the same value
76
+ MALLINFO2 . store ( mallinfo2, Ordering :: Relaxed ) ;
77
+ }
78
+
79
+ if mallinfo2 == 0 {
80
+ // mallinfo2 does not exist, use mallinfo.
81
+ let alloc = unsafe { libc:: mallinfo ( ) } . uordblks as isize ;
82
+ MemoryUsage { allocated : Bytes ( alloc) }
83
+ } else {
84
+ let mallinfo2: fn ( ) -> libc:: mallinfo2 = unsafe { std:: mem:: transmute ( mallinfo2) } ;
85
+ let alloc = mallinfo2 ( ) . uordblks as isize ;
86
+ MemoryUsage { allocated : Bytes ( alloc) }
87
+ }
88
+ }
89
+
61
90
#[ derive( Default , PartialEq , Eq , PartialOrd , Ord , Hash , Clone , Copy ) ]
62
91
pub struct Bytes ( isize ) ;
63
92
0 commit comments