From bb8eb7063c998003a8b3d3ff30bb9c4075d80b3f Mon Sep 17 00:00:00 2001 From: Sai Ganesh Muthuraman Date: Thu, 21 May 2026 23:39:50 -0700 Subject: [PATCH] Enable scroll and zoom out in Trace Viewer V2 when loading deep-linked traces. PiperOrigin-RevId: 919479016 --- .../trace_helper/trace_pb_event_parser.cc | 9 ++++++++ .../xprof/protobuf/trace_data_response.proto | 3 +++ ...ce_data_to_compressed_delta_series_proto.h | 7 ++++++ ...a_to_compressed_delta_series_proto_test.cc | 23 +++++++++++++++++++ 4 files changed, 42 insertions(+) diff --git a/frontend/app/components/trace_viewer_v2/trace_helper/trace_pb_event_parser.cc b/frontend/app/components/trace_viewer_v2/trace_helper/trace_pb_event_parser.cc index a8402becb..b4118ab81 100644 --- a/frontend/app/components/trace_viewer_v2/trace_helper/trace_pb_event_parser.cc +++ b/frontend/app/components/trace_viewer_v2/trace_helper/trace_pb_event_parser.cc @@ -57,6 +57,15 @@ ParsedTraceEvents ParseCompressedTraceEvents( ProcessAsyncEvents(response, result); ProcessCounterEvents(response, result); + if (response.has_full_timespan_start_ps() && + response.has_full_timespan_end_ps()) { + const Milliseconds start_ms = response.full_timespan_start_ps() / 1e9; + const Milliseconds end_ms = response.full_timespan_end_ps() / 1e9; + if (start_ms <= end_ms) { + result.full_timespan = std::make_pair(start_ms, end_ms); + } + } + if (!visible_range_from_url.isNull() && !visible_range_from_url.isUndefined() && visible_range_from_url["length"].as() == 2) { diff --git a/plugin/xprof/protobuf/trace_data_response.proto b/plugin/xprof/protobuf/trace_data_response.proto index 2b84b351f..343c6caea 100644 --- a/plugin/xprof/protobuf/trace_data_response.proto +++ b/plugin/xprof/protobuf/trace_data_response.proto @@ -84,4 +84,7 @@ message TraceDataResponse { repeated string interned_strings = 5; // Details for the trace (e.g., flags for the frontend). repeated DetailItem details = 6; + // The full timespan of the trace (start time and end time in picoseconds). + optional uint64 full_timespan_start_ps = 7; + optional uint64 full_timespan_end_ps = 8; } diff --git a/xprof/convert/trace_viewer/delta_series/trace_data_to_compressed_delta_series_proto.h b/xprof/convert/trace_viewer/delta_series/trace_data_to_compressed_delta_series_proto.h index a88a13b01..6fd7144e6 100644 --- a/xprof/convert/trace_viewer/delta_series/trace_data_to_compressed_delta_series_proto.h +++ b/xprof/convert/trace_viewer/delta_series/trace_data_to_compressed_delta_series_proto.h @@ -134,6 +134,13 @@ absl::Status DeltaSeriesProtoConverter::GenerateResponse( d->set_value(detail.second); } + if (trace_->has_min_timestamp_ps()) { + response->set_full_timespan_start_ps(trace_->min_timestamp_ps()); + } + if (trace_->has_max_timestamp_ps()) { + response->set_full_timespan_end_ps(trace_->max_timestamp_ps()); + } + using TidOrName = std::variant; container.ForAllTracks([this, response](uint32_t pid, TidOrName tid_or_name, diff --git a/xprof/convert/trace_viewer/delta_series/trace_data_to_compressed_delta_series_proto_test.cc b/xprof/convert/trace_viewer/delta_series/trace_data_to_compressed_delta_series_proto_test.cc index 394354e08..269db4bdd 100644 --- a/xprof/convert/trace_viewer/delta_series/trace_data_to_compressed_delta_series_proto_test.cc +++ b/xprof/convert/trace_viewer/delta_series/trace_data_to_compressed_delta_series_proto_test.cc @@ -15,6 +15,7 @@ namespace tensorflow { namespace profiler { namespace { +using ::testing::Eq; using ::testing::EqualsProto; using ::testing::proto::Partially; @@ -416,6 +417,28 @@ TEST(DeltaSeriesProtoConverterTest, PopulatesDetails) { )pb"))); } +TEST(DeltaSeriesProtoConverterTest, PopulatesFullTimespan) { + Trace trace; + trace.set_min_timestamp_ps(12345000); + trace.set_max_timestamp_ps(67890000); + TestTraceEventsContainer container(trace); + + ASSERT_OK_AND_ASSIGN(std::string compressed_result, + ConvertTraceDataToCompressedDeltaSeriesProto( + DeltaSeriesProtoConversionOptions{}, container)); + + ASSERT_OK_AND_ASSIGN(std::string decompressed, + ZstdCompression::Decompress(compressed_result)); + + xprof::TraceDataResponse response; + ASSERT_TRUE(response.ParseFromString(decompressed)); + + EXPECT_TRUE(response.has_full_timespan_start_ps()); + EXPECT_THAT(response.full_timespan_start_ps(), Eq(12345000)); + EXPECT_TRUE(response.has_full_timespan_end_ps()); + EXPECT_THAT(response.full_timespan_end_ps(), Eq(67890000)); +} + } // namespace } // namespace profiler } // namespace tensorflow