Skip to content
This repository was archived by the owner on Jan 31, 2025. It is now read-only.

Commit ac88ecb

Browse files
authored
Add SelectionData for tracking selections (#4725)
SelectionData contains the underlying data that any of the sampling tabs may need. This makes it easier and quicker to swap between the data of a full capture, a selection, or an inspection. The inspection isn't taking full advantage of this data structure yet as it's still branched, but I hope to change this in a future PR. Bug: http://b/264437402
1 parent d30f9fb commit ac88ecb

File tree

13 files changed

+201
-63
lines changed

13 files changed

+201
-63
lines changed

src/OrbitGl/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ target_sources(
5858
include/OrbitGl/SamplingReport.h
5959
include/OrbitGl/SchedulerTrack.h
6060
include/OrbitGl/SchedulingStats.h
61+
include/OrbitGl/SelectionData.h
6162
include/OrbitGl/ShortenStringWithEllipsis.h
6263
include/OrbitGl/SimpleTimings.h
6364
include/OrbitGl/StaticTimeGraphLayout.h
@@ -133,6 +134,7 @@ target_sources(
133134
SamplingReport.cpp
134135
SchedulerTrack.cpp
135136
SchedulingStats.cpp
137+
SelectionData.cpp
136138
SimpleTimings.cpp
137139
SymbolLoader.cpp
138140
SystemMemoryTrack.cpp

src/OrbitGl/CallstackThreadBar.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ void CallstackThreadBar::DoUpdatePrimitives(PrimitiveAssembler& primitive_assemb
151151
primitive_assembler.AddVerticalLine({pos_x, GetPos()[1]}, track_height, z, green_selection);
152152
};
153153
const orbit_client_data::CallstackData& selection_callstack_data =
154-
capture_data_->selection_callstack_data();
154+
app_->GetSelectedCallstackData();
155155
if (GetThreadId() == orbit_base::kAllProcessThreadsTid) {
156156
selection_callstack_data.ForEachCallstackEventInTimeRangeDiscretized(
157157
min_tick, max_tick, resolution_in_pixels, action_on_selected_callstack_events);

src/OrbitGl/OrbitApp.cpp

Lines changed: 58 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ constexpr const char* kWineSyscallDispatcherFunctionName = "__wine_syscall_dispa
186186
constexpr std::string_view kGgpVlkModulePathSubstring = "ggpvlk.so";
187187
const TimeRange kDefaultTimeRange =
188188
TimeRange(std::numeric_limits<uint64_t>::min(), std::numeric_limits<uint64_t>::max());
189+
const CallstackData kEmptyCallstackData;
189190

190191
orbit_data_views::PresetLoadState GetPresetLoadStateForProcess(const PresetFile& preset,
191192
const ProcessData* process) {
@@ -435,10 +436,13 @@ Future<void> OrbitApp::OnCaptureComplete() {
435436
std::move(post_processed_sampling_data));
436437
RefreshCaptureView();
437438

438-
SetSamplingReport(&GetCaptureData().GetCallstackData(),
439-
&GetCaptureData().post_processed_sampling_data());
440-
SetTopDownView(GetCaptureData().post_processed_sampling_data());
441-
SetBottomUpView(GetCaptureData().post_processed_sampling_data());
439+
full_capture_selection_ = std::make_unique<SelectionData>(
440+
*module_manager_, GetCaptureData(), GetCaptureData().post_processed_sampling_data(),
441+
&GetCaptureData().GetCallstackData());
442+
SetSamplingReport(&full_capture_selection_->GetCallstackData(),
443+
&full_capture_selection_->GetPostProcessedSamplingData());
444+
main_window_->SetTopDownView(full_capture_selection_->GetTopDownView());
445+
main_window_->SetBottomUpView(full_capture_selection_->GetBottomUpView());
442446

443447
ORBIT_CHECK(capture_stopped_callback_);
444448
capture_stopped_callback_();
@@ -2249,7 +2253,6 @@ void OrbitApp::SetCaptureDataSelectionFields(
22492253
}
22502254

22512255
void OrbitApp::SelectCallstackEvents(absl::Span<const CallstackEvent> selected_callstack_events) {
2252-
main_window_->ClearCallstackInspection();
22532256
SetCaptureDataSelectionFields(selected_callstack_events);
22542257
SetSelectionTopDownView(GetCaptureData().selection_post_processed_sampling_data(),
22552258
GetCaptureData());
@@ -2261,16 +2264,13 @@ void OrbitApp::SelectCallstackEvents(absl::Span<const CallstackEvent> selected_c
22612264
}
22622265

22632266
void OrbitApp::InspectCallstackEvents(absl::Span<const CallstackEvent> selected_callstack_events) {
2264-
SetCaptureDataSelectionFields(selected_callstack_events);
2265-
main_window_->SetCallstackInspection(
2266-
CallTreeView::CreateTopDownViewFromPostProcessedSamplingData(
2267-
GetCaptureData().selection_post_processed_sampling_data(), *module_manager_,
2268-
GetCaptureData()),
2269-
CallTreeView::CreateBottomUpViewFromPostProcessedSamplingData(
2270-
GetCaptureData().selection_post_processed_sampling_data(), *module_manager_,
2271-
GetCaptureData()),
2272-
GetOrCreateSelectionCallstackDataView(), &GetCaptureData().selection_callstack_data(),
2273-
&GetCaptureData().selection_post_processed_sampling_data());
2267+
auto selection = std::make_unique<SelectionData>(*module_manager_, GetCaptureData(),
2268+
selected_callstack_events);
2269+
main_window_->SetCallstackInspection(selection->GetTopDownView(), selection->GetBottomUpView(),
2270+
GetOrCreateDataView(DataViewType::kCallstack),
2271+
&selection->GetCallstackData(),
2272+
&selection->GetPostProcessedSamplingData());
2273+
inspection_selection_ = std::move(selection);
22742274
FireRefreshCallbacks();
22752275
}
22762276

@@ -2281,8 +2281,8 @@ void OrbitApp::ClearSelectionTabs() {
22812281
}
22822282

22832283
void OrbitApp::ClearInspection() {
2284-
SetCaptureDataSelectionFields(std::vector<CallstackEvent>());
22852284
main_window_->ClearCallstackInspection();
2285+
inspection_selection_.reset();
22862286
FireRefreshCallbacks();
22872287
}
22882288

@@ -2297,10 +2297,18 @@ void OrbitApp::UpdateAfterSymbolLoading() {
22972297
orbit_client_model::CreatePostProcessedSamplingData(capture_data.GetCallstackData(),
22982298
capture_data, *module_manager_);
22992299
GetMutableCaptureData().set_post_processed_sampling_data(post_processed_sampling_data);
2300-
main_window_->UpdateSamplingReport(&capture_data.GetCallstackData(),
2301-
&capture_data.post_processed_sampling_data());
2302-
SetTopDownView(capture_data.post_processed_sampling_data());
2303-
SetBottomUpView(capture_data.post_processed_sampling_data());
2300+
auto selection = std::make_unique<SelectionData>(*module_manager_, GetCaptureData(),
2301+
GetCaptureData().post_processed_sampling_data(),
2302+
&GetCaptureData().GetCallstackData());
2303+
main_window_->SetTopDownView(selection->GetTopDownView());
2304+
main_window_->SetBottomUpView(selection->GetBottomUpView());
2305+
main_window_->UpdateSamplingReport(&selection->GetCallstackData(),
2306+
&selection->GetPostProcessedSamplingData());
2307+
full_capture_selection_ = std::move(selection);
2308+
2309+
main_window_->ClearCallstackInspection();
2310+
inspection_selection_.reset();
2311+
time_range_thread_selection_.reset();
23042312

23052313
PostProcessedSamplingData selection_post_processed_sampling_data =
23062314
orbit_client_model::CreatePostProcessedSamplingData(capture_data.selection_callstack_data(),
@@ -2788,12 +2796,12 @@ void OrbitApp::ClearTimeRangeSelection() {
27882796
}
27892797

27902798
void OrbitApp::ClearThreadAndTimeRangeSelection() {
2791-
SetCaptureDataSelectionFields(std::vector<CallstackEvent>());
27922799
main_window_->SetLiveTabScopeStatsCollection(GetCaptureData().GetAllScopeStatsCollection());
2793-
SetTopDownView(GetCaptureData().post_processed_sampling_data());
2794-
SetBottomUpView(GetCaptureData().post_processed_sampling_data());
2795-
SetSamplingReport(&GetCaptureData().GetCallstackData(),
2796-
&GetCaptureData().post_processed_sampling_data());
2800+
main_window_->SetTopDownView(full_capture_selection_->GetTopDownView());
2801+
main_window_->SetBottomUpView(full_capture_selection_->GetBottomUpView());
2802+
SetSamplingReport(&full_capture_selection_->GetCallstackData(),
2803+
&full_capture_selection_->GetPostProcessedSamplingData());
2804+
time_range_thread_selection_.reset();
27972805

27982806
FireRefreshCallbacks();
27992807
}
@@ -2803,6 +2811,7 @@ void OrbitApp::OnThreadOrTimeRangeSelectionChange() {
28032811
if (!HasCaptureData() || !absl::GetFlag(FLAGS_time_range_selection)) return;
28042812

28052813
main_window_->ClearCallstackInspection();
2814+
inspection_selection_.reset();
28062815

28072816
uint32_t thread_id = data_manager_->selected_thread_id();
28082817
bool has_time_range = data_manager_->GetSelectionTimeRange().has_value();
@@ -2813,21 +2822,35 @@ void OrbitApp::OnThreadOrTimeRangeSelectionChange() {
28132822

28142823
TimeRange time_range =
28152824
has_time_range ? data_manager_->GetSelectionTimeRange().value() : kDefaultTimeRange;
2825+
std::vector<CallstackEvent> callstack_events;
28162826
if (thread_id == kAllProcessThreadsTid) {
2817-
SetCaptureDataSelectionFields(GetCaptureData().GetCallstackData().GetCallstackEventsInTimeRange(
2818-
time_range.start, time_range.end));
2827+
callstack_events = GetCaptureData().GetCallstackData().GetCallstackEventsInTimeRange(
2828+
time_range.start, time_range.end);
28192829
} else {
2820-
SetCaptureDataSelectionFields(
2821-
GetCaptureData().GetCallstackData().GetCallstackEventsOfTidInTimeRange(
2822-
thread_id, time_range.start, time_range.end));
2830+
callstack_events = GetCaptureData().GetCallstackData().GetCallstackEventsOfTidInTimeRange(
2831+
thread_id, time_range.start, time_range.end);
28232832
}
2824-
2833+
auto selection =
2834+
std::make_unique<SelectionData>(*module_manager_, GetCaptureData(), callstack_events);
28252835
main_window_->SetLiveTabScopeStatsCollection(
28262836
GetCaptureData().CreateScopeStatsCollection(thread_id, time_range.start, time_range.end));
2827-
SetTopDownView(GetCaptureData().selection_post_processed_sampling_data());
2828-
SetBottomUpView(GetCaptureData().selection_post_processed_sampling_data());
2829-
SetSamplingReport(&GetCaptureData().selection_callstack_data(),
2830-
&GetCaptureData().selection_post_processed_sampling_data());
2837+
main_window_->SetTopDownView(selection->GetTopDownView());
2838+
main_window_->SetBottomUpView(selection->GetBottomUpView());
2839+
SetSamplingReport(&selection->GetCallstackData(), &selection->GetPostProcessedSamplingData());
2840+
time_range_thread_selection_ = std::move(selection);
28312841

28322842
FireRefreshCallbacks();
2843+
}
2844+
2845+
const CallstackData& OrbitApp::GetSelectedCallstackData() const {
2846+
if (absl::GetFlag(FLAGS_time_range_selection)) {
2847+
if (inspection_selection_ != nullptr) {
2848+
return inspection_selection_->GetCallstackData();
2849+
}
2850+
if (time_range_thread_selection_ != nullptr) {
2851+
return time_range_thread_selection_->GetCallstackData();
2852+
}
2853+
return kEmptyCallstackData;
2854+
}
2855+
return GetCaptureData().selection_callstack_data();
28332856
}

src/OrbitGl/SelectionData.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
// Copyright (c) 2023 The Orbit Authors. All rights reserved.
3+
// Use of this source code is governed by a BSD-style license that can be
4+
// found in the LICENSE file.
5+
6+
#include "OrbitGl/SelectionData.h"
7+
8+
#include <utility>
9+
10+
#include "ClientData/CallstackData.h"
11+
#include "ClientData/CallstackEvent.h"
12+
#include "ClientModel/SamplingDataPostProcessor.h"
13+
14+
using orbit_client_data::CallstackData;
15+
using orbit_client_data::CallstackEvent;
16+
using orbit_client_data::CaptureData;
17+
using orbit_client_data::ModuleManager;
18+
using orbit_client_data::PostProcessedSamplingData;
19+
20+
SelectionData::SelectionData(const ModuleManager& module_manager, const CaptureData& capture_data,
21+
PostProcessedSamplingData post_processed_sampling_data,
22+
const CallstackData* callstack_data)
23+
: post_processed_sampling_data_(std::move(post_processed_sampling_data)),
24+
callstack_data_pointer_(callstack_data) {
25+
top_down_view_ = CallTreeView::CreateTopDownViewFromPostProcessedSamplingData(
26+
post_processed_sampling_data_, module_manager, capture_data);
27+
bottom_up_view_ = CallTreeView::CreateBottomUpViewFromPostProcessedSamplingData(
28+
post_processed_sampling_data_, module_manager, capture_data);
29+
}
30+
31+
SelectionData::SelectionData(const ModuleManager& module_manager, const CaptureData& capture_data,
32+
absl::Span<const CallstackEvent> callstack_events) {
33+
for (const CallstackEvent& event : callstack_events) {
34+
callstack_data_object_.AddCallstackFromKnownCallstackData(event,
35+
capture_data.GetCallstackData());
36+
}
37+
post_processed_sampling_data_ = orbit_client_model::CreatePostProcessedSamplingData(
38+
callstack_data_object_, capture_data, module_manager);
39+
top_down_view_ = CallTreeView::CreateTopDownViewFromPostProcessedSamplingData(
40+
post_processed_sampling_data_, module_manager, capture_data);
41+
bottom_up_view_ = CallTreeView::CreateBottomUpViewFromPostProcessedSamplingData(
42+
post_processed_sampling_data_, module_manager, capture_data);
43+
}

src/OrbitGl/include/OrbitGl/MainWindowInterface.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ class MainWindowInterface {
7979
virtual ~MainWindowInterface() = default;
8080

8181
virtual void SetCallstackInspection(
82-
std::unique_ptr<CallTreeView> top_down_view, std::unique_ptr<CallTreeView> bottom_up_view,
82+
std::shared_ptr<const CallTreeView> top_down_view,
83+
std::shared_ptr<const CallTreeView> bottom_up_view,
8384
orbit_data_views::DataView* callstack_data_view,
8485
const orbit_client_data::CallstackData* callstack_data,
8586
const orbit_client_data::PostProcessedSamplingData* post_processed_sampling_data) = 0;
@@ -91,10 +92,10 @@ class MainWindowInterface {
9192
virtual void SetLiveTabScopeStatsCollection(
9293
std::shared_ptr<const orbit_client_data::ScopeStatsCollection> scope_collection) = 0;
9394

94-
virtual void SetTopDownView(std::unique_ptr<CallTreeView> view) = 0;
95-
virtual void SetBottomUpView(std::unique_ptr<CallTreeView> view) = 0;
96-
virtual void SetSelectionTopDownView(std::unique_ptr<CallTreeView> view) = 0;
97-
virtual void SetSelectionBottomUpView(std::unique_ptr<CallTreeView> view) = 0;
95+
virtual void SetTopDownView(std::shared_ptr<const CallTreeView> view) = 0;
96+
virtual void SetBottomUpView(std::shared_ptr<const CallTreeView> view) = 0;
97+
virtual void SetSelectionTopDownView(std::shared_ptr<const CallTreeView> view) = 0;
98+
virtual void SetSelectionBottomUpView(std::shared_ptr<const CallTreeView> view) = 0;
9899
virtual void SetSamplingReport(
99100
orbit_data_views::DataView* callstack_data_view,
100101
const orbit_client_data::CallstackData* callstack_data,

src/OrbitGl/include/OrbitGl/OrbitApp.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
#include "OrbitGl/IntrospectionWindow.h"
8484
#include "OrbitGl/MainWindowInterface.h"
8585
#include "OrbitGl/ManualInstrumentationManager.h"
86+
#include "OrbitGl/SelectionData.h"
8687
#include "OrbitGl/SymbolLoader.h"
8788
#include "OrbitGl/TimeGraph.h"
8889
#include "PresetFile/PresetFile.h"
@@ -399,6 +400,8 @@ class OrbitApp final : public DataViewFactory,
399400
void ClearInspection();
400401
void ClearSelectionTabs();
401402

403+
const orbit_client_data::CallstackData& GetSelectedCallstackData() const;
404+
402405
void SelectTracepoint(const orbit_grpc_protos::TracepointInfo& tracepoint) override;
403406
void DeselectTracepoint(const orbit_grpc_protos::TracepointInfo& tracepoint) override;
404407

@@ -583,6 +586,10 @@ class OrbitApp final : public DataViewFactory,
583586
std::optional<orbit_gl::SymbolLoader> symbol_loader_;
584587
static constexpr std::chrono::milliseconds kMaxPostProcessingInterval{1000};
585588
orbit_qt_utils::Throttle update_after_symbol_loading_throttle_{kMaxPostProcessingInterval};
589+
590+
std::unique_ptr<SelectionData> full_capture_selection_;
591+
std::unique_ptr<SelectionData> time_range_thread_selection_;
592+
std::unique_ptr<SelectionData> inspection_selection_;
586593
};
587594

588595
#endif // ORBIT_GL_APP_H_
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
2+
// Copyright (c) 2023 The Orbit Authors. All rights reserved.
3+
// Use of this source code is governed by a BSD-style license that can be
4+
// found in the LICENSE file.
5+
6+
#ifndef CLIENT_DATA_SELECTION_DATA_H_
7+
#define CLIENT_DATA_SELECTION_DATA_H_
8+
9+
#include "ClientData/CaptureData.h"
10+
#include "ClientData/ModuleManager.h"
11+
#include "ClientData/PostProcessedSamplingData.h"
12+
#include "OrbitGl/CallTreeView.h"
13+
14+
// This is meant to hold the data needed to update the data tabs to a specific selection.
15+
class SelectionData {
16+
public:
17+
// Delete move/copy operators because callstack_data_pointer_ is pointing to a variable inside the
18+
// class.
19+
SelectionData(const SelectionData& other) = delete;
20+
SelectionData& operator=(const SelectionData& other) = delete;
21+
SelectionData(SelectionData&& other) = delete;
22+
SelectionData& operator=(SelectionData&& other) = delete;
23+
24+
SelectionData(const orbit_client_data::ModuleManager& module_manager,
25+
const orbit_client_data::CaptureData& capture_data,
26+
orbit_client_data::PostProcessedSamplingData post_processed_sampling_data,
27+
const orbit_client_data::CallstackData* callstack_data);
28+
29+
SelectionData(const orbit_client_data::ModuleManager& module_manager,
30+
const orbit_client_data::CaptureData& capture_data,
31+
absl::Span<const orbit_client_data::CallstackEvent> callstack_events);
32+
33+
std::shared_ptr<const CallTreeView> GetTopDownView() const { return top_down_view_; }
34+
35+
std::shared_ptr<const CallTreeView> GetBottomUpView() const { return bottom_up_view_; }
36+
37+
const orbit_client_data::PostProcessedSamplingData& GetPostProcessedSamplingData() const {
38+
return post_processed_sampling_data_;
39+
}
40+
41+
const orbit_client_data::CallstackData& GetCallstackData() const {
42+
ORBIT_CHECK(callstack_data_pointer_);
43+
return *callstack_data_pointer_;
44+
}
45+
46+
private:
47+
std::shared_ptr<CallTreeView> top_down_view_;
48+
std::shared_ptr<CallTreeView> bottom_up_view_;
49+
50+
orbit_client_data::PostProcessedSamplingData post_processed_sampling_data_;
51+
52+
orbit_client_data::CallstackData callstack_data_object_;
53+
// Depending on how SelectionData is created, this either points to callstack_data_object_ or to
54+
// the CallstackData object passed into SelectionData.
55+
const orbit_client_data::CallstackData* callstack_data_pointer_ = &callstack_data_object_;
56+
};
57+
58+
#endif // CLIENT_DATA_SELECTION_DATA_H_

src/OrbitQt/CallTreeViewItemModel.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include "OrbitBase/Logging.h"
2121
#include "OrbitBase/ThreadConstants.h"
2222

23-
CallTreeViewItemModel::CallTreeViewItemModel(std::unique_ptr<CallTreeView> call_tree_view,
23+
CallTreeViewItemModel::CallTreeViewItemModel(std::shared_ptr<const CallTreeView> call_tree_view,
2424
QObject* parent)
2525
: QAbstractItemModel{parent}, call_tree_view_{std::move(call_tree_view)} {}
2626

@@ -362,7 +362,7 @@ QModelIndex CallTreeViewItemModel::index(int row, int column, const QModelIndex&
362362
return {};
363363
}
364364

365-
CallTreeNode* parent_item = nullptr;
365+
const CallTreeNode* parent_item = nullptr;
366366
if (!parent.isValid()) {
367367
parent_item = call_tree_view_.get();
368368
} else {

src/OrbitQt/CallTreeWidget.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ CallTreeWidget::CallTreeWidget(QWidget* parent)
105105

106106
CallTreeWidget::~CallTreeWidget() = default;
107107

108-
void CallTreeWidget::SetCallTreeView(std::unique_ptr<CallTreeView> call_tree_view,
108+
void CallTreeWidget::SetCallTreeView(std::shared_ptr<const CallTreeView> call_tree_view,
109109
std::unique_ptr<QIdentityProxyModel> hide_values_proxy_model) {
110110
ORBIT_CHECK(app_ != nullptr);
111111

@@ -216,7 +216,7 @@ static void ExpandRecursivelyWithThreshold(QTreeView* tree_view, const QModelInd
216216
}
217217
}
218218

219-
void CallTreeWidget::SetTopDownView(std::unique_ptr<CallTreeView> top_down_view) {
219+
void CallTreeWidget::SetTopDownView(std::shared_ptr<const CallTreeView> top_down_view) {
220220
// Expand recursively if CallTreeView contains information for a single thread.
221221
bool should_expand = IsSliderEnabled() && top_down_view->thread_count() == 1;
222222

@@ -230,14 +230,14 @@ void CallTreeWidget::SetTopDownView(std::unique_ptr<CallTreeView> top_down_view)
230230
}
231231
}
232232

233-
void CallTreeWidget::SetBottomUpView(std::unique_ptr<CallTreeView> bottom_up_view) {
233+
void CallTreeWidget::SetBottomUpView(std::shared_ptr<const CallTreeView> bottom_up_view) {
234234
SetCallTreeView(std::move(bottom_up_view),
235235
std::make_unique<HideValuesForBottomUpProxyModel>(nullptr));
236236
// Don't show the "Exclusive" column for the bottom-up tree, it provides no useful information.
237237
ui_->callTreeTreeView->hideColumn(CallTreeViewItemModel::kExclusive);
238238
}
239239

240-
void CallTreeWidget::SetInspection(std::unique_ptr<CallTreeView> call_tree_view) {
240+
void CallTreeWidget::SetInspection(std::shared_ptr<const CallTreeView> call_tree_view) {
241241
ORBIT_CHECK(hide_values_proxy_model_ != nullptr);
242242
ui_->inspectionNoticeWidget->show();
243243
inspection_model_ = std::make_unique<CallTreeViewItemModel>(std::move(call_tree_view));

0 commit comments

Comments
 (0)