Merge "Project import generated by Copybara."
diff --git a/BUILD b/BUILD
index 4448932..08bc590 100644
--- a/BUILD
+++ b/BUILD
@@ -953,6 +953,7 @@
perfetto_filegroup(
name = "src_trace_processor_db_db",
srcs = [
+ "src/trace_processor/db/base_id.h",
"src/trace_processor/db/column.cc",
"src/trace_processor/db/column.h",
"src/trace_processor/db/compare.h",
diff --git a/BUILD.gn b/BUILD.gn
index 201e340..d18c71c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -92,7 +92,9 @@
import("gn/perfetto_unittests.gni")
test("perfetto_unittests") {
if (is_fuchsia) {
- use_cfv2 = false
+ additional_manifest_fragments = [
+ "//build/config/fuchsia/test/network.shard.test-cml",
+ ]
}
deps = perfetto_unittests_targets
}
diff --git a/CHANGELOG b/CHANGELOG
index ab2f7bf..db4ed93 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -13,6 +13,8 @@
an ISO8601 string.
* Changed 'trace_to_text' to be named 'traceconv'. The source
location also moved from 'tools/trace_to_text' to 'src/traceconv'.
+ * Changed compiler flags, added -mavx2. The previous patch in v22.0 was
+ supposed to add AVX2 support but added only AVX.
UI:
*
SDK:
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index 42e35b8..c7f6469 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -147,9 +147,8 @@
# For now the IPC layer is conservatively not enabled on Chromium+Windows
# builds.
enable_perfetto_ipc =
- !is_fuchsia && !is_nacl &&
- (perfetto_build_standalone || perfetto_build_with_android ||
- (build_with_chromium && !is_win))
+ !is_nacl && (perfetto_build_standalone || perfetto_build_with_android ||
+ (build_with_chromium && !is_win) || is_fuchsia)
# Makes the heap profiling daemon target reachable. It works only on Android,
# but is built on Linux as well for test/compiler coverage.
diff --git a/gn/standalone/BUILD.gn b/gn/standalone/BUILD.gn
index 4b401d4..33fd7aa 100644
--- a/gn/standalone/BUILD.gn
+++ b/gn/standalone/BUILD.gn
@@ -247,7 +247,7 @@
# When updating these flags, the CheckCpuOptimizations() in utils.cc must
# be updated accordingly.
cflags += [
- "-mavx",
+ "-mavx2",
"-mpopcnt",
"-msse4.2",
]
diff --git a/include/perfetto/ext/base/unix_socket.h b/include/perfetto/ext/base/unix_socket.h
index c849da6..dd90423 100644
--- a/include/perfetto/ext/base/unix_socket.h
+++ b/include/perfetto/ext/base/unix_socket.h
@@ -362,7 +362,8 @@
// User ID of the peer, as returned by the kernel. If the client disconnects
// and the socket goes into the kDisconnected state, it retains the uid of
// the last peer.
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
uid_t peer_uid_posix(bool skip_check_for_testing = false) const {
PERFETTO_DCHECK((!is_listening() && peer_uid_ != kInvalidUid) ||
skip_check_for_testing);
@@ -416,7 +417,8 @@
State state_ = State::kDisconnected;
SockPeerCredMode peer_cred_mode_ = SockPeerCredMode::kDefault;
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
uid_t peer_uid_ = kInvalidUid;
#endif
#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
diff --git a/include/perfetto/ext/ipc/basic_types.h b/include/perfetto/ext/ipc/basic_types.h
index 3931f05..191a5a8 100644
--- a/include/perfetto/ext/ipc/basic_types.h
+++ b/include/perfetto/ext/ipc/basic_types.h
@@ -33,10 +33,13 @@
using ClientID = uint64_t;
using RequestID = uint64_t;
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
// AF_UNIX on Windows is supported only on Windows 10 from build 17063.
// Also it doesn't bring major advantages compared to a TCP socket.
// See go/perfetto-win .
+// AF_UNIX sockets are not supported on Fuchsia. The typical IPC flow involves
+// adoption of connected kernel sockets.
constexpr bool kUseTCPSocket = true;
#else
// On Android, Linux, Mac use a AF_UNIX socket.
diff --git a/infra/perfetto-get.appspot.com/main.py b/infra/perfetto-get.appspot.com/main.py
index e4b14a8..015e922 100644
--- a/infra/perfetto-get.appspot.com/main.py
+++ b/infra/perfetto-get.appspot.com/main.py
@@ -22,6 +22,7 @@
'+/master/%s?format=TEXT'
RESOURCES = {
+ 'tracebox': 'tools/tracebox',
'traceconv': 'tools/traceconv',
'trace_processor': 'tools/trace_processor',
}
diff --git a/python/perfetto/trace_processor/metrics.descriptor b/python/perfetto/trace_processor/metrics.descriptor
index 81b6b62..850b6df 100644
--- a/python/perfetto/trace_processor/metrics.descriptor
+++ b/python/perfetto/trace_processor/metrics.descriptor
Binary files differ
diff --git a/src/base/utils.cc b/src/base/utils.cc
index 0b08ece..0ec6cdf 100644
--- a/src/base/utils.cc
+++ b/src/base/utils.cc
@@ -99,12 +99,21 @@
(ecx & (1u << 28)) && // AVX supported in hardware
((GetXCR0EAX() & xcr0_avx_mask) == xcr0_avx_mask);
- if (!have_sse4_2 || !have_popcnt || !have_avx) {
+ // Get level 7 features (eax = 7 and ecx= 0), to check for AVX2 support.
+ // (See Intel 64 and IA-32 Architectures Software Developer's Manual
+ // Volume 2A: Instruction Set Reference, A-M CPUID).
+ PERFETTO_GETCPUID(eax, ebx, ecx, edx, 7, 0);
+ const bool have_avx2 = have_avx && ((ebx >> 5) & 0x1);
+
+ if (!have_sse4_2 || !have_popcnt || !have_avx2) {
fprintf(
stderr,
- "This executable requires a cpu that supports SSE4.2 and AVX2.\n"
- "Rebuild with enable_perfetto_x64_cpu_opt=false (ebx=%x, ecx=%x).\n",
- ebx, ecx);
+ "This executable requires a X86_64 cpu that supports SSE4.2 and AVX2.\n"
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ "On MacOS, this might be caused by running x86_64 binaries on arm64.\n"
+ "See https://github.com/google/perfetto/issues/294 for more.\n"
+#endif
+ "Rebuild with enable_perfetto_x64_cpu_opt=false.\n");
_exit(126);
}
}
diff --git a/src/ipc/BUILD.gn b/src/ipc/BUILD.gn
index 39843f1..d093978 100644
--- a/src/ipc/BUILD.gn
+++ b/src/ipc/BUILD.gn
@@ -117,6 +117,13 @@
"host_impl_unittest.cc",
"test/ipc_integrationtest.cc",
]
+
+ if (is_fuchsia) {
+ deps += [
+ "//third_party/fuchsia-sdk/sdk/pkg/zx",
+ "//third_party/fuchsia-sdk/sdk/pkg/fdio",
+ ]
+ }
}
perfetto_proto_library("test_messages_@TYPE@") {
diff --git a/src/ipc/client_impl_unittest.cc b/src/ipc/client_impl_unittest.cc
index 0a31a8c..0f46459 100644
--- a/src/ipc/client_impl_unittest.cc
+++ b/src/ipc/client_impl_unittest.cc
@@ -340,8 +340,9 @@
ASSERT_EQ(kNumReplies, replies_seen);
}
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-// File descriptor sending over IPC is not supported on Windows.
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+// File descriptor sending over IPC is not supported on Windows or Fuchsia.
TEST_F(ClientImplTest, ReceiveFileDescriptor) {
auto* host_svc = host_->AddFakeService("FakeSvc");
auto* host_method = host_svc->AddFakeMethod("FakeMethod1");
diff --git a/src/ipc/host_impl.cc b/src/ipc/host_impl.cc
index c182cd1..7304702 100644
--- a/src/ipc/host_impl.cc
+++ b/src/ipc/host_impl.cc
@@ -43,7 +43,8 @@
base::CrashKey g_crash_key_uid("ipc_uid");
uid_t GetPosixPeerUid(base::UnixSocket* sock) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
base::ignore_result(sock);
// Unsupported. Must be != kInvalidUid or the PacketValidator will fail.
return 0;
diff --git a/src/ipc/host_impl_unittest.cc b/src/ipc/host_impl_unittest.cc
index e1bbee7..4956a4f 100644
--- a/src/ipc/host_impl_unittest.cc
+++ b/src/ipc/host_impl_unittest.cc
@@ -321,7 +321,8 @@
task_runner_->RunUntilCheckpoint("on_reply_received");
}
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
// File descriptor sending over IPC is not supported on Windows.
TEST_F(HostImplTest, SendFileDescriptor) {
FakeService* fake_service = new FakeService("FakeService");
diff --git a/src/ipc/test/test_socket.h b/src/ipc/test/test_socket.h
index eaafd73..29e9058 100644
--- a/src/ipc/test/test_socket.h
+++ b/src/ipc/test/test_socket.h
@@ -41,7 +41,8 @@
inline void Destroy();
};
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
const char* TestSocket::name() {
uint64_t hash = 5381;
diff --git a/src/trace_processor/containers/nullable_vector.h b/src/trace_processor/containers/nullable_vector.h
index 537e822..44bf4f6 100644
--- a/src/trace_processor/containers/nullable_vector.h
+++ b/src/trace_processor/containers/nullable_vector.h
@@ -118,14 +118,6 @@
valid_.Insert(size_++);
}
- // Adds a null value to the NullableVector.
- void AppendNull() {
- if (mode_ == Mode::kDense) {
- data_.emplace_back();
- }
- size_++;
- }
-
// Adds the given optional value to the NullableVector.
void Append(base::Optional<T> val) {
if (val) {
@@ -167,6 +159,13 @@
private:
explicit NullableVector(Mode mode) : mode_(mode) {}
+ void AppendNull() {
+ if (mode_ == Mode::kDense) {
+ data_.emplace_back();
+ }
+ size_++;
+ }
+
Mode mode_ = Mode::kSparse;
std::deque<T> data_;
diff --git a/src/trace_processor/containers/nullable_vector_unittest.cc b/src/trace_processor/containers/nullable_vector_unittest.cc
index 37a8b78..1db8d3f 100644
--- a/src/trace_processor/containers/nullable_vector_unittest.cc
+++ b/src/trace_processor/containers/nullable_vector_unittest.cc
@@ -26,7 +26,7 @@
NullableVector<int64_t> sv;
sv.Append(10);
sv.Append(20);
- sv.AppendNull();
+ sv.Append(base::nullopt);
sv.Append(40);
ASSERT_FALSE(sv.IsDense());
@@ -41,8 +41,8 @@
NullableVector<int64_t> sv;
sv.Append(10);
sv.Append(20);
- sv.AppendNull();
- sv.AppendNull();
+ sv.Append(base::nullopt);
+ sv.Append(base::nullopt);
sv.Append(40);
sv.Set(0, 15);
@@ -74,10 +74,10 @@
auto sv = NullableVector<int64_t>::Dense();
sv.Append(0);
- sv.AppendNull();
+ sv.Append(base::nullopt);
sv.Append(2);
sv.Append(3);
- sv.AppendNull();
+ sv.Append(base::nullopt);
ASSERT_TRUE(sv.IsDense());
ASSERT_EQ(sv.Get(0), 0);
diff --git a/src/trace_processor/db/BUILD.gn b/src/trace_processor/db/BUILD.gn
index ebbd478..fa695e5 100644
--- a/src/trace_processor/db/BUILD.gn
+++ b/src/trace_processor/db/BUILD.gn
@@ -16,6 +16,7 @@
source_set("db") {
sources = [
+ "base_id.h",
"column.cc",
"column.h",
"compare.h",
diff --git a/src/trace_processor/db/base_id.h b/src/trace_processor/db/base_id.h
new file mode 100644
index 0000000..75d479e
--- /dev/null
+++ b/src/trace_processor/db/base_id.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 <stdint.h>
+#include <type_traits>
+
+#ifndef SRC_TRACE_PROCESSOR_DB_BASE_ID_H_
+#define SRC_TRACE_PROCESSOR_DB_BASE_ID_H_
+
+namespace perfetto {
+namespace trace_processor {
+
+// Id type which can be used as a base for strongly typed ids.
+// TypedColumn has support for storing descendents of BaseId seamlessly
+// in a Column.
+struct BaseId {
+ BaseId() = default;
+ explicit constexpr BaseId(uint32_t v) : value(v) {}
+
+ bool operator==(const BaseId& o) const { return o.value == value; }
+ bool operator!=(const BaseId& o) const { return !(*this == o); }
+ bool operator<(const BaseId& o) const { return value < o.value; }
+
+ uint32_t value;
+};
+static_assert(std::is_trivially_destructible<BaseId>::value,
+ "Inheritance used without trivial destruction");
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_DB_BASE_ID_H_
diff --git a/src/trace_processor/db/column.h b/src/trace_processor/db/column.h
index c3071b8..88928f4 100644
--- a/src/trace_processor/db/column.h
+++ b/src/trace_processor/db/column.h
@@ -30,22 +30,6 @@
namespace perfetto {
namespace trace_processor {
-// Id type which can be used as a base for strongly typed ids.
-// TypedColumn has support for storing descendents of BaseId seamlessly
-// in a Column.
-struct BaseId {
- BaseId() = default;
- explicit constexpr BaseId(uint32_t v) : value(v) {}
-
- bool operator==(const BaseId& o) const { return o.value == value; }
- bool operator!=(const BaseId& o) const { return !(*this == o); }
- bool operator<(const BaseId& o) const { return value < o.value; }
-
- uint32_t value;
-};
-static_assert(std::is_trivially_destructible<BaseId>::value,
- "Inheritance used without trivial destruction");
-
// Represents the possible filter operations on a column.
enum class FilterOp {
kEq,
@@ -300,41 +284,6 @@
PERFETTO_FATAL("For GCC");
}
- // Sets the value of the column at the given |row|.
- void Set(uint32_t row, SqlValue value) {
- PERFETTO_CHECK(value.type == type());
- switch (type_) {
- case ColumnType::kInt32: {
- mutable_nullable_vector<int32_t>()->Set(
- row, static_cast<int32_t>(value.long_value));
- break;
- }
- case ColumnType::kUint32: {
- mutable_nullable_vector<uint32_t>()->Set(
- row, static_cast<uint32_t>(value.long_value));
- break;
- }
- case ColumnType::kInt64: {
- mutable_nullable_vector<int64_t>()->Set(
- row, static_cast<int64_t>(value.long_value));
- break;
- }
- case ColumnType::kDouble: {
- mutable_nullable_vector<double>()->Set(row, value.double_value);
- break;
- }
- case ColumnType::kString: {
- PERFETTO_FATAL(
- "Setting a generic value on a string column is not implemented");
- }
- case ColumnType::kId: {
- PERFETTO_FATAL("Cannot set value on a id column");
- }
- case ColumnType::kDummy:
- PERFETTO_FATAL("Set not allowed on dummy column");
- }
- }
-
// Sorts |idx| in ascending or descending order (determined by |desc|) based
// on the contents of this column.
void StableSort(bool desc, std::vector<uint32_t>* idx) const;
diff --git a/src/trace_processor/db/typed_column.h b/src/trace_processor/db/typed_column.h
index 605a02a..7522df0 100644
--- a/src/trace_processor/db/typed_column.h
+++ b/src/trace_processor/db/typed_column.h
@@ -120,22 +120,14 @@
return Column::ToSqlValueType<serialized_type>();
}
- // Reinterpret cast a Column to TypedColumn or crash if that is likely to be
- // unsafe.
- static const TypedColumn<T>* FromColumn(const Column* column) {
- // While casting from a base to derived without constructing as a derived is
- // technically UB, in practice, this is at the heart of protozero (see
- // Message::BeginNestedMessage) so we use it here.
- static_assert(sizeof(TypedColumn<T>) == sizeof(Column),
- "TypedColumn cannot introduce extra state.");
+ // Cast a Column to TypedColumn or crash if that is unsafe.
+ static TypedColumn<T>* FromColumn(Column* column) {
+ return FromColumnInternal<TypedColumn<T>>(column);
+ }
- if (column->IsColumnType<serialized_type>() &&
- (column->IsNullable() == TH::is_optional) && !column->IsId()) {
- return static_cast<const TypedColumn<T>*>(column);
- } else {
- PERFETTO_FATAL("Unsafe to convert Column TypedColumn (%s)",
- column->name());
- }
+ // Cast a Column to TypedColumn or crash if that is unsafe.
+ static const TypedColumn<T>* FromColumn(const Column* column) {
+ return FromColumnInternal<const TypedColumn<T>>(column);
}
// Public for use by macro tables.
@@ -158,6 +150,23 @@
private:
friend class Table;
+ template <typename Output, typename Input>
+ static Output* FromColumnInternal(Input* column) {
+ // While casting from a base to derived without constructing as a derived is
+ // technically UB, in practice, this is at the heart of protozero (see
+ // Message::BeginNestedMessage) so we use it here.
+ static_assert(sizeof(TypedColumn<T>) == sizeof(Column),
+ "TypedColumn cannot introduce extra state.");
+
+ if (column->template IsColumnType<serialized_type>() &&
+ (column->IsNullable() == TH::is_optional) && !column->IsId()) {
+ return static_cast<Output*>(column);
+ } else {
+ PERFETTO_FATAL("Unsafe to convert Column TypedColumn (%s)",
+ column->name());
+ }
+ }
+
static SqlValue ToValue(double value) { return SqlValue::Double(value); }
static SqlValue ToValue(uint32_t value) { return SqlValue::Long(value); }
static SqlValue ToValue(int64_t value) { return SqlValue::Long(value); }
diff --git a/src/trace_processor/db/typed_column_internal.h b/src/trace_processor/db/typed_column_internal.h
index 5e2f618..9001ef6 100644
--- a/src/trace_processor/db/typed_column_internal.h
+++ b/src/trace_processor/db/typed_column_internal.h
@@ -17,7 +17,9 @@
#ifndef SRC_TRACE_PROCESSOR_DB_TYPED_COLUMN_INTERNAL_H_
#define SRC_TRACE_PROCESSOR_DB_TYPED_COLUMN_INTERNAL_H_
-#include "src/trace_processor/db/column.h"
+#include "src/trace_processor/containers/nullable_vector.h"
+#include "src/trace_processor/containers/string_pool.h"
+#include "src/trace_processor/db/base_id.h"
namespace perfetto {
namespace trace_processor {
diff --git a/src/trace_processor/importers/common/args_tracker.cc b/src/trace_processor/importers/common/args_tracker.cc
index 1b6e0e9..b0036cf 100644
--- a/src/trace_processor/importers/common/args_tracker.cc
+++ b/src/trace_processor/importers/common/args_tracker.cc
@@ -67,20 +67,23 @@
std::stable_sort(args_.begin(), args_.end(), comparator);
for (uint32_t i = 0; i < args_.size();) {
- const auto& arg = args_[i];
- Column* column = arg.column;
- auto row = arg.row;
+ const GlobalArgsTracker::Arg& arg = args_[i];
+ auto* col = arg.column;
+ uint32_t row = arg.row;
uint32_t next_rid_idx = i + 1;
- while (next_rid_idx < args_.size() &&
- column == args_[next_rid_idx].column &&
+ while (next_rid_idx < args_.size() && col == args_[next_rid_idx].column &&
row == args_[next_rid_idx].row) {
next_rid_idx++;
}
ArgSetId set_id =
context_->global_args_tracker->AddArgSet(&args_[0], i, next_rid_idx);
- column->Set(row, SqlValue::Long(set_id));
+ if (col->IsNullable()) {
+ TypedColumn<base::Optional<uint32_t>>::FromColumn(col)->Set(row, set_id);
+ } else {
+ TypedColumn<uint32_t>::FromColumn(col)->Set(row, set_id);
+ }
i = next_rid_idx;
}
diff --git a/src/trace_processor/importers/common/clock_tracker.cc b/src/trace_processor/importers/common/clock_tracker.cc
index 7642777..2bb0ff2 100644
--- a/src/trace_processor/importers/common/clock_tracker.cc
+++ b/src/trace_processor/importers/common/clock_tracker.cc
@@ -200,8 +200,7 @@
// Expore all the adjacent clocks.
// The lower_bound() below returns an iterator to the first edge that starts
// on |cur_clock_id|. The edges are sorted by (src, target, hash).
- for (auto it = std::lower_bound(graph_.begin(), graph_.end(),
- ClockGraphEdge(cur_clock_id, 0, 0));
+ for (auto it = graph_.lower_bound(ClockGraphEdge(cur_clock_id, 0, 0));
it != graph_.end() && std::get<0>(*it) == cur_clock_id; ++it) {
ClockId next_clock_id = std::get<1>(*it);
SnapshotHash hash = std::get<2>(*it);
diff --git a/src/trace_processor/metrics/sql/android/startup/launches_minsdk33.sql b/src/trace_processor/metrics/sql/android/startup/launches_minsdk33.sql
index f3773bb..25ea8cd 100644
--- a/src/trace_processor/metrics/sql/android/startup/launches_minsdk33.sql
+++ b/src/trace_processor/metrics/sql/android/startup/launches_minsdk33.sql
@@ -30,12 +30,14 @@
CREATE VIEW launch_complete_events AS
SELECT
STR_SPLIT(completed, ':completed:', 0) id,
- STR_SPLIT(completed, ':completed:', 1) package_name
+ STR_SPLIT(completed, ':completed:', 1) package_name,
+ MIN(ts)
FROM (
- SELECT SUBSTR(name, 19) completed
+ SELECT ts, SUBSTR(name, 19) completed
FROM slice
WHERE dur = 0 AND name GLOB 'launchingActivity#*:completed:*'
-);
+)
+GROUP BY 1, 2;
INSERT INTO launches(id, ts, ts_end, dur, package)
SELECT
diff --git a/src/tracing/ipc/posix_shared_memory.cc b/src/tracing/ipc/posix_shared_memory.cc
index 3a59948..a21a290 100644
--- a/src/tracing/ipc/posix_shared_memory.cc
+++ b/src/tracing/ipc/posix_shared_memory.cc
@@ -18,7 +18,8 @@
#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
- PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
#include <fcntl.h>
#include <stdint.h>
diff --git a/src/tracing/ipc/posix_shared_memory.h b/src/tracing/ipc/posix_shared_memory.h
index 18c7dd7..0ba1a31 100644
--- a/src/tracing/ipc/posix_shared_memory.h
+++ b/src/tracing/ipc/posix_shared_memory.h
@@ -21,7 +21,8 @@
#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
- PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
#include <stddef.h>
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index 4788112..2293a73 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -608,6 +608,11 @@
return ReadSlicesFromTrace(tracing_session->ReadTraceBlocking());
}
+ std::vector<std::string> StopSessionAndReadSlicesFromTrace(
+ TestTracingSessionHandle* tracing_session) {
+ return ReadSlicesFromTrace(StopSessionAndReturnBytes(tracing_session));
+ }
+
std::vector<std::string> ReadSlicesFromTrace(
const std::vector<char>& raw_trace) {
EXPECT_GE(raw_trace.size(), 0u);
@@ -956,10 +961,9 @@
// the producer name filter was cleared.
TRACE_EVENT_BEGIN("foo", "EventIncluded");
TRACE_EVENT_END("foo");
- tracing_session->get()->StopBlocking();
// Verify that only the second event is in the trace data.
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
std::string trace(raw_trace.data(), raw_trace.size());
EXPECT_THAT(trace, Not(HasSubstr("EventFilteredOut")));
EXPECT_THAT(trace, HasSubstr("EventIncluded"));
@@ -1251,13 +1255,7 @@
perfetto::TraceTimestamp{kClockIdIncremental, kInstantEvent2Time},
empty_lambda);
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-
- perfetto::protos::gen::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
uint64_t absolute_timestamp = 0;
uint64_t prv_timestamp = 0;
int event_count = 0;
@@ -1339,8 +1337,7 @@
TRACE_EVENT_BEGIN("bar", "Enabled");
TRACE_EVENT_END("bar");
- tracing_session->get()->StopBlocking();
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
std::string trace(raw_trace.data(), raw_trace.size());
// TODO(skyostil): Come up with a nicer way to verify trace contents.
EXPECT_THAT(trace, HasSubstr("Enabled"));
@@ -1477,8 +1474,7 @@
TRACE_EVENT_BEGIN("bar", "DisabledEventFromMain");
TRACE_EVENT_END("bar");
- tracing_session->get()->StopBlocking();
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
std::string trace(raw_trace.data(), raw_trace.size());
EXPECT_THAT(trace, HasSubstr("FooEventFromMain"));
EXPECT_THAT(trace, Not(HasSubstr("DisabledEventFromMain")));
@@ -1547,9 +1543,7 @@
});
thread.join();
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
std::string trace(raw_trace.data(), raw_trace.size());
EXPECT_THAT(trace, HasSubstr("EventInDynamicCategory"));
EXPECT_THAT(trace, Not(HasSubstr("EventInDisabledDynamicCategory")));
@@ -1559,8 +1553,7 @@
EXPECT_THAT(trace,
Not(HasSubstr("EventInSecondStaticallyNamedDynamicCategory")));
- tracing_session2->get()->StopBlocking();
- raw_trace = tracing_session2->get()->ReadTraceBlocking();
+ raw_trace = StopSessionAndReturnBytes(tracing_session2);
trace = std::string(raw_trace.data(), raw_trace.size());
EXPECT_THAT(trace, Not(HasSubstr("EventInDynamicCategory")));
EXPECT_THAT(trace, Not(HasSubstr("EventInDisabledDynamicCategory")));
@@ -1739,13 +1732,8 @@
static_cast<int32_t>(perfetto::base::GetThreadId()));
desc.mutable_chrome_process()->set_process_priority(123);
perfetto::TrackEvent::SetTrackDescriptor(track, std::move(desc));
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- perfetto::protos::gen::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
uint32_t main_thread_sequence = GetMainThreadPacketSequenceId(trace);
bool found_desc = false;
@@ -1799,12 +1787,7 @@
});
thread.join();
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- perfetto::protos::gen::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
// Check that the track uuids match on the begin and end events.
const auto track = perfetto::Track(async_id);
@@ -1875,12 +1858,7 @@
perfetto::TraceTimestamp{kMyClockId, kTimestamp});
TRACE_EVENT_INSTANT("foo", "EventWithNormalTime");
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- perfetto::protos::gen::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
// Check that both the clock id and the timestamp got written together with
// the packet. Note that we don't check the actual clock sync behavior here
@@ -1907,12 +1885,7 @@
TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0("cat", "Name", 1,
MyThreadId(456), MyTimestamp{0});
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- perfetto::protos::gen::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
// Check that we wrote a track descriptor for the custom thread track, and
// that the event was associated with that track.
@@ -1952,12 +1925,7 @@
INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(
TRACE_EVENT_PHASE_INSTANT, "cat", "Name", 0, MyThreadId{789},
MyTimestamp{0}, TRACE_EVENT_FLAG_HAS_PROCESS_ID);
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- perfetto::protos::gen::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
// Check that the event has a pid_override matching MyThread above.
bool found_event = false;
@@ -1981,12 +1949,7 @@
// Emit an event on a custom track.
TRACE_EVENT_INSTANT("bar", "Event", perfetto::Track(8086));
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- perfetto::protos::gen::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
// Check that the descriptor was written before the event.
std::set<uint64_t> seen_descriptors;
@@ -2020,12 +1983,7 @@
TRACE_EVENT_INSTANT("bar", "InstantEvent", track, kInstantEventTime,
empty_lambda);
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- perfetto::protos::gen::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
int event_count = 0;
for (const auto& packet : trace.packet()) {
@@ -2065,12 +2023,7 @@
TRACE_EVENT_BEGIN("bar", "Event", track, kBeginEventTime);
TRACE_EVENT_END("bar", track, kEndEventTime);
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- perfetto::protos::gen::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
int event_count = 0;
for (const auto& packet : trace.packet()) {
@@ -2106,12 +2059,7 @@
std::thread thread([&] { TRACE_EVENT_END("bar", track); });
thread.join();
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- perfetto::protos::gen::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
// Check that a descriptor for the track was emitted.
bool found_descriptor = false;
@@ -2145,15 +2093,10 @@
});
TRACE_EVENT_END("foo");
- tracing_session->get()->StopBlocking();
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- std::string trace(raw_trace.data(), raw_trace.size());
-
- perfetto::protos::gen::Trace parsed_trace;
- ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
bool found_args = false;
- for (const auto& packet : parsed_trace.packet()) {
+ for (const auto& packet : trace.packet()) {
if (!packet.has_track_event())
continue;
const auto& track_event = packet.track_event();
@@ -2185,15 +2128,10 @@
perfetto::protos::pbzero::TrackEvent::kFlowIds, flow_ids);
TRACE_EVENT_END("foo");
- tracing_session->get()->StopBlocking();
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- std::string trace(raw_trace.data(), raw_trace.size());
-
- perfetto::protos::gen::Trace parsed_trace;
- ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
bool found_args = false;
- for (const auto& packet : parsed_trace.packet()) {
+ for (const auto& packet : trace.packet()) {
if (!packet.has_track_event())
continue;
const auto& track_event = packet.track_event();
@@ -2282,8 +2220,7 @@
LogMessage());
TRACE_EVENT_END("foo");
- tracing_session->get()->StopBlocking();
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
}
TEST_P(PerfettoApiTest, TrackEventThreadTime) {
@@ -2305,19 +2242,13 @@
TRACE_EVENT_END("foo");
TRACE_EVENT_END("foo");
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-
- perfetto::protos::gen::Trace parsed_trace;
- EXPECT_TRUE(
- parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
bool found_counter_track_descriptor = false;
uint64_t thread_time_counter_uuid = 0;
uint64_t default_counter_uuid = 0;
std::unordered_set<std::string> event_names;
- for (const auto& packet : parsed_trace.packet()) {
+ for (const auto& packet : trace.packet()) {
if (packet.has_track_descriptor() &&
packet.track_descriptor().has_counter()) {
EXPECT_FALSE(found_counter_track_descriptor);
@@ -2376,9 +2307,7 @@
LogMessage(), "arg", "value");
TRACE_EVENT_END("foo");
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
std::string trace(raw_trace.data(), raw_trace.size());
// Find typed argument.
@@ -2386,7 +2315,7 @@
// Find untyped argument.
EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
- ElementsAre("B:foo.E(arg=(string)value)"));
+ ElementsAre("B:foo.E(arg=(string)value)", "E"));
}
TEST_P(PerfettoApiTest, TrackEventArgs_UntypedAndTyped) {
@@ -2399,16 +2328,14 @@
LogMessage());
TRACE_EVENT_END("foo");
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
// Find typed argument.
CheckLogMessagePresent(raw_trace);
// Find untyped argument.
EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
- ElementsAre("B:foo.E(arg=(string)value)"));
+ ElementsAre("B:foo.E(arg=(string)value)", "E"));
}
TEST_P(PerfettoApiTest, TrackEventArgs_UntypedAndRefLambda) {
@@ -2419,16 +2346,14 @@
TRACE_EVENT_BEGIN("foo", "E", "arg", "value", GetWriteLogMessageRefLambda());
TRACE_EVENT_END("foo");
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
// Find typed argument.
CheckLogMessagePresent(raw_trace);
// Find untyped argument.
EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
- ElementsAre("B:foo.E(arg=(string)value)"));
+ ElementsAre("B:foo.E(arg=(string)value)", "E"));
}
TEST_P(PerfettoApiTest, TrackEventArgs_RefLambdaAndUntyped) {
@@ -2439,16 +2364,14 @@
TRACE_EVENT_BEGIN("foo", "E", GetWriteLogMessageRefLambda(), "arg", "value");
TRACE_EVENT_END("foo");
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
// Find typed argument.
CheckLogMessagePresent(raw_trace);
// Find untyped argument.
EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
- ElementsAre("B:foo.E(arg=(string)value)"));
+ ElementsAre("B:foo.E(arg=(string)value)", "E"));
}
TEST_P(PerfettoApiTest, TrackEventArgs_RefLambdaAndTyped) {
@@ -2464,16 +2387,14 @@
perfetto::protos::pbzero::TrackEvent::kLogMessage, LogMessage());
TRACE_EVENT_END("foo");
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
// Find typed argument.
CheckLogMessagePresent(raw_trace);
// Find untyped argument.
EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
- ElementsAre("B:foo.E(arg=(string)value)"));
+ ElementsAre("B:foo.E(arg=(string)value)", "E"));
}
TEST_P(PerfettoApiTest, TrackEventArgs_TypedAndRefLambda) {
@@ -2488,16 +2409,14 @@
});
TRACE_EVENT_END("foo");
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
// Find typed argument.
CheckLogMessagePresent(raw_trace);
// Find untyped argument.
EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
- ElementsAre("B:foo.E(arg=(string)value)"));
+ ElementsAre("B:foo.E(arg=(string)value)", "E"));
}
TEST_P(PerfettoApiTest, TrackEventArgs_RefLambdaAndRefLambda) {
@@ -2515,13 +2434,12 @@
});
TRACE_EVENT_END("foo");
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
// Find untyped arguments.
- EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
- ElementsAre("B:foo.E(arg1=(string)value1,arg2=(string)value2)"));
+ EXPECT_THAT(
+ ReadSlicesFromTrace(raw_trace),
+ ElementsAre("B:foo.E(arg1=(string)value1,arg2=(string)value2)", "E"));
}
TEST_P(PerfettoApiTest, TrackEventArgs_RefLambdaAndLambda) {
@@ -2539,13 +2457,12 @@
});
TRACE_EVENT_END("foo");
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
// Find untyped arguments.
- EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
- ElementsAre("B:foo.E(arg1=(string)value1,arg2=(string)value2)"));
+ EXPECT_THAT(
+ ReadSlicesFromTrace(raw_trace),
+ ElementsAre("B:foo.E(arg1=(string)value1,arg2=(string)value2)", "E"));
}
TEST_P(PerfettoApiTest, TrackEventArgs_RefLambda) {
@@ -2558,13 +2475,11 @@
});
TRACE_EVENT_END("foo");
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
// Find untyped argument.
EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
- ElementsAre("B:foo.E(arg=(string)value)"));
+ ElementsAre("B:foo.E(arg=(string)value)", "E"));
}
TEST_P(PerfettoApiTest, TrackEventArgs_Flow_Global) {
@@ -2575,9 +2490,7 @@
TRACE_EVENT_INSTANT("foo", "E1", perfetto::Flow::Global(42));
TRACE_EVENT_INSTANT("foo", "E2", perfetto::TerminatingFlow::Global(42));
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
// Find typed argument.
CheckTypedArguments(
@@ -2602,13 +2515,11 @@
}
{ TRACE_EVENT("foo", "E3", perfetto::TerminatingFlow::Global(3)); }
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
EXPECT_THAT(ReadSlicesFromTrace(raw_trace),
ElementsAre("B:foo.E1(flow_ids=1,2,3)", "E",
"B:foo.E2(flow_ids=1)(terminating_flow_ids=2)", "E",
- "B:foo.E3(terminating_flow_ids=3)"));
+ "B:foo.E3(terminating_flow_ids=3)", "E"));
}
TEST_P(PerfettoApiTest, TrackEventArgs_Flow_ProcessScoped) {
@@ -2620,9 +2531,7 @@
TRACE_EVENT_INSTANT("foo", "E2", perfetto::TerminatingFlow::ProcessScoped(1));
TRACE_EVENT_INSTANT("foo", "Flush");
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
// Find typed arguments.
CheckTypedArguments(raw_trace, "E1",
@@ -2648,9 +2557,7 @@
TRACE_EVENT_INSTANT("foo", "E2", perfetto::TerminatingFlow::FromPointer(ptr));
TRACE_EVENT_INSTANT("foo", "Flush");
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
// Find typed arguments.
CheckTypedArguments(raw_trace, "E1",
@@ -2888,10 +2795,7 @@
TRACE_EVENT("test", "AnotherEvent");
TRACE_EVENT("foo", "DisabledEvent");
}
- perfetto::TrackEvent::Flush();
-
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
EXPECT_THAT(
slices,
ElementsAre("B:test.TestEventWithArgs", "E", "B:test.SingleLineTestEvent",
@@ -2921,10 +2825,7 @@
});
}
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
EXPECT_GE(raw_trace.size(), 0u);
bool found_extension = false;
@@ -2964,10 +2865,7 @@
std::vector<int>{42});
}
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ std::vector<char> raw_trace = StopSessionAndReturnBytes(tracing_session);
EXPECT_GE(raw_trace.size(), 0u);
bool found_extension = false;
@@ -3003,10 +2901,7 @@
TRACE_EVENT_INSTANT("test", "TestEvent");
TRACE_EVENT_INSTANT("test", "AnotherEvent");
- perfetto::TrackEvent::Flush();
-
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
EXPECT_THAT(slices, ElementsAre("I:test.TestEvent", "I:test.AnotherEvent"));
}
@@ -3017,10 +2912,7 @@
TRACE_EVENT_INSTANT("test", "ThreadEvent");
TRACE_EVENT_INSTANT("test", "GlobalEvent", perfetto::Track::Global(0u));
- perfetto::TrackEvent::Flush();
-
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
EXPECT_THAT(slices,
ElementsAre("I:test.ThreadEvent", "[track=0]I:test.GlobalEvent"));
}
@@ -3034,12 +2926,10 @@
int* ptr = reinterpret_cast<int*>(2);
TRACE_EVENT_INSTANT("test", "Event",
perfetto::Track::FromPointer(ptr, parent_track));
- perfetto::TrackEvent::Flush();
perfetto::Track track(reinterpret_cast<uintptr_t>(ptr), parent_track);
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
EXPECT_THAT(slices, ElementsAre("[track=" + std::to_string(track.uuid) +
"]I:test.Event"));
}
@@ -3068,14 +2958,11 @@
perfetto::Track::ThreadScoped(&num));
});
t2.join();
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- perfetto::protos::gen::Trace parsed_trace;
- ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
std::unordered_map<std::string, uint64_t> track_uuid_map;
- for (auto packet : parsed_trace.packet()) {
+ for (auto packet : trace.packet()) {
if (packet.has_interned_data()) {
for (auto& ename : packet.interned_data().event_names()) {
track_uuid_map.emplace(ename.name(), packet.track_event().track_uuid());
@@ -3107,10 +2994,7 @@
ctx.AddDebugAnnotation("debug_name", "debug_value");
});
TRACE_EVENT_BEGIN("test", "Event3");
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
-
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
ASSERT_EQ(3u, slices.size());
if (flag) {
EXPECT_EQ("B:test.Event2", slices[1]);
@@ -3150,10 +3034,7 @@
TRACE_EVENT_BEGIN("test", "E", [&](perfetto::EventContext ctx) {
ctx.AddDebugAnnotation("debug_annotation", "value");
});
- perfetto::TrackEvent::Flush();
-
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
EXPECT_THAT(
slices,
ElementsAre(
@@ -3178,10 +3059,7 @@
TRACE_EVENT_BEGIN("test", "E", "custom_arg", MyDebugAnnotation());
TRACE_EVENT_BEGIN("test", "E", "normal_arg", "x", "custom_arg",
std::move(owned_annotation));
- perfetto::TrackEvent::Flush();
-
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
EXPECT_THAT(
slices,
ElementsAre(
@@ -3221,10 +3099,7 @@
TRACE_EVENT_BEGIN("test", "E", "raw_arg", MyRawDebugAnnotation());
TRACE_EVENT_BEGIN("test", "E", "plain_arg", 42, "raw_arg",
MyRawDebugAnnotation());
- perfetto::TrackEvent::Flush();
-
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
EXPECT_THAT(
slices,
ElementsAre("B:test.E(raw_arg=(nested)nested_value)",
@@ -3237,10 +3112,7 @@
tracing_session->get()->StartBlocking();
TRACE_EVENT_BEGIN("test", "E", "arg1", 1, "arg2", 2, "arg3", 3);
- perfetto::TrackEvent::Flush();
-
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
EXPECT_THAT(slices,
ElementsAre("B:test.E(arg1=(int)1,arg2=(int)2,arg3=(int)3)"));
}
@@ -3258,17 +3130,10 @@
"test", "E", "key", "value", [](perfetto::EventContext ctx) {
ctx.event()->set_log_message()->set_source_location_iid(42);
});
- perfetto::TrackEvent::Flush();
-
- tracing_session->get()->StopBlocking();
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- std::string trace(raw_trace.data(), raw_trace.size());
-
- perfetto::protos::gen::Trace parsed_trace;
- ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
bool found_args = false;
- for (const auto& packet : parsed_trace.packet()) {
+ for (const auto& packet : trace.packet()) {
if (!packet.has_track_event())
continue;
const auto& track_event = packet.track_event();
@@ -3298,20 +3163,13 @@
ctx->set_source_location_iid(42);
});
- perfetto::TrackEvent::Flush();
-
- tracing_session->get()->StopBlocking();
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- std::string trace(raw_trace.data(), raw_trace.size());
-
- perfetto::protos::gen::Trace parsed_trace;
- ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
std::vector<std::string> interned_debug_annotation_names;
std::vector<std::string> interned_debug_annotation_proto_type_names;
bool found_args = false;
- for (const auto& packet : parsed_trace.packet()) {
+ for (const auto& packet : trace.packet()) {
if (packet.has_interned_data()) {
for (const auto& interned_name :
packet.interned_data().debug_annotation_names()) {
@@ -3363,10 +3221,7 @@
for (int i = 0; i < 3; i++)
TRACE_EVENT_BEGIN0("test", i % 2 ? "Odd" : "Even");
- perfetto::TrackEvent::Flush();
-
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
EXPECT_THAT(slices, ElementsAre("B:test.Even", "B:test.Odd", "B:test.Even",
"B:test.Even", "B:test.Odd", "B:test.Even"));
}
@@ -3419,9 +3274,7 @@
perfetto::DynamicCategory dyn{"dynamic,bar"};
TRACE_EVENT_BEGIN(dyn, "DynamicGroupBarEvent");
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
tracing_session->session.reset();
return slices;
};
@@ -3672,16 +3525,8 @@
packet = ctx.NewTracePacket();
});
- EXPECT_TRUE(tracing_session->get()->FlushBlocking());
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
- // Deliberately doing ReadTraceBlocking() before StopBlocking() to avoid
- // hitting the auto scrape-on-stop behavior of the service.
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- tracing_session->get()->StopBlocking();
-
- ASSERT_GE(raw_trace.size(), 0u);
- perfetto::protos::gen::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
bool test_packet_found = false;
for (const auto& packet : trace.packet()) {
if (!packet.has_for_testing())
@@ -4338,9 +4183,7 @@
TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP_AND_FLAGS0(
"cat", "LegacyAsync3", 9001, MyTimestamp{6}, TRACE_EVENT_FLAG_NONE);
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
EXPECT_THAT(
slices,
ElementsAre(
@@ -4375,9 +4218,7 @@
std::unique_ptr<MyDebugAnnotation> owned_annotation(new MyDebugAnnotation());
TRACE_EVENT_BEGIN1("cat", "LegacyEvent", "arg", std::move(owned_annotation));
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
EXPECT_THAT(slices,
ElementsAre("B:cat.LegacyEvent(arg=(json){\"key\": 123})",
"B:cat.LegacyEvent(arg=(json){\"key\": 123})"));
@@ -4396,9 +4237,7 @@
std::unique_ptr<MyDebugAnnotation> owned_annotation(new MyDebugAnnotation());
TRACE_EVENT_BEGIN1("cat", "LegacyEvent", "arg", std::move(owned_annotation));
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
EXPECT_THAT(slices,
ElementsAre("B:cat.LegacyEvent(arg=(json){\"key\": 123})"));
@@ -4419,9 +4258,7 @@
"cat", "WithScope",
TRACE_ID_WITH_SCOPE("scope string", TRACE_ID_GLOBAL(0x4000)));
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
EXPECT_THAT(slices, ElementsAre("Legacy_S(unscoped_id=4096):cat.UnscopedId",
"Legacy_S(local_id=8192):cat.LocalId",
"Legacy_S(global_id=12288):cat.GlobalId",
@@ -4444,15 +4281,10 @@
TRACE_EVENT_NESTABLE_ASYNC_END0("cat", "bar", TRACE_ID_WITH_SCOPE("bar", 2));
TRACE_EVENT_NESTABLE_ASYNC_END0("cat", "bar", TRACE_ID_WITH_SCOPE("bar", 1));
TRACE_EVENT_NESTABLE_ASYNC_END0("cat", "foo", TRACE_ID_WITH_SCOPE("foo", 1));
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- perfetto::protos::gen::Trace parsed_trace;
- ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
using LegacyEvent = perfetto::protos::gen::TrackEvent::LegacyEvent;
std::vector<const LegacyEvent*> legacy_events;
- for (const auto& packet : parsed_trace.packet()) {
+ for (const auto& packet : trace.packet()) {
if (packet.has_track_event() && packet.track_event().has_legacy_event()) {
legacy_events.push_back(&packet.track_event().legacy_event());
}
@@ -4495,9 +4327,7 @@
TRACE_EVENT_FLAG_FLOW_IN, "step", "End");
}
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
EXPECT_THAT(slices,
ElementsAre("B(bind_id=1234)(flow_direction=2):cat.LatencyInfo."
"Flow(step=(string)Begin)",
@@ -4991,9 +4821,7 @@
{ TRACE_EVENT1("cat", "ScopedLegacy", "value", obj.value); }
obj.mutex.Unlock();
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
- auto slices = ReadSlicesFromTrace(tracing_session->get());
+ auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
EXPECT_THAT(slices, ElementsAre("I:cat.Instant(value=(int)1)",
"[track=0]I:cat.InstantLegacy(value=(int)1)",
"B:cat.Scoped(value=(int)1)", "E",
@@ -5033,12 +4861,7 @@
TRACE_COUNTER("cat", track1, 98);
TRACE_COUNTER("cat", track2, 1084);
- perfetto::TrackEvent::Flush();
-
- tracing_session->get()->StopBlocking();
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- perfetto::protos::gen::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
std::unordered_map<uint64_t, std::string> counter_names;
// Map(Counter name -> counter values)
std::unordered_map<std::string, std::vector<int64_t>> values;
@@ -5094,13 +4917,7 @@
TRACE_COUNTER("cat",
perfetto::CounterTrack("Power", "GW").set_category("dmc"),
MyTimestamp(1985u), 1.21f);
- perfetto::TrackEvent::Flush();
-
- tracing_session->get()->StopBlocking();
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-
- perfetto::protos::gen::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
std::map<uint64_t, std::string> counter_names;
std::vector<std::string> counter_samples;
for (const auto& packet : trace.packet()) {
@@ -5151,13 +4968,7 @@
// Emit an empty event.
PERFETTO_INTERNAL_ADD_EMPTY_EVENT();
- perfetto::TrackEvent::Flush();
-
- tracing_session->get()->StopBlocking();
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-
- perfetto::protos::gen::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+ auto trace = StopSessionAndReturnParsedTrace(tracing_session);
auto it = std::find_if(trace.packet().begin(), trace.packet().end(),
[](const perfetto::protos::gen::TracePacket& packet) {
return packet.has_trace_stats();
diff --git a/ui/src/common/engine.ts b/ui/src/common/engine.ts
index 01c1207..fba2bca 100644
--- a/ui/src/common/engine.ts
+++ b/ui/src/common/engine.ts
@@ -190,12 +190,17 @@
break;
case TPM.TPM_COMPUTE_METRIC:
const metricRes = assertExists(rpc.metricResult) as ComputeMetricResult;
+ const pendingComputeMetric =
+ assertExists(this.pendingComputeMetrics.shift());
if (metricRes.error && metricRes.error.length > 0) {
- throw new QueryError(`ComputeMetric() error: ${metricRes.error}`, {
- query: 'COMPUTE_METRIC',
- });
+ const error =
+ new QueryError(`ComputeMetric() error: ${metricRes.error}`, {
+ query: 'COMPUTE_METRIC',
+ });
+ pendingComputeMetric.reject(error);
+ } else {
+ pendingComputeMetric.resolve(metricRes);
}
- assertExists(this.pendingComputeMetrics.shift()).resolve(metricRes);
break;
default:
console.log(
diff --git a/ui/src/controller/pivot_table_redux_controller.ts b/ui/src/controller/pivot_table_redux_controller.ts
index c72ce02..833b7a9 100644
--- a/ui/src/controller/pivot_table_redux_controller.ts
+++ b/ui/src/controller/pivot_table_redux_controller.ts
@@ -141,6 +141,7 @@
// Controller responsible for showing the panel with pivot table, as well as
// executing its queries and post-processing query results.
export class PivotTableReduxController extends Controller<{}> {
+ static detailsCount = 0;
engine: Engine;
lastQueryAreaId = '';
lastQueryAreaTracks = new Set<string>();
diff --git a/ui/src/frontend/details_panel.ts b/ui/src/frontend/details_panel.ts
index 357f246..8aa5dc8 100644
--- a/ui/src/frontend/details_panel.ts
+++ b/ui/src/frontend/details_panel.ts
@@ -169,6 +169,24 @@
}
}
+// For queries that are supposed to be displayed in the bottom bar, return a
+// name for a tab. Otherwise, return null.
+function userVisibleQueryName(id: string): string|null {
+ if (id === 'command') {
+ return 'Omnibox Query';
+ }
+ if (id === 'analyze-page-query') {
+ return 'Standalone Query';
+ }
+ if (id.startsWith('command_')) {
+ return 'Pinned Query';
+ }
+ if (id.startsWith('pivot_table_details_')) {
+ return 'Pivot Table Details';
+ }
+ return null;
+}
+
export class DetailsPanel implements m.ClassComponent {
private detailsHeight = DEFAULT_DETAILS_HEIGHT_PX;
@@ -273,16 +291,25 @@
});
}
- if (globals.queryResults.has('command')) {
+ const queryResults = [];
+ for (const queryId of globals.queryResults.keys()) {
+ const readableName = userVisibleQueryName(queryId);
+ if (readableName !== null) {
+ queryResults.push({queryId, name: readableName});
+ }
+ }
+
+ for (const {queryId, name} of queryResults) {
const count =
- (globals.queryResults.get('command') as QueryResponse).rows.length;
+ (globals.queryResults.get(queryId) as QueryResponse).rows.length;
detailsPanels.push({
- key: 'query_result',
- name: `Query Result (${count})`,
- vnode: m(QueryTable, {key: 'query', queryId: 'command'})
+ key: `query_result_${queryId}`,
+ name: `${name} (${count})`,
+ vnode: m(QueryTable, {key: `query_${queryId}`, queryId})
});
}
+
if (globals.state.nonSerializableState.pivotTableRedux.selectionArea !==
null) {
detailsPanels.push({
diff --git a/ui/src/frontend/pivot_table_redux.ts b/ui/src/frontend/pivot_table_redux.ts
index d0ed91b..84ec43b 100644
--- a/ui/src/frontend/pivot_table_redux.ts
+++ b/ui/src/frontend/pivot_table_redux.ts
@@ -25,7 +25,10 @@
PivotTableReduxResult,
SortDirection
} from '../common/state';
-import {PivotTree} from '../controller/pivot_table_redux_controller';
+import {
+ PivotTableReduxController,
+ PivotTree
+} from '../controller/pivot_table_redux_controller';
import {globals} from './globals';
import {Panel} from './panel';
@@ -179,7 +182,8 @@
// TODO(ddrone): the UI of running query as if it was a canned or
// custom query is a temporary one, replace with a proper UI.
globals.dispatch(Actions.executeQuery({
- queryId: 'command',
+ queryId: `pivot_table_details_${
+ PivotTableReduxController.detailsCount++}`,
query,
}));
}
diff --git a/ui/src/frontend/publish.ts b/ui/src/frontend/publish.ts
index aa148cb..53339c0 100644
--- a/ui/src/frontend/publish.ts
+++ b/ui/src/frontend/publish.ts
@@ -147,7 +147,7 @@
export function publishQueryResult(args: {id: string, data?: {}}) {
globals.queryResults.set(args.id, args.data);
- globals.dispatch(Actions.setCurrentTab({tab: 'query_result'}));
+ globals.dispatch(Actions.setCurrentTab({tab: `query_result_${args.id}`}));
globals.publishRedraw();
}
diff --git a/ui/src/frontend/topbar.ts b/ui/src/frontend/topbar.ts
index d816249..ccb3a56 100644
--- a/ui/src/frontend/topbar.ts
+++ b/ui/src/frontend/topbar.ts
@@ -34,6 +34,7 @@
let mode: Mode = SEARCH;
let displayStepThrough = false;
+let queryCount = 0;
function onKeyDown(e: Event) {
const event = (e as KeyboardEvent);
@@ -59,6 +60,12 @@
if (mode === SEARCH && key === 'Enter') {
txt.blur();
}
+
+ if (mode === COMMAND && key === 'Enter') {
+ const queryId =
+ (event.metaKey || event.ctrlKey) ? `command_${queryCount++}` : 'command';
+ globals.dispatch(Actions.executeQuery({queryId, query: txt.value}));
+ }
}
function onKeyUp(e: Event) {
@@ -75,10 +82,6 @@
globals.rafScheduler.scheduleFullRedraw();
return;
}
- if (mode === COMMAND && key === 'Enter') {
- globals.dispatch(
- Actions.executeQuery({queryId: 'command', query: txt.value}));
- }
}
class Omnibox implements m.ClassComponent {