Skip to content

Commit f0e588b

Browse files
committed
Build frame table columns during serialization.
1 parent b75b50c commit f0e588b

File tree

8 files changed

+155
-148
lines changed

8 files changed

+155
-148
lines changed

‎fxprof-processed-profile/src/frame_table.rs

Lines changed: 92 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,16 @@ use crate::global_lib_table::{GlobalLibIndex, GlobalLibTable};
88
use crate::native_symbols::NativeSymbolIndex;
99
use crate::resource_table::ResourceTable;
1010
use crate::serialization_helpers::SerializableSingleValueColumn;
11-
use crate::string_table::{ProfileStringTable, StringHandle};
11+
use crate::string_table::StringHandle;
1212
use crate::SourceLocation;
1313

1414
#[derive(Debug, Clone, Default)]
15-
pub struct FrameTable {
16-
func_table: FuncTable,
17-
resource_table: ResourceTable,
18-
19-
func_col: Vec<FuncIndex>,
20-
category_col: Vec<CategoryHandle>,
21-
subcategory_col: Vec<SubcategoryIndex>,
22-
line_col: Vec<Option<u32>>,
23-
column_col: Vec<Option<u32>>,
24-
address_col: Vec<Option<u32>>,
25-
native_symbol_col: Vec<Option<NativeSymbolIndex>>,
26-
inline_depth_col: Vec<u16>,
27-
15+
pub struct FrameInterner {
2816
frame_key_set: FastIndexSet<InternalFrame>,
17+
contains_js_frame: bool,
2918
}
3019

31-
impl FrameTable {
20+
impl FrameInterner {
3221
pub fn new() -> Self {
3322
Default::default()
3423
}
@@ -37,86 +26,119 @@ impl FrameTable {
3726
&mut self,
3827
frame: InternalFrame,
3928
global_libs: &mut GlobalLibTable,
40-
string_table: &mut ProfileStringTable,
4129
) -> usize {
4230
let (frame_index, is_new) = self.frame_key_set.insert_full(frame);
4331

44-
if !is_new {
45-
return frame_index;
46-
}
47-
48-
let func_key = frame.func_key();
49-
let func = self.func_table.index_for_func(
50-
func_key,
51-
&mut self.resource_table,
52-
global_libs,
53-
string_table,
54-
);
55-
56-
self.func_col.push(func);
57-
let SubcategoryHandle(category, subcategory) = frame.subcategory;
58-
self.category_col.push(category);
59-
self.subcategory_col.push(subcategory);
60-
self.line_col.push(frame.source_location.line);
61-
self.column_col.push(frame.source_location.col);
62-
63-
match frame.variant {
64-
InternalFrameVariant::Label => {
65-
self.address_col.push(None);
66-
self.native_symbol_col.push(None);
67-
self.inline_depth_col.push(0);
32+
if is_new {
33+
if frame
34+
.flags
35+
.intersects(FrameFlags::IS_JS | FrameFlags::IS_RELEVANT_FOR_JS)
36+
{
37+
self.contains_js_frame = true;
6838
}
69-
InternalFrameVariant::Native(NativeFrameData {
39+
40+
if let InternalFrameVariant::Native(NativeFrameData {
7041
lib,
71-
native_symbol,
7242
relative_address,
73-
inline_depth,
74-
}) => {
43+
..
44+
}) = frame.variant
45+
{
7546
global_libs.add_lib_used_rva(lib, relative_address);
76-
77-
self.address_col.push(Some(relative_address));
78-
self.native_symbol_col.push(native_symbol);
79-
self.inline_depth_col.push(inline_depth);
8047
}
8148
}
82-
8349
frame_index
8450
}
8551

8652
pub fn contains_js_frame(&self) -> bool {
87-
self.func_table.contains_js_func()
53+
self.contains_js_frame
8854
}
8955

90-
pub fn get_serializable_tables(
91-
&self,
92-
) -> (SerializableFrameTable<'_>, &'_ FuncTable, &'_ ResourceTable) {
93-
(
94-
SerializableFrameTable(self),
95-
&self.func_table,
96-
&self.resource_table,
97-
)
56+
pub fn create_tables(&self) -> (FrameTable, FuncTable, ResourceTable) {
57+
let len = self.frame_key_set.len();
58+
let mut func_col = Vec::with_capacity(len);
59+
let mut category_col = Vec::with_capacity(len);
60+
let mut subcategory_col = Vec::with_capacity(len);
61+
let mut line_col = Vec::with_capacity(len);
62+
let mut column_col = Vec::with_capacity(len);
63+
let mut address_col = Vec::with_capacity(len);
64+
let mut native_symbol_col = Vec::with_capacity(len);
65+
let mut inline_depth_col = Vec::with_capacity(len);
66+
67+
let mut func_table = FuncTable::default();
68+
let mut resource_table = ResourceTable::default();
69+
70+
for frame in &self.frame_key_set {
71+
let func_key = frame.func_key();
72+
let func = func_table.index_for_func(func_key, &mut resource_table);
73+
74+
func_col.push(func);
75+
let SubcategoryHandle(category, subcategory) = frame.subcategory;
76+
category_col.push(category);
77+
subcategory_col.push(subcategory);
78+
line_col.push(frame.source_location.line);
79+
column_col.push(frame.source_location.col);
80+
81+
match frame.variant {
82+
InternalFrameVariant::Label => {
83+
address_col.push(None);
84+
native_symbol_col.push(None);
85+
inline_depth_col.push(0);
86+
}
87+
InternalFrameVariant::Native(NativeFrameData {
88+
native_symbol,
89+
relative_address,
90+
inline_depth,
91+
..
92+
}) => {
93+
address_col.push(Some(relative_address));
94+
native_symbol_col.push(native_symbol);
95+
inline_depth_col.push(inline_depth);
96+
}
97+
}
98+
}
99+
100+
let frame_table = FrameTable {
101+
func_col,
102+
category_col,
103+
subcategory_col,
104+
line_col,
105+
column_col,
106+
address_col,
107+
native_symbol_col,
108+
inline_depth_col,
109+
};
110+
111+
(frame_table, func_table, resource_table)
98112
}
99113
}
100114

101-
pub struct SerializableFrameTable<'a>(&'a FrameTable);
115+
pub struct FrameTable {
116+
func_col: Vec<FuncIndex>,
117+
category_col: Vec<CategoryHandle>,
118+
subcategory_col: Vec<SubcategoryIndex>,
119+
line_col: Vec<Option<u32>>,
120+
column_col: Vec<Option<u32>>,
121+
address_col: Vec<Option<u32>>,
122+
native_symbol_col: Vec<Option<NativeSymbolIndex>>,
123+
inline_depth_col: Vec<u16>,
124+
}
102125

103-
impl Serialize for SerializableFrameTable<'_> {
126+
impl Serialize for FrameTable {
104127
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
105-
let SerializableFrameTable(table) = self;
106-
let len = table.func_col.len();
128+
let len = self.func_col.len();
107129
let mut map = serializer.serialize_map(None)?;
108130
map.serialize_entry("length", &len)?;
109-
map.serialize_entry("func", &table.func_col)?;
110-
map.serialize_entry("category", &table.category_col)?;
111-
map.serialize_entry("subcategory", &table.subcategory_col)?;
112-
map.serialize_entry("line", &table.line_col)?;
113-
map.serialize_entry("column", &table.column_col)?;
131+
map.serialize_entry("func", &self.func_col)?;
132+
map.serialize_entry("category", &self.category_col)?;
133+
map.serialize_entry("subcategory", &self.subcategory_col)?;
134+
map.serialize_entry("line", &self.line_col)?;
135+
map.serialize_entry("column", &self.column_col)?;
114136
map.serialize_entry(
115137
"address",
116-
&SerializableFrameTableAddressColumn(&table.address_col),
138+
&SerializableFrameTableAddressColumn(&self.address_col),
117139
)?;
118-
map.serialize_entry("nativeSymbol", &table.native_symbol_col)?;
119-
map.serialize_entry("inlineDepth", &table.inline_depth_col)?;
140+
map.serialize_entry("nativeSymbol", &self.native_symbol_col)?;
141+
map.serialize_entry("inlineDepth", &self.inline_depth_col)?;
120142
map.serialize_entry("innerWindowID", &SerializableSingleValueColumn(0, len))?;
121143
map.end()
122144
}

‎fxprof-processed-profile/src/func_table.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
22

33
use crate::fast_hash_map::FastIndexSet;
44
use crate::frame::FrameFlags;
5-
use crate::global_lib_table::{GlobalLibIndex, GlobalLibTable};
5+
use crate::global_lib_table::GlobalLibIndex;
66
use crate::resource_table::{ResourceIndex, ResourceTable};
77
use crate::serialization_helpers::SerializableSingleValueColumn;
8-
use crate::string_table::{ProfileStringTable, StringHandle};
8+
use crate::string_table::StringHandle;
99

1010
#[derive(Debug, Clone, Default)]
1111
pub struct FuncTable {
@@ -15,8 +15,6 @@ pub struct FuncTable {
1515
flags: Vec<FrameFlags>,
1616

1717
func_key_set: FastIndexSet<FuncKey>,
18-
19-
contains_js_func: bool,
2018
}
2119

2220
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
@@ -32,8 +30,6 @@ impl FuncTable {
3230
&mut self,
3331
func_key: FuncKey,
3432
resource_table: &mut ResourceTable,
35-
global_libs: &mut GlobalLibTable,
36-
string_table: &mut ProfileStringTable,
3733
) -> FuncIndex {
3834
let (index, is_new) = self.func_key_set.insert_full(func_key);
3935

@@ -49,24 +45,15 @@ impl FuncTable {
4945
flags,
5046
} = func_key;
5147

52-
let resource =
53-
lib.map(|lib| resource_table.resource_for_lib(lib, global_libs, string_table));
48+
let resource = lib.map(|lib| resource_table.resource_for_lib(lib));
5449

5550
self.names.push(name);
5651
self.files.push(file_path);
5752
self.resources.push(resource);
5853
self.flags.push(flags);
5954

60-
if flags.intersects(FrameFlags::IS_JS | FrameFlags::IS_RELEVANT_FOR_JS) {
61-
self.contains_js_func = true;
62-
}
63-
6455
func_index
6556
}
66-
67-
pub fn contains_js_func(&self) -> bool {
68-
self.contains_js_func
69-
}
7057
}
7158

7259
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]

‎fxprof-processed-profile/src/global_lib_table.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use std::sync::Arc;
44
use serde::ser::{Serialize, Serializer};
55

66
use crate::fast_hash_map::{FastHashMap, FastIndexSet};
7-
use crate::{LibraryInfo, SymbolTable};
7+
use crate::string_table::ProfileStringTable;
8+
use crate::{LibraryInfo, StringHandle, SymbolTable};
89

910
#[derive(Debug)]
1011
pub struct GlobalLibTable {
@@ -43,21 +44,22 @@ impl GlobalLibTable {
4344
self.symbol_tables.insert(library, symbol_table);
4445
}
4546

46-
pub fn index_for_used_lib(&mut self, lib_handle: LibraryHandle) -> GlobalLibIndex {
47+
pub fn index_for_used_lib(
48+
&mut self,
49+
lib_handle: LibraryHandle,
50+
string_table: &mut ProfileStringTable,
51+
) -> GlobalLibIndex {
4752
let used_libs = &mut self.used_libs;
4853
*self.used_lib_map.entry(lib_handle).or_insert_with(|| {
49-
let index = GlobalLibIndex(used_libs.len());
54+
let lib = self.all_libs.get_index(lib_handle.0).unwrap();
55+
let name_index = string_table.index_for_string(&lib.name);
56+
let index = GlobalLibIndex(used_libs.len(), name_index);
5057
used_libs.push(lib_handle);
5158
self.used_libs_seen_rvas.push(BTreeSet::new());
5259
index
5360
})
5461
}
5562

56-
pub fn get_lib(&self, index: GlobalLibIndex) -> Option<&LibraryInfo> {
57-
let handle = self.used_libs.get(index.0)?;
58-
self.all_libs.get_index(handle.0)
59-
}
60-
6163
pub fn get_lib_symbol_table(&self, index: GlobalLibIndex) -> Option<&SymbolTable> {
6264
let handle = self.used_libs.get(index.0)?;
6365
self.symbol_tables.get(handle).map(|v| &**v)
@@ -84,14 +86,20 @@ impl Serialize for GlobalLibTable {
8486
/// An index for a *used* library, i.e. a library for which there exists at
8587
/// least one frame in any process's frame table which refers to this lib.
8688
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
87-
pub struct GlobalLibIndex(usize);
89+
pub struct GlobalLibIndex(usize, StringHandle);
8890

8991
impl Serialize for GlobalLibIndex {
9092
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
9193
serializer.serialize_u32(self.0 as u32)
9294
}
9395
}
9496

97+
impl GlobalLibIndex {
98+
pub fn name_string_index(&self) -> StringHandle {
99+
self.1
100+
}
101+
}
102+
95103
/// The handle for a library, obtained from [`Profile::add_lib`](crate::Profile::add_lib).
96104
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
97105
pub struct LibraryHandle(usize);

‎fxprof-processed-profile/src/process.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::hash::Hash;
44
use crate::frame_table::InternalFrameAddress;
55
use crate::global_lib_table::{GlobalLibTable, LibraryHandle};
66
use crate::lib_mappings::LibMappings;
7+
use crate::string_table::ProfileStringTable;
78
use crate::Timestamp;
89

910
/// A thread. Can be created with [`Profile::add_thread`](crate::Profile::add_thread).
@@ -90,6 +91,7 @@ impl Process {
9091
&mut self,
9192
global_libs: &mut GlobalLibTable,
9293
kernel_libs: &mut LibMappings<LibraryHandle>,
94+
string_table: &mut ProfileStringTable,
9395
address: u64,
9496
) -> InternalFrameAddress {
9597
// Try to find the address in the kernel libs first, and then in the process libs.
@@ -98,7 +100,7 @@ impl Process {
98100
.or_else(|| self.libs.convert_address(address))
99101
{
100102
Some((relative_address, lib_handle)) => {
101-
let global_lib_index = global_libs.index_for_used_lib(*lib_handle);
103+
let global_lib_index = global_libs.index_for_used_lib(*lib_handle, string_table);
102104
InternalFrameAddress::InLib(relative_address, global_lib_index)
103105
}
104106
None => InternalFrameAddress::Unknown(address),

0 commit comments

Comments
 (0)