8
8
use std:: collections:: BTreeMap ;
9
9
use std:: ops:: AddAssign ;
10
10
11
- use lgalloc:: { FileStats , SizeClassStats } ;
11
+ use lgalloc:: { FileStats , MapStats } ;
12
12
use mz_ore:: cast:: CastFrom ;
13
13
use mz_ore:: metrics:: { MetricsRegistry , raw} ;
14
14
use paste:: paste;
@@ -48,6 +48,11 @@ struct FileStatsAccum {
48
48
pub file_size : usize ,
49
49
/// Size of the file on disk in bytes.
50
50
pub allocated_size : usize ,
51
+ }
52
+
53
+ /// An accumulator for [`MapStats`].
54
+ #[ derive( Default ) ]
55
+ struct MapStatsAccum {
51
56
/// Number of mapped bytes, if different from `dirty`. Consult `man 7 numa` for details.
52
57
pub mapped : usize ,
53
58
/// Number of active bytes. Consult `man 7 numa` for details.
@@ -60,6 +65,11 @@ impl AddAssign<&FileStats> for FileStatsAccum {
60
65
fn add_assign ( & mut self , rhs : & FileStats ) {
61
66
self . file_size += rhs. file_size ;
62
67
self . allocated_size += rhs. allocated_size ;
68
+ }
69
+ }
70
+
71
+ impl AddAssign < & MapStats > for MapStatsAccum {
72
+ fn add_assign ( & mut self , rhs : & MapStats ) {
63
73
self . mapped += rhs. mapped ;
64
74
self . active += rhs. active ;
65
75
self . dirty += rhs. dirty ;
@@ -118,32 +128,25 @@ macro_rules! metrics_size_class {
118
128
}
119
129
fn update( & mut self ) -> Result <( ) , Error > {
120
130
let stats = lgalloc:: lgalloc_stats( ) ;
121
- for sc in & stats. size_class {
122
- let sc_stats = self . get_size_class( sc . size_class) ;
123
- $( sc_stats. $metric. set( ( $conv) ( u64 :: cast_from( sc. $name) , sc ) ) ; ) *
131
+ for ( size_class , sc ) in & stats. size_class {
132
+ let sc_stats = self . get_size_class( * size_class) ;
133
+ $( sc_stats. $metric. set( ( $conv) ( u64 :: cast_from( sc. $name) , * size_class ) ) ; ) *
124
134
}
125
- let mut accums = BTreeMap :: new( ) ;
126
- match & stats. file_stats {
127
- Ok ( file_stats ) => {
128
- for file_stat in file_stats {
129
- let accum : & mut FileStatsAccum = accums . entry ( file_stat. size_class ) . or_default ( ) ;
135
+ let mut f_accums = BTreeMap :: new( ) ;
136
+ for ( size_class , file_stat ) in & stats. file {
137
+ let accum : & mut FileStatsAccum = f_accums . entry ( * size_class ) . or_default ( ) ;
138
+ match file_stat {
139
+ Ok ( file_stat) => {
130
140
accum. add_assign( file_stat) ;
131
141
}
132
- }
133
- #[ cfg( target_os = "linux" ) ]
134
- Err ( err) => {
135
- return Err ( Error :: new( ErrorKind :: FileStatsFailed ( err. to_string( ) ) ) ) ;
136
- }
137
- #[ cfg( not( target_os = "linux" ) ) ]
138
- Err ( err) => {
139
- if err. kind( ) != std:: io:: ErrorKind :: NotFound {
140
- return Err ( Error :: new( ErrorKind :: FileStatsFailed ( err. to_string( ) ) ) ) ;
142
+ Err ( err) => {
143
+ return Err ( ErrorKind :: FileStatsFailed ( err. to_string( ) ) . into( ) ) ;
141
144
}
142
145
}
143
146
}
144
- for ( size_class, accum ) in accums {
147
+ for ( size_class, f_accum ) in f_accums {
145
148
let sc_stats = self . get_size_class( size_class) ;
146
- $( sc_stats. $f_metric. set( u64 :: cast_from( accum . $f_name) ) ; ) *
149
+ $( sc_stats. $f_metric. set( u64 :: cast_from( f_accum . $f_name) ) ; ) *
147
150
}
148
151
Ok ( ( ) )
149
152
}
@@ -152,11 +155,74 @@ macro_rules! metrics_size_class {
152
155
} ;
153
156
}
154
157
155
- fn normalize_by_size_class ( value : u64 , stats : & SizeClassStats ) -> u64 {
156
- value * u64:: cast_from ( stats. size_class )
158
+ macro_rules! map_metrics {
159
+ ( $namespace: ident
160
+ @mem ( $( ( $m_name: ident, $m_metric: ident, $m_desc: expr) ) ,* )
161
+ ) => {
162
+ map_metrics! {
163
+ @define $namespace
164
+ @mem $( ( $m_name, $m_metric, $m_desc) ) ,*
165
+ }
166
+ } ;
167
+ ( @define $namespace: ident
168
+ @mem $( ( $m_name: ident, $m_metric: ident, $m_desc: expr) ) ,*
169
+ ) => {
170
+ paste! {
171
+ pub ( crate ) struct LgMapMetrics {
172
+ size_class: BTreeMap <usize , LgMapMetricsSC >,
173
+ $( $m_metric: raw:: UIntGaugeVec , ) *
174
+ }
175
+ struct LgMapMetricsSC {
176
+ $( $m_metric: GenericGauge <AtomicU64 >, ) *
177
+ }
178
+ impl LgMapMetrics {
179
+ fn new( registry: & MetricsRegistry ) -> Self {
180
+ Self {
181
+ size_class: BTreeMap :: default ( ) ,
182
+ $( $m_metric: registry. register( mz_ore:: metric!(
183
+ name: concat!( stringify!( $namespace) , "_" , stringify!( $m_metric) ) ,
184
+ help: $m_desc,
185
+ var_labels: [ "size_class" ] ,
186
+ ) ) , ) *
187
+ }
188
+ }
189
+ fn get_size_class( & mut self , size_class: usize ) -> & LgMapMetricsSC {
190
+ self . size_class. entry( size_class) . or_insert_with( || {
191
+ let labels: & [ & str ] = & [ & size_class. to_string( ) ] ;
192
+ LgMapMetricsSC {
193
+ $( $m_metric: self . $m_metric. with_label_values( labels) , ) *
194
+ }
195
+ } )
196
+ }
197
+ #[ cfg( target_os = "linux" ) ]
198
+ fn update( & mut self ) -> std:: io:: Result <( ) > {
199
+ let stats = lgalloc:: lgalloc_stats_with_mapping( ) ?;
200
+ let mut m_accums = BTreeMap :: new( ) ;
201
+ for ( size_class, map_stat) in stats. map. iter( ) . flatten( ) {
202
+ let accum: & mut MapStatsAccum = m_accums. entry( * size_class) . or_default( ) ;
203
+ accum. add_assign( map_stat) ;
204
+ }
205
+ for ( size_class, m_accum) in m_accums {
206
+ let sc_stats = self . get_size_class( size_class) ;
207
+ $( sc_stats. $m_metric. set( u64 :: cast_from( m_accum. $m_name) ) ; ) *
208
+ }
209
+ Ok ( ( ) )
210
+ }
211
+ #[ cfg( not( target_os = "linux" ) ) ]
212
+ fn update( & mut self ) -> std:: io:: Result <( ) > {
213
+ // On non-Linux systems, we do not have `numa_maps` stats.
214
+ Ok ( ( ) )
215
+ }
216
+ }
217
+ }
218
+ } ;
157
219
}
158
220
159
- fn id ( value : u64 , _stats : & SizeClassStats ) -> u64 {
221
+ fn normalize_by_size_class ( value : u64 , size_class : usize ) -> u64 {
222
+ value * u64:: cast_from ( size_class)
223
+ }
224
+
225
+ fn id ( value : u64 , _size_class : usize ) -> u64 {
160
226
value
161
227
}
162
228
@@ -184,7 +250,13 @@ metrics_size_class! {
184
250
)
185
251
@file (
186
252
( file_size, file_size_bytes, "Sum of file sizes in size class" ) ,
187
- ( allocated_size, file_allocated_size_bytes, "Sum of allocated sizes in size class" ) ,
253
+ ( allocated_size, file_allocated_size_bytes, "Sum of allocated sizes in size class" )
254
+ )
255
+ }
256
+
257
+ map_metrics ! {
258
+ mz_metrics_lgalloc
259
+ @mem (
188
260
( mapped, vm_mapped_bytes, "Sum of mapped sizes in size class" ) ,
189
261
( active, vm_active_bytes, "Sum of active sizes in size class" ) ,
190
262
( dirty, vm_dirty_bytes, "Sum of dirty sizes in size class" )
@@ -196,10 +268,23 @@ pub(crate) fn register_metrics_into(metrics_registry: &MetricsRegistry) -> LgMet
196
268
LgMetrics :: new ( metrics_registry)
197
269
}
198
270
271
+ /// Register a task to read mapping-related lgalloc stats.
272
+ pub ( crate ) fn register_map_metrics_into ( metrics_registry : & MetricsRegistry ) -> LgMapMetrics {
273
+ LgMapMetrics :: new ( metrics_registry)
274
+ }
275
+
199
276
impl MetricsUpdate for LgMetrics {
200
277
type Error = Error ;
201
278
const NAME : & ' static str = "lgalloc" ;
202
279
fn update ( & mut self ) -> Result < ( ) , Self :: Error > {
203
280
self . update ( )
204
281
}
205
282
}
283
+
284
+ impl MetricsUpdate for LgMapMetrics {
285
+ type Error = std:: io:: Error ;
286
+ const NAME : & ' static str = "lgalloc_map" ;
287
+ fn update ( & mut self ) -> Result < ( ) , Self :: Error > {
288
+ self . update ( )
289
+ }
290
+ }
0 commit comments