1
1
use std:: {
2
2
cell:: UnsafeCell ,
3
3
ptr:: NonNull ,
4
- sync:: atomic:: { AtomicUsize , Ordering } ,
4
+ sync:: {
5
+ LazyLock ,
6
+ atomic:: { AtomicUsize , Ordering } ,
7
+ } ,
5
8
} ;
6
9
7
10
use crate :: AllocationCounters ;
8
11
9
- static GLOBAL : [ AtomicCounters ; 128 ] = [
10
- AtomicCounters :: new ( ) ,
11
- AtomicCounters :: new ( ) ,
12
- AtomicCounters :: new ( ) ,
13
- AtomicCounters :: new ( ) ,
14
- AtomicCounters :: new ( ) ,
15
- AtomicCounters :: new ( ) ,
16
- AtomicCounters :: new ( ) ,
17
- AtomicCounters :: new ( ) ,
18
- AtomicCounters :: new ( ) ,
19
- AtomicCounters :: new ( ) ,
20
- AtomicCounters :: new ( ) ,
21
- AtomicCounters :: new ( ) ,
22
- AtomicCounters :: new ( ) ,
23
- AtomicCounters :: new ( ) ,
24
- AtomicCounters :: new ( ) ,
25
- AtomicCounters :: new ( ) ,
26
- AtomicCounters :: new ( ) ,
27
- AtomicCounters :: new ( ) ,
28
- AtomicCounters :: new ( ) ,
29
- AtomicCounters :: new ( ) ,
30
- AtomicCounters :: new ( ) ,
31
- AtomicCounters :: new ( ) ,
32
- AtomicCounters :: new ( ) ,
33
- AtomicCounters :: new ( ) ,
34
- AtomicCounters :: new ( ) ,
35
- AtomicCounters :: new ( ) ,
36
- AtomicCounters :: new ( ) ,
37
- AtomicCounters :: new ( ) ,
38
- AtomicCounters :: new ( ) ,
39
- AtomicCounters :: new ( ) ,
40
- AtomicCounters :: new ( ) ,
41
- AtomicCounters :: new ( ) ,
42
- AtomicCounters :: new ( ) ,
43
- AtomicCounters :: new ( ) ,
44
- AtomicCounters :: new ( ) ,
45
- AtomicCounters :: new ( ) ,
46
- AtomicCounters :: new ( ) ,
47
- AtomicCounters :: new ( ) ,
48
- AtomicCounters :: new ( ) ,
49
- AtomicCounters :: new ( ) ,
50
- AtomicCounters :: new ( ) ,
51
- AtomicCounters :: new ( ) ,
52
- AtomicCounters :: new ( ) ,
53
- AtomicCounters :: new ( ) ,
54
- AtomicCounters :: new ( ) ,
55
- AtomicCounters :: new ( ) ,
56
- AtomicCounters :: new ( ) ,
57
- AtomicCounters :: new ( ) ,
58
- AtomicCounters :: new ( ) ,
59
- AtomicCounters :: new ( ) ,
60
- AtomicCounters :: new ( ) ,
61
- AtomicCounters :: new ( ) ,
62
- AtomicCounters :: new ( ) ,
63
- AtomicCounters :: new ( ) ,
64
- AtomicCounters :: new ( ) ,
65
- AtomicCounters :: new ( ) ,
66
- AtomicCounters :: new ( ) ,
67
- AtomicCounters :: new ( ) ,
68
- AtomicCounters :: new ( ) ,
69
- AtomicCounters :: new ( ) ,
70
- AtomicCounters :: new ( ) ,
71
- AtomicCounters :: new ( ) ,
72
- AtomicCounters :: new ( ) ,
73
- AtomicCounters :: new ( ) ,
74
- AtomicCounters :: new ( ) ,
75
- AtomicCounters :: new ( ) ,
76
- AtomicCounters :: new ( ) ,
77
- AtomicCounters :: new ( ) ,
78
- AtomicCounters :: new ( ) ,
79
- AtomicCounters :: new ( ) ,
80
- AtomicCounters :: new ( ) ,
81
- AtomicCounters :: new ( ) ,
82
- AtomicCounters :: new ( ) ,
83
- AtomicCounters :: new ( ) ,
84
- AtomicCounters :: new ( ) ,
85
- AtomicCounters :: new ( ) ,
86
- AtomicCounters :: new ( ) ,
87
- AtomicCounters :: new ( ) ,
88
- AtomicCounters :: new ( ) ,
89
- AtomicCounters :: new ( ) ,
90
- AtomicCounters :: new ( ) ,
91
- AtomicCounters :: new ( ) ,
92
- AtomicCounters :: new ( ) ,
93
- AtomicCounters :: new ( ) ,
94
- AtomicCounters :: new ( ) ,
95
- AtomicCounters :: new ( ) ,
96
- AtomicCounters :: new ( ) ,
97
- AtomicCounters :: new ( ) ,
98
- AtomicCounters :: new ( ) ,
99
- AtomicCounters :: new ( ) ,
100
- AtomicCounters :: new ( ) ,
101
- AtomicCounters :: new ( ) ,
102
- AtomicCounters :: new ( ) ,
103
- AtomicCounters :: new ( ) ,
104
- AtomicCounters :: new ( ) ,
105
- AtomicCounters :: new ( ) ,
106
- AtomicCounters :: new ( ) ,
107
- AtomicCounters :: new ( ) ,
108
- AtomicCounters :: new ( ) ,
109
- AtomicCounters :: new ( ) ,
110
- AtomicCounters :: new ( ) ,
111
- AtomicCounters :: new ( ) ,
112
- AtomicCounters :: new ( ) ,
113
- AtomicCounters :: new ( ) ,
114
- AtomicCounters :: new ( ) ,
115
- AtomicCounters :: new ( ) ,
116
- AtomicCounters :: new ( ) ,
117
- AtomicCounters :: new ( ) ,
118
- AtomicCounters :: new ( ) ,
119
- AtomicCounters :: new ( ) ,
120
- AtomicCounters :: new ( ) ,
121
- AtomicCounters :: new ( ) ,
122
- AtomicCounters :: new ( ) ,
123
- AtomicCounters :: new ( ) ,
124
- AtomicCounters :: new ( ) ,
125
- AtomicCounters :: new ( ) ,
126
- AtomicCounters :: new ( ) ,
127
- AtomicCounters :: new ( ) ,
128
- AtomicCounters :: new ( ) ,
129
- AtomicCounters :: new ( ) ,
130
- AtomicCounters :: new ( ) ,
131
- AtomicCounters :: new ( ) ,
132
- AtomicCounters :: new ( ) ,
133
- AtomicCounters :: new ( ) ,
134
- AtomicCounters :: new ( ) ,
135
- AtomicCounters :: new ( ) ,
136
- AtomicCounters :: new ( ) ,
137
- AtomicCounters :: new ( ) ,
138
- ] ;
12
+ static GLOBAL : LazyLock < Vec < AtomicCounters > > = LazyLock :: new ( || {
13
+ let size = match std:: thread:: available_parallelism ( ) {
14
+ Ok ( s) => s. into ( ) ,
15
+ Err ( _) => 128 ,
16
+ } ;
17
+ let mut vec = Vec :: with_capacity ( size) ;
18
+ for _ in 0 ..size {
19
+ vec. push ( AtomicCounters :: new ( ) ) ;
20
+ }
21
+ vec
22
+ } ) ;
23
+
139
24
static INDEX : AtomicUsize = AtomicUsize :: new ( 0 ) ;
140
- fn get_index ( ) -> usize {
141
- INDEX . fetch_add ( 1 , Ordering :: AcqRel ) & ( GLOBAL . len ( ) - 1 )
25
+
26
+ /// Returns a reference to an entry in global
27
+ fn get_global_ref ( ) -> & ' static AtomicCounters {
28
+ let index = INDEX . fetch_add ( 1 , Ordering :: AcqRel ) & ( GLOBAL . len ( ) - 1 ) ;
29
+
30
+ GLOBAL . get ( index) . unwrap ( )
142
31
}
143
32
144
- #[ repr( align( 64 ) ) ] // cache line aligned
33
+ #[ repr( align( 64 ) ) ] // cache line aligned to reduce false sharing between adjacent entries
145
34
struct AtomicCounters {
146
35
allocations : AtomicUsize ,
147
36
deallocations : AtomicUsize ,
@@ -162,13 +51,13 @@ impl AtomicCounters {
162
51
163
52
struct ThreadLocalCounter {
164
53
counters : AllocationCounters ,
165
- index : Option < usize > ,
54
+ global : Option < & ' static AtomicCounters > ,
166
55
}
167
56
168
57
impl ThreadLocalCounter {
169
58
const fn new ( ) -> Self {
170
59
Self {
171
- index : None ,
60
+ global : None ,
172
61
counters : AllocationCounters :: new ( ) ,
173
62
}
174
63
}
@@ -204,7 +93,7 @@ static MAX_ALLOCATED: AtomicUsize = AtomicUsize::new(0);
204
93
/// Returns an estimate of the total memory statistics
205
94
pub fn global_counters ( ) -> AllocationCounters {
206
95
let mut counters = AllocationCounters :: new ( ) ;
207
- for global in & GLOBAL {
96
+ for global in GLOBAL . iter ( ) {
208
97
counters. allocation_count += global. allocation_count . load ( Ordering :: Acquire ) ;
209
98
counters. deallocation_count += global. deallocation_count . load ( Ordering :: Acquire ) ;
210
99
counters. allocations += global. allocations . load ( Ordering :: Acquire ) ;
@@ -236,15 +125,7 @@ fn with_local_counter<T>(f: impl FnOnce(&mut ThreadLocalCounter, &AtomicCounters
236
125
// threadlocal
237
126
let mut local = unsafe { NonNull :: new_unchecked ( ptr) } ;
238
127
let local = unsafe { local. as_mut ( ) } ;
239
- let global = & GLOBAL [ match local. index {
240
- None => {
241
- let index = get_index ( ) ;
242
- local. index = Some ( index) ;
243
- index
244
- }
245
- Some ( index) => index,
246
- } ] ;
247
-
128
+ let global = * local. global . get_or_insert_with ( get_global_ref) ;
248
129
f ( local, global)
249
130
} )
250
131
}
0 commit comments