Extract :host_tracer_utils library
PiperOrigin-RevId: 282582745
Change-Id: I8866d4ff7c43376cdfaaea7b93e6f6cf5452f7ee
diff --git a/tensorflow/core/profiler/internal/cpu/BUILD b/tensorflow/core/profiler/internal/cpu/BUILD
index 5d7f7d6..93fc8e0 100644
--- a/tensorflow/core/profiler/internal/cpu/BUILD
+++ b/tensorflow/core/profiler/internal/cpu/BUILD
@@ -6,19 +6,32 @@
)
cc_library(
- name = "host_tracer",
- srcs = ["host_tracer.cc"],
+ name = "host_tracer_utils",
+ srcs = ["host_tracer_utils.cc"],
+ hdrs = ["host_tracer_utils.h"],
+ visibility = ["//tensorflow/core/profiler:friends"],
deps = [
- "//tensorflow/core:core_cpu_lib",
"//tensorflow/core:lib",
- "//tensorflow/core:lib_internal",
- "//tensorflow/core:protos_all_cc",
"//tensorflow/core/profiler/internal:parse_annotation",
- "//tensorflow/core/profiler/internal:profiler_interface",
"//tensorflow/core/profiler/internal:traceme_recorder",
"//tensorflow/core/profiler/protobuf:xplane_proto_cc",
"//tensorflow/core/profiler/utils:xplane_builder",
"@com_google_absl//absl/container:flat_hash_map",
+ ],
+)
+
+cc_library(
+ name = "host_tracer",
+ srcs = ["host_tracer.cc"],
+ deps = [
+ ":host_tracer_utils",
+ "//tensorflow/core:core_cpu_lib",
+ "//tensorflow/core:lib",
+ "//tensorflow/core:lib_internal",
+ "//tensorflow/core:protos_all_cc",
+ "//tensorflow/core/profiler/internal:profiler_interface",
+ "//tensorflow/core/profiler/internal:traceme_recorder",
+ "//tensorflow/core/profiler/protobuf:xplane_proto_cc",
"@com_google_absl//absl/strings",
],
alwayslink = True,
diff --git a/tensorflow/core/profiler/internal/cpu/host_tracer.cc b/tensorflow/core/profiler/internal/cpu/host_tracer.cc
index 829efb9..9b32ce8 100644
--- a/tensorflow/core/profiler/internal/cpu/host_tracer.cc
+++ b/tensorflow/core/profiler/internal/cpu/host_tracer.cc
@@ -15,22 +15,19 @@
#include <utility>
#include <vector>
-#include "absl/container/flat_hash_map.h"
#include "absl/strings/str_split.h"
#include "tensorflow/core/common_runtime/step_stats_collector.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/platform/env_time.h"
-#include "tensorflow/core/profiler/internal/parse_annotation.h"
+#include "tensorflow/core/profiler/internal/cpu/host_tracer_utils.h"
#include "tensorflow/core/profiler/internal/profiler_interface.h"
#include "tensorflow/core/profiler/internal/traceme_recorder.h"
#include "tensorflow/core/profiler/protobuf/xplane.pb.h"
-#include "tensorflow/core/profiler/utils/xplane_builder.h"
#include "tensorflow/core/protobuf/config.pb.h"
#include "tensorflow/core/util/env_var.h"
namespace tensorflow {
namespace profiler {
-namespace cpu {
namespace {
// Controls TraceMeRecorder and converts TraceMeRecorder::Events into
@@ -57,10 +54,6 @@
DeviceType GetDeviceType() override { return DeviceType::kCpu; }
private:
- // Combine events created by TraceMe::ActivityStart and TraceMe::ActivityEnd,
- // which can be paired up by their activity_id.
- void MakeCompleteEvents();
-
// Level of host tracing.
const int host_trace_level_;
@@ -100,49 +93,11 @@
return Status::OK();
}
-void HostTracer::MakeCompleteEvents() {
- // Track events create by ActivityStart and copy their data to events created
- // by ActivityEnd. TraceME records events in its destructor, so this results
- // in complete events sorted by their end_time in the thread they ended.
- // Within the same thread, the record created by ActivityStart must appear
- // before the record created by ActivityEnd. Cross-thread events must be
- // processed in a separate pass. A single map can be used because the
- // activity_id is globally unique.
- absl::flat_hash_map<uint64, TraceMeRecorder::Event*> start_events;
- std::vector<TraceMeRecorder::Event*> end_events;
- for (auto& thread : events_) {
- for (auto& event : thread.events) {
- if (event.start_time && !event.end_time) { // ActivityStart
- start_events.emplace(event.activity_id, &event);
- } else if (!event.start_time && event.end_time) { // ActivityEnd
- auto iter = start_events.find(event.activity_id);
- if (iter != start_events.end()) { // same thread
- auto* start_event = iter->second;
- event.name = std::move(start_event->name);
- event.start_time = start_event->start_time;
- start_events.erase(iter);
- } else { // cross-thread
- end_events.push_back(&event);
- }
- }
- }
- }
- for (auto* event : end_events) { // cross-thread
- auto iter = start_events.find(event->activity_id);
- if (iter != start_events.end()) {
- auto* start_event = iter->second;
- event->name = std::move(start_event->name);
- event->start_time = start_event->start_time;
- start_events.erase(iter);
- }
- }
-}
-
Status HostTracer::CollectData(RunMetadata* run_metadata) {
if (recording_) {
return errors::Internal("TraceMeRecorder not stopped");
}
- MakeCompleteEvents();
+ MakeCompleteEvents(&events_);
StepStatsCollector step_stats_collector(run_metadata->mutable_step_stats());
constexpr char kUserMetadataMarker = '#';
@@ -183,43 +138,9 @@
if (recording_) {
return errors::Internal("TraceMeRecorder not stopped");
}
- MakeCompleteEvents();
- XPlaneBuilder xplane(space->add_planes());
- xplane.SetName("Host Threads");
- absl::flat_hash_map<string, XEventMetadata*> xevent_metadata_by_name;
- absl::flat_hash_map<string, XStatMetadata*> xstat_metadata_by_name;
- for (const auto& thread : events_) {
- XLineBuilder xline = xplane.AddLine();
- xline.SetId(thread.thread.tid);
- xline.SetName(thread.thread.name);
- xline.SetTimestampNs(start_timestamp_ns_);
- xline.ReserveEvents(thread.events.size());
- for (const auto& event : thread.events) {
- if (event.start_time && event.end_time) {
- Annotation annotation = ParseAnnotation(event.name);
- XEventMetadata*& xevent_metadata =
- xevent_metadata_by_name[annotation.name];
- if (xevent_metadata == nullptr) {
- xevent_metadata =
- xplane.GetOrCreateEventMetadata(xevent_metadata_by_name.size());
- xevent_metadata->set_name(string(annotation.name));
- }
- XEventBuilder xevent = xline.AddEvent(*xevent_metadata);
- xevent.SetTimestampNs(event.start_time);
- xevent.SetEndTimestampNs(event.end_time);
- xevent.ReserveStats(annotation.metadata.size());
- for (const auto& metadata : annotation.metadata) {
- XStatMetadata*& xstat_metadata = xstat_metadata_by_name[metadata.key];
- if (xstat_metadata == nullptr) {
- xstat_metadata =
- xplane.GetOrCreateStatMetadata(xstat_metadata_by_name.size());
- xstat_metadata->set_name(string(metadata.key));
- }
- xevent.ParseAndAddStatValue(*xstat_metadata, metadata.value);
- }
- }
- }
- }
+ MakeCompleteEvents(&events_);
+ ConvertCompleteEventsToXPlane(start_timestamp_ns_, events_,
+ space->add_planes());
events_.clear();
return Status::OK();
}
@@ -242,6 +163,5 @@
return 0;
}();
-} // namespace cpu
} // namespace profiler
} // namespace tensorflow
diff --git a/tensorflow/core/profiler/internal/cpu/host_tracer_test.cc b/tensorflow/core/profiler/internal/cpu/host_tracer_test.cc
index c88d7fa..7623a4e 100644
--- a/tensorflow/core/profiler/internal/cpu/host_tracer_test.cc
+++ b/tensorflow/core/profiler/internal/cpu/host_tracer_test.cc
@@ -28,7 +28,6 @@
namespace tensorflow {
namespace profiler {
-namespace cpu {
std::unique_ptr<ProfilerInterface> CreateHostTracer(
const ProfilerOptions& options);
@@ -169,6 +168,5 @@
}
} // namespace
-} // namespace cpu
} // namespace profiler
} // namespace tensorflow
diff --git a/tensorflow/core/profiler/internal/cpu/host_tracer_utils.cc b/tensorflow/core/profiler/internal/cpu/host_tracer_utils.cc
new file mode 100644
index 0000000..099cd1a
--- /dev/null
+++ b/tensorflow/core/profiler/internal/cpu/host_tracer_utils.cc
@@ -0,0 +1,109 @@
+/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+#include "tensorflow/core/profiler/internal/cpu/host_tracer_utils.h"
+
+#include <utility>
+#include <vector>
+
+#include "absl/container/flat_hash_map.h"
+#include "tensorflow/core/profiler/internal/parse_annotation.h"
+#include "tensorflow/core/profiler/internal/traceme_recorder.h"
+#include "tensorflow/core/profiler/protobuf/xplane.pb.h"
+#include "tensorflow/core/profiler/utils/xplane_builder.h"
+
+namespace tensorflow {
+namespace profiler {
+
+void MakeCompleteEvents(TraceMeRecorder::Events* events) {
+ // Track events created by ActivityStart and copy their data to events created
+ // by ActivityEnd. TraceMe records events in its destructor, so this results
+ // in complete events sorted by their end_time in the thread they ended.
+ // Within the same thread, the record created by ActivityStart must appear
+ // before the record created by ActivityEnd. Cross-thread events must be
+ // processed in a separate pass. A single map can be used because the
+ // activity_id is globally unique.
+ absl::flat_hash_map<uint64, TraceMeRecorder::Event*> start_events;
+ std::vector<TraceMeRecorder::Event*> end_events;
+ for (auto& thread : *events) {
+ for (auto& event : thread.events) {
+ if (event.start_time && !event.end_time) { // ActivityStart
+ start_events.emplace(event.activity_id, &event);
+ } else if (!event.start_time && event.end_time) { // ActivityEnd
+ auto iter = start_events.find(event.activity_id);
+ if (iter != start_events.end()) { // same thread
+ auto* start_event = iter->second;
+ event.name = std::move(start_event->name);
+ event.start_time = start_event->start_time;
+ start_events.erase(iter);
+ } else { // cross-thread
+ end_events.push_back(&event);
+ }
+ }
+ }
+ }
+ for (auto* event : end_events) { // cross-thread
+ auto iter = start_events.find(event->activity_id);
+ if (iter != start_events.end()) {
+ auto* start_event = iter->second;
+ event->name = std::move(start_event->name);
+ event->start_time = start_event->start_time;
+ start_events.erase(iter);
+ }
+ }
+}
+
+void ConvertCompleteEventsToXPlane(uint64 start_timestamp_ns,
+ const TraceMeRecorder::Events& events,
+ XPlane* raw_plane) {
+ XPlaneBuilder xplane(raw_plane);
+ xplane.SetName("Host Threads");
+ absl::flat_hash_map<string, XEventMetadata*> xevent_metadata_by_name;
+ absl::flat_hash_map<string, XStatMetadata*> xstat_metadata_by_name;
+ for (const auto& thread : events) {
+ XLineBuilder xline = xplane.AddLine();
+ xline.SetId(thread.thread.tid);
+ xline.SetName(thread.thread.name);
+ xline.SetTimestampNs(start_timestamp_ns);
+ xline.ReserveEvents(thread.events.size());
+ for (const auto& event : thread.events) {
+ if (event.start_time && event.end_time) {
+ Annotation annotation = ParseAnnotation(event.name);
+ XEventMetadata*& xevent_metadata =
+ xevent_metadata_by_name[annotation.name];
+ if (xevent_metadata == nullptr) {
+ xevent_metadata =
+ xplane.GetOrCreateEventMetadata(xevent_metadata_by_name.size());
+ xevent_metadata->set_name(string(annotation.name));
+ }
+ XEventBuilder xevent = xline.AddEvent(*xevent_metadata);
+ xevent.SetTimestampNs(event.start_time);
+ xevent.SetEndTimestampNs(event.end_time);
+ xevent.ReserveStats(annotation.metadata.size());
+ for (const auto& metadata : annotation.metadata) {
+ XStatMetadata*& xstat_metadata = xstat_metadata_by_name[metadata.key];
+ if (xstat_metadata == nullptr) {
+ xstat_metadata =
+ xplane.GetOrCreateStatMetadata(xstat_metadata_by_name.size());
+ xstat_metadata->set_name(string(metadata.key));
+ }
+ xevent.ParseAndAddStatValue(*xstat_metadata, metadata.value);
+ }
+ }
+ }
+ }
+}
+
+} // namespace profiler
+} // namespace tensorflow
diff --git a/tensorflow/core/profiler/internal/cpu/host_tracer_utils.h b/tensorflow/core/profiler/internal/cpu/host_tracer_utils.h
new file mode 100644
index 0000000..e422760
--- /dev/null
+++ b/tensorflow/core/profiler/internal/cpu/host_tracer_utils.h
@@ -0,0 +1,37 @@
+/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+#ifndef TENSORFLOW_CORE_PROFILER_INTERNAL_CPU_HOST_TRACER_UTILS_H_
+#define TENSORFLOW_CORE_PROFILER_INTERNAL_CPU_HOST_TRACER_UTILS_H_
+
+#include "tensorflow/core/platform/types.h"
+#include "tensorflow/core/profiler/internal/traceme_recorder.h"
+#include "tensorflow/core/profiler/protobuf/xplane.pb.h"
+
+namespace tensorflow {
+namespace profiler {
+
+// Combine events created by TraceMe::ActivityStart and TraceMe::ActivityEnd,
+// which can be paired up by their activity_id.
+void MakeCompleteEvents(TraceMeRecorder::Events* events);
+
+// Convert complete events to XPlane format.
+void ConvertCompleteEventsToXPlane(uint64 start_timestamp_ns,
+ const TraceMeRecorder::Events& events,
+ XPlane* raw_plane);
+
+} // namespace profiler
+} // namespace tensorflow
+
+#endif // TENSORFLOW_CORE_PROFILER_INTERNAL_CPU_HOST_TRACER_UTILS_H_