I am writing a top-like utility to profile the memory usage of Linux processes. Here is an excerpt from that code:
match map_path: {
Path(pathbuf) => {
let Some(pss) = map.extension.map.get("Pss") else {
eprintln!("WARNING: PSS field not defined on file-backed map. Assuming 0.\n\
The map is: {:?}", map);
continue;
};
memory_ext.file_backed_pss += pss;
},
Heap => {
if let Some(pss) = map.extension.map.get("Pss") {
memory_ext.heap_pss += pss;
} else {
eprintln!("WARNING: PSS field not defined on heap. Assuming 0.\n\
The map is: {:?}", map);
}
},
Stack => {
if let Some(pss) = map.extension.map.get("Pss") {
memory_ext.stack_pss += pss;
} else {
eprintln!("WARNING: PSS field not defined on stack. Assuming 0.\n\
The map is: {:?}", map);
}
},
Anonymous => {
if let Some(pss) = map.extension.map.get("Pss") {
memory_ext.anon_map_pss += pss;
} else {
eprintln!("WARNING: PSS field not defined on anonymous map. Assuming 0.\n\
The map is: {:?}", map);
}
},
_ => {
let Some(&rss) = map.extension.map.get("Rss") else {
eprintln!("WARNING: I don't know how to classify this map and it doesn't have a RSS field.\n\
The map is: {:?}", map);
continue;
};
if rss == 0 {
eprintln!("WARNING: I don't know how to classify this map, but at least its RSS is 0.\n\
The map is: {:?}", map);
} else {
panic!("FATAL: I don't know how to classify this map and its RSS is not 0.\n\
The map is: {:?}", map);
}
},
} // end match
So there's a map_path
, and independently from that, there's whether "Pss"
is in the HashMap
. However, if map_path
is one of the fallthrough values, then I want to look at the "Rss"
key instead.
The action to take in most cases is the same, and the messages are substantially similar. I wonder if I could factor code out, something like:
let pss = map.extension.map.get("Pss");
match (map_path, pss) {
(Path(pathbuf), Some(pss)) => memory_ext.file_backed_pss += pss,
(Heap, Some(pss)) => memory_ext.heap_pss += pss,
(Stack, Some(pss)) => memory_ext.stack_pss += pss,
(Anonymous, Some(pss)) => memory_ext.anon_map_pss += pss,
m @ (Path(_) | Heap | Stack | Anonymous, None) => {
eprintln!("WARNING: PSS field not defined on {}. Assuming 0.\n\
The map is: {:?}", m.0.to_string(), map); // to_string() hypothetically exists
},
(_, _) => {
let Some(&rss) = map.extension.map.get("Rss") else {
eprintln!("WARNING: I don't know how to classify this map and it doesn't have a RSS field.\n\
The map is: {:?}", map);
continue;
};
if rss == 0 {
eprintln!("WARNING: I don't know how to classify this map, but at least its RSS is 0.\n\
The map is: {:?}", map);
} else {
panic!("FATAL: I don't know how to classify this map and its RSS is not 0.\n\
The map is: {:?}", map);
}
},
} // end match
This code has a lot less repetition. However, maybe I only want to run map.extension.map.get("Pss")
if I know I'm not in the fallthrough case for the first tuple item. In other words, I would like to set it up, perhaps with a lambda, so that the match
statement only calls the function if it needs to. Is there a way to do this?