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

Commit 38fa05a

Browse files
authored
Allow thread selection alongside time range (#4659)
This allows users to select a thread either on it's own or in conjunction with a time range selection. The UI needs some improvements to make this more obvious, but the functionality is all there in this PR. It is still hidden behind the flag --time_range_selection so will nto affect any current workflows. Bug: http://b/240111360
1 parent c50bf15 commit 38fa05a

File tree

5 files changed

+86
-35
lines changed

5 files changed

+86
-35
lines changed

src/ClientData/CaptureData.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "ClientData/ScopeInfo.h"
2222
#include "ClientData/ScopeStatsCollection.h"
2323
#include "GrpcProtos/process.pb.h"
24+
#include "OrbitBase/ThreadConstants.h"
2425
#include "OrbitBase/Typedef.h"
2526
#include "SymbolProvider/ModuleIdentifier.h"
2627

@@ -276,23 +277,34 @@ std::shared_ptr<const ScopeStatsCollection> CaptureData::GetAllScopeStatsCollect
276277
}
277278

278279
std::unique_ptr<const ScopeStatsCollection> CaptureData::CreateScopeStatsCollection(
279-
uint64_t min_tick, uint64_t max_tick) const {
280+
uint32_t thread_id, uint64_t min_tick, uint64_t max_tick) const {
280281
ORBIT_CHECK(scope_id_provider_);
281-
auto timers = GetAllScopeTimers(kAllValidScopeTypes, min_tick, max_tick, /*exclusive=*/true);
282+
std::vector<uint32_t> thread_ids = thread_id == orbit_base::kAllProcessThreadsTid
283+
? GetThreadTrackDataProvider()->GetAllThreadIds()
284+
: std::vector<uint32_t>{thread_id};
285+
auto timers = GetAllScopeTimersByTids(thread_ids, kAllValidScopeTypes, min_tick, max_tick,
286+
/*exclusive=*/true);
282287
return std::make_unique<ScopeStatsCollection>(*scope_id_provider_, timers);
283288
}
284289

