Skip to content

Commit faae7c4

Browse files
stepanchegfacebook-github-bot
authored andcommitted
StringIndexMap
Summary: Another abstraction, map `StringId -> V`. Before this diff: ``` pub(crate) struct HeapSummaryByFunction { info: Vec<FuncInfo>, } ``` Now field type is changed to `StringIndexMap<FuncInfo>`. Also, `StringIndexMap` is sparse, which is easier to work with. Reviewed By: bobyangyf Differential Revision: D38518061 fbshipit-source-id: f0fb716945cbc99d47489e8784c0af06fa96fc30
1 parent c499be3 commit faae7c4

File tree

2 files changed

+43
-21
lines changed

2 files changed

+43
-21
lines changed

starlark/src/values/layout/heap/profile/string_index.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717

1818
use gazebo::dupe::Dupe;
19+
use gazebo::prelude::*;
1920
use starlark_map::small_set::SmallSet;
2021

2122
/// Map strings to integers 0, 1, 2, ...
@@ -45,3 +46,32 @@ impl StringIndex {
4546
self.strings.get_index(id.0).expect("invalid string id")
4647
}
4748
}
49+
50+
#[derive(Debug, Default_)]
51+
pub(crate) struct StringIndexMap<V> {
52+
values: Vec<Option<V>>,
53+
}
54+
55+
impl<V> StringIndexMap<V> {
56+
pub(crate) fn or_insert(&mut self, id: StringId) -> &mut V
57+
where
58+
V: Default,
59+
{
60+
// Resize.
61+
while self.values.get(id.0).is_none() {
62+
self.values.push(None);
63+
}
64+
self.values[id.0].get_or_insert_with(Default::default)
65+
}
66+
67+
pub(crate) fn iter(&self) -> impl Iterator<Item = (StringId, &V)> {
68+
self.values
69+
.iter()
70+
.enumerate()
71+
.filter_map(|(id, value)| value.as_ref().map(|value| (StringId(id), value)))
72+
}
73+
74+
pub(crate) fn values(&self) -> impl Iterator<Item = &V> {
75+
self.values.iter().filter_map(Option::as_ref)
76+
}
77+
}

starlark/src/values/layout/heap/profile/summary.rs

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use crate::values::layout::heap::profile::aggregated::AggregateHeapProfileInfo;
2525
use crate::values::layout::heap::profile::aggregated::StackFrame;
2626
use crate::values::layout::heap::profile::alloc_counts::AllocCounts;
2727
use crate::values::layout::heap::profile::string_index::StringId;
28+
use crate::values::layout::heap::profile::string_index::StringIndexMap;
2829

2930
/// Information relating to a function.
3031
#[derive(Default, Debug, Clone)]
@@ -65,19 +66,14 @@ impl FuncInfo {
6566
/// so pull out top_stack/top_info as a cache.
6667
pub(crate) struct HeapSummaryByFunction {
6768
/// Information about all functions. Map from `StringId`.
68-
info: Vec<FuncInfo>,
69+
info: StringIndexMap<FuncInfo>,
6970
}
7071

7172
impl HeapSummaryByFunction {
72-
fn ensure(&mut self, x: StringId) -> &mut FuncInfo {
73-
if self.info.len() <= x.0 {
74-
self.info.resize(x.0 + 1, FuncInfo::default());
75-
}
76-
&mut self.info[x.0]
77-
}
78-
7973
pub(crate) fn init(stacks: &AggregateHeapProfileInfo) -> HeapSummaryByFunction {
80-
let mut info = HeapSummaryByFunction { info: Vec::new() };
74+
let mut info = HeapSummaryByFunction {
75+
info: StringIndexMap::default(),
76+
};
8177
info.init_children(&stacks.root, stacks.root_id);
8278
info
8379
}
@@ -96,28 +92,24 @@ impl HeapSummaryByFunction {
9692
frame: &StackFrame,
9793
caller: StringId,
9894
) -> SmallDuration {
99-
self.ensure(func).time += frame.time_x2;
100-
self.ensure(func).calls += frame.calls_x2 as usize;
101-
*self.ensure(func).callers.entry(caller).or_insert(0) += 1;
95+
self.info.or_insert(func).time += frame.time_x2;
96+
self.info.or_insert(func).calls += frame.calls_x2 as usize;
97+
*self.info.or_insert(func).callers.entry(caller).or_insert(0) += 1;
10298
for (t, allocs) in &frame.allocs.summary {
103-
*self.ensure(func).alloc.entry(t).or_default() += *allocs;
99+
*self.info.or_insert(func).alloc.entry(t).or_default() += *allocs;
104100
}
105101

106102
let time_rec = frame.time_x2 + self.init_children(frame, func);
107-
self.ensure(func).time_rec += time_rec;
103+
self.info.or_insert(func).time_rec += time_rec;
108104
time_rec
109105
}
110106

111107
fn totals(&self) -> FuncInfo {
112-
FuncInfo::merge(self.info.iter())
108+
FuncInfo::merge(self.info.values())
113109
}
114110

115111
fn info(&self) -> Vec<(StringId, &FuncInfo)> {
116-
self.info
117-
.iter()
118-
.enumerate()
119-
.map(|(id, x)| (StringId(id), x))
120-
.collect::<Vec<_>>()
112+
self.info.iter().collect::<Vec<_>>()
121113
}
122114

123115
pub(crate) fn gen_csv(&self, stacks: &AggregateHeapProfileInfo) -> String {
@@ -216,7 +208,7 @@ _ignore = str([1]) # allocate a string in non_drop
216208

217209
let info = HeapSummaryByFunction::init(&stacks);
218210

219-
let total = FuncInfo::merge(info.info.iter());
211+
let total = FuncInfo::merge(info.info.values());
220212
// from non-drop heap
221213
assert_eq!(total.alloc.get("string").unwrap().count, 1);
222214
// from drop heap

0 commit comments

Comments
 (0)