285290
[[nodiscard]] std::vector<const TimerInfo*> CaptureData::GetAllScopeTimers(
286291
const absl::flat_hash_set<ScopeType> types, uint64_t min_tick, uint64_t max_tick,
287292
bool exclusive) const {
293+
std::vector<uint32_t> thread_ids = GetThreadTrackDataProvider()->GetAllThreadIds();
294+
return GetAllScopeTimersByTids(thread_ids, types, min_tick, max_tick, exclusive);
295+
}
296+
297+
[[nodiscard]] std::vector<const TimerInfo*> CaptureData::GetAllScopeTimersByTids(
298+
const std::vector<uint32_t>& thread_ids, const absl::flat_hash_set<ScopeType> types,
299+
uint64_t min_tick, uint64_t max_tick, bool exclusive) const {
288300
std::vector<const TimerInfo*> result;
289301

290302
// The timers corresponding to dynamically instrumented functions and manual instrumentation
291303
// (kApiScope) are stored in ThreadTracks. Hence, they're acquired separately from the manual
292304
// async (kApiScope).
293305
if (types.contains(ScopeType::kApiScope) ||
294306
types.contains(ScopeType::kDynamicallyInstrumentedFunction)) {
295-
for (const uint32_t thread_id : GetThreadTrackDataProvider()->GetAllThreadIds()) {
307+
for (const uint32_t thread_id : thread_ids) {
296308
const std::vector<const TimerInfo*> thread_track_timers =
297309
GetThreadTrackDataProvider()->GetTimers(thread_id, min_tick, max_tick, exclusive);
298310
std::copy_if(std::begin(thread_track_timers), std::end(thread_track_timers),

src/ClientData/include/ClientData/CaptureData.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,11 @@ class CaptureData {
265265
uint64_t min_tick = std::numeric_limits<uint64_t>::min(),
266266
uint64_t max_tick = std::numeric_limits<uint64_t>::max(), bool exclusive = false) const;
267267

268+
[[nodiscard]] std::vector<const TimerInfo*> GetAllScopeTimersByTids(
269+
const std::vector<uint32_t>& thread_ids, absl::flat_hash_set<ScopeType> types,
270+
uint64_t min_tick = std::numeric_limits<uint64_t>::min(),
271+
uint64_t max_tick = std::numeric_limits<uint64_t>::max(), bool exclusive = false) const;
272+
268273
[[nodiscard]] std::vector<const TimerInfo*> GetTimersForScope(
269274
ScopeId scope_id, uint64_t min_tick = std::numeric_limits<uint64_t>::min(),
270275
uint64_t max_tick = std::numeric_limits<uint64_t>::max()) const;
@@ -277,7 +282,7 @@ class CaptureData {
277282
int64_t thread_id, uint64_t timestamp) const;
278283

279284
[[nodiscard]] std::unique_ptr<const ScopeStatsCollection> CreateScopeStatsCollection(
280-
uint64_t min_tick, uint64_t max_tick) const;
285+
uint32_t thread_id, uint64_t min_tick, uint64_t max_tick) const;
281286
[[nodiscard]] std::shared_ptr<const ScopeStatsCollection> GetAllScopeStatsCollection() const;
282287

283288
private:

src/OrbitGl/CaptureWindow.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -290,13 +290,11 @@ void CaptureWindow::RightUp() {
290290
}
291291
}
292292

293-
if (absl::GetFlag(FLAGS_time_range_selection)) {
294-
if (select_start_pos_world_[0] == select_stop_pos_world_[0]) {
295-
app_->ClearTimeRangeSelection();
296-
} else {
297-
app_->OnTimeRangeSelection(TimeRange(std::min(select_start_time_, select_stop_time_),
298-
std::max(select_start_time_, select_stop_time_)));
299-
}
293+
if (select_start_pos_world_[0] == select_stop_pos_world_[0]) {
294+
app_->ClearTimeRangeSelection();
295+
} else {
296+
app_->OnTimeRangeSelection(TimeRange(std::min(select_start_time_, select_stop_time_),
297+
std::max(select_start_time_, select_stop_time_)));
300298
}
301299

302300
if (time_graph_ != nullptr) {

src/OrbitGl/OrbitApp.cpp

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <absl/container/flat_hash_map.h>
88
#include <absl/container/flat_hash_set.h>
99
#include <absl/flags/flag.h>
10+
#include <absl/flags/internal/flag.h>
1011
#include <absl/hash/hash.h>
1112
#include <absl/strings/match.h>
1213
#include <absl/strings/str_cat.h>
@@ -117,6 +118,7 @@
117118

118119
using orbit_base::CanceledOr;
119120
using orbit_base::Future;
121+
using orbit_base::kAllProcessThreadsTid;
120122
using orbit_base::NotFoundOr;
121123

122124
using orbit_capture_client::CaptureClient;
@@ -183,6 +185,8 @@ namespace {
183185
constexpr const char* kNtdllSoFileName = "ntdll.so";
184186
constexpr const char* kWineSyscallDispatcherFunctionName = "__wine_syscall_dispatcher";
185187
constexpr std::string_view kGgpVlkModulePathSubstring = "ggpvlk.so";
188+
const TimeRange kDefaultTimeRange =
189+
TimeRange(std::numeric_limits<uint64_t>::min(), std::numeric_limits<uint64_t>::max());
186190

187191
orbit_data_views::PresetLoadState GetPresetLoadStateForProcess(const PresetFile& preset,
188192
const ProcessData* process) {
@@ -2156,9 +2160,15 @@ void OrbitApp::SetVisibleScopeIds(absl::flat_hash_set<ScopeId> visible_scope_ids
21562160
}
21572161

21582162
bool OrbitApp::IsTimerActive(const TimerInfo& timer) const {
2159-
const std::optional<TimeRange>& time_range = data_manager_->GetSelectionTimeRange();
2160-
if (time_range.has_value() && !time_range.value().IsTimerInRange(timer)) {
2161-
return false;
2163+
if (absl::GetFlag(FLAGS_time_range_selection)) {
2164+
const std::optional<TimeRange>& time_range = data_manager_->GetSelectionTimeRange();
2165+
if (time_range.has_value() && !time_range.value().IsTimerInRange(timer)) {
2166+
return false;
2167+
}
2168+
const uint32_t thread_id = data_manager_->selected_thread_id();
2169+
if (thread_id != kAllProcessThreadsTid && thread_id != timer.thread_id()) {
2170+
return false;
2171+
}
21622172
}
21632173
const std::optional<ScopeId> scope_id = GetCaptureData().ProvideScopeId(timer);
21642174
if (!scope_id.has_value()) {
@@ -2180,7 +2190,8 @@ ThreadID OrbitApp::selected_thread_id() const { return data_manager_->selected_t
21802190

21812191
void OrbitApp::set_selected_thread_id(ThreadID thread_id) {
21822192
RequestUpdatePrimitives();
2183-
return data_manager_->set_selected_thread_id(thread_id);
2193+
data_manager_->set_selected_thread_id(thread_id);
2194+
OnThreadOrTimeRangeSelectionChange();
21842195
}
21852196

21862197
std::optional<ThreadStateSliceInfo> OrbitApp::selected_thread_state_slice() const {
@@ -2290,8 +2301,7 @@ void OrbitApp::InspectCallstackEvents(absl::Span<const CallstackEvent> selected_
22902301
FireRefreshCallbacks();
22912302
}
22922303

2293-
void OrbitApp::ClearAllSelections() {
2294-
ClearInspection();
2304+
void OrbitApp::ClearSelectionTabs() {
22952305
ClearSelectionReport();
22962306
ClearSelectionTopDownView();
22972307
ClearSelectionBottomUpView();
@@ -2806,33 +2816,57 @@ const ProcessData& OrbitApp::GetConnectedOrLoadedProcess() const {
28062816
}
28072817

28082818
void OrbitApp::OnTimeRangeSelection(TimeRange time_range) {
2809-
ClearAllSelections();
2810-
2811-
auto selected_callstack_events =
2812-
GetCaptureData().GetCallstackData().GetCallstackEventsInTimeRange(time_range.start,
2813-
time_range.end);
2814-
SetCaptureDataSelectionFields(selected_callstack_events, /*origin_is_multiple_threads=*/true);
2815-
2816-
main_window_->SetLiveTabScopeStatsCollection(
2817-
GetCaptureData().CreateScopeStatsCollection(time_range.start, time_range.end));
2818-
SetTopDownView(GetCaptureData().selection_post_processed_sampling_data());
2819-
SetBottomUpView(GetCaptureData().selection_post_processed_sampling_data());
2820-
SetSamplingReport(&GetCaptureData().selection_callstack_data(),
2821-
&GetCaptureData().selection_post_processed_sampling_data());
28222819
data_manager_->SetSelectionTimeRange(time_range);
2823-
2824-
FireRefreshCallbacks();
2820+
OnThreadOrTimeRangeSelectionChange();
28252821
}
28262822

28272823
void OrbitApp::ClearTimeRangeSelection() {
2828-
ClearAllSelections();
2824+
data_manager_->ClearSelectionTimeRange();
2825+
OnThreadOrTimeRangeSelectionChange();
2826+
}
28292827

2828+
void OrbitApp::ClearThreadAndTimeRangeSelection() {
28302829
main_window_->SetLiveTabScopeStatsCollection(GetCaptureData().GetAllScopeStatsCollection());
28312830
SetTopDownView(GetCaptureData().post_processed_sampling_data());
28322831
SetBottomUpView(GetCaptureData().post_processed_sampling_data());
28332832
SetSamplingReport(&GetCaptureData().GetCallstackData(),
28342833
&GetCaptureData().post_processed_sampling_data());
2835-
data_manager_->ClearSelectionTimeRange();
2834+
2835+
FireRefreshCallbacks();
2836+
}
2837+
2838+
void OrbitApp::OnThreadOrTimeRangeSelectionChange() {
2839+
if (!HasCaptureData() || !absl::GetFlag(FLAGS_time_range_selection)) return;
2840+
2841+
ClearSelectionTabs();
2842+
ClearInspection();
2843+
2844+
uint32_t thread_id = data_manager_->selected_thread_id();
2845+
bool has_time_range = data_manager_->GetSelectionTimeRange().has_value();
2846+
if (thread_id == kAllProcessThreadsTid && !has_time_range) {
2847+
ClearThreadAndTimeRangeSelection();
2848+
return;
2849+
}
2850+
2851+
TimeRange time_range =
2852+
has_time_range ? data_manager_->GetSelectionTimeRange().value() : kDefaultTimeRange;
2853+
if (thread_id == kAllProcessThreadsTid) {
2854+
SetCaptureDataSelectionFields(GetCaptureData().GetCallstackData().GetCallstackEventsInTimeRange(
2855+
time_range.start, time_range.end),
2856+
/*origin_is_multiple_threads=*/true);
2857+
} else {
2858+
SetCaptureDataSelectionFields(
2859+
GetCaptureData().GetCallstackData().GetCallstackEventsOfTidInTimeRange(
2860+
thread_id, time_range.start, time_range.end),
2861+
/*origin_is_multiple_threads=*/false);
2862+
}
2863+
2864+
main_window_->SetLiveTabScopeStatsCollection(
2865+
GetCaptureData().CreateScopeStatsCollection(thread_id, time_range.start, time_range.end));
2866+
SetTopDownView(GetCaptureData().selection_post_processed_sampling_data());
2867+
SetBottomUpView(GetCaptureData().selection_post_processed_sampling_data());
2868+
SetSamplingReport(&GetCaptureData().selection_callstack_data(),
2869+
&GetCaptureData().selection_post_processed_sampling_data());
28362870

28372871
FireRefreshCallbacks();
28382872
}

src/OrbitGl/include/OrbitGl/OrbitApp.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ class OrbitApp final : public DataViewFactory,
408408
absl::Span<const orbit_client_data::CallstackEvent> selected_callstack_events,
409409
bool origin_is_multiple_threads);
410410
void ClearInspection();
411-
void ClearAllSelections();
411+
void ClearSelectionTabs();
412412

413413
void SelectTracepoint(const orbit_grpc_protos::TracepointInfo& tracepoint) override;
414414
void DeselectTracepoint(const orbit_grpc_protos::TracepointInfo& tracepoint) override;
@@ -486,6 +486,8 @@ class OrbitApp final : public DataViewFactory,
486486

487487
void OnTimeRangeSelection(orbit_client_data::TimeRange time_range);
488488
void ClearTimeRangeSelection();
489+
void OnThreadOrTimeRangeSelectionChange();
490+
void ClearThreadAndTimeRangeSelection();
489491

490492
private:
491493
void UpdateModulesAbortCaptureIfModuleWithoutBuildIdNeedsReload(

0 commit comments

Comments
 (0)