Merge "perfetto-ui: Fix bug in pan_and_zoom_handler.ts"
diff --git a/Android.bp b/Android.bp
index 541e66f..480e618 100644
--- a/Android.bp
+++ b/Android.bp
@@ -32,6 +32,7 @@
":perfetto_protos_perfetto_trace_trusted_lite_gen",
":perfetto_protos_perfetto_trace_zero_gen",
":perfetto_src_ipc_wire_protocol_gen",
+ "src/base/event.cc",
"src/base/file_utils.cc",
"src/base/metatrace.cc",
"src/base/page_allocator.cc",
@@ -157,6 +158,7 @@
":perfetto_src_ipc_wire_protocol_gen",
":perfetto_src_perfetto_cmd_protos_gen",
"src/base/android_task_runner.cc",
+ "src/base/event.cc",
"src/base/file_utils.cc",
"src/base/metatrace.cc",
"src/base/page_allocator.cc",
@@ -297,6 +299,7 @@
":perfetto_protos_perfetto_trace_zero_gen",
":perfetto_src_ipc_wire_protocol_gen",
"src/base/android_task_runner.cc",
+ "src/base/event.cc",
"src/base/file_utils.cc",
"src/base/metatrace.cc",
"src/base/page_allocator.cc",
@@ -3612,6 +3615,7 @@
":perfetto_protos_perfetto_trace_trusted_lite_gen",
":perfetto_protos_perfetto_trace_zero_gen",
":perfetto_src_ipc_wire_protocol_gen",
+ "src/base/event.cc",
"src/base/file_utils.cc",
"src/base/metatrace.cc",
"src/base/page_allocator.cc",
@@ -3800,6 +3804,7 @@
":perfetto_src_traced_probes_ftrace_test_messages_lite_gen",
":perfetto_src_traced_probes_ftrace_test_messages_zero_gen",
"src/base/android_task_runner.cc",
+ "src/base/event.cc",
"src/base/file_utils.cc",
"src/base/metatrace.cc",
"src/base/page_allocator.cc",
@@ -4033,6 +4038,7 @@
":perfetto_protos_perfetto_trace_minimal_lite_gen",
":perfetto_protos_perfetto_trace_ps_lite_gen",
":perfetto_protos_perfetto_trace_sys_stats_lite_gen",
+ "src/base/event.cc",
"src/base/file_utils.cc",
"src/base/metatrace.cc",
"src/base/page_allocator.cc",
diff --git a/include/perfetto/base/BUILD.gn b/include/perfetto/base/BUILD.gn
index 10da3d0..5ee76ba 100644
--- a/include/perfetto/base/BUILD.gn
+++ b/include/perfetto/base/BUILD.gn
@@ -17,6 +17,7 @@
source_set("base") {
sources = [
"build_config.h",
+ "event.h",
"export.h",
"file_utils.h",
"logging.h",
diff --git a/include/perfetto/base/android_task_runner.h b/include/perfetto/base/android_task_runner.h
index 5087330..5aebbac 100644
--- a/include/perfetto/base/android_task_runner.h
+++ b/include/perfetto/base/android_task_runner.h
@@ -17,6 +17,7 @@
#ifndef INCLUDE_PERFETTO_BASE_ANDROID_TASK_RUNNER_H_
#define INCLUDE_PERFETTO_BASE_ANDROID_TASK_RUNNER_H_
+#include "perfetto/base/event.h"
#include "perfetto/base/scoped_file.h"
#include "perfetto/base/task_runner.h"
#include "perfetto/base/thread_checker.h"
@@ -69,7 +70,7 @@
void ScheduleDelayedWakeUp(TimeMillis time);
ALooper* const looper_;
- ScopedFile immediate_event_;
+ Event immediate_event_;
ScopedFile delayed_timer_;
ThreadChecker thread_checker_;
diff --git a/include/perfetto/base/event.h b/include/perfetto/base/event.h
new file mode 100644
index 0000000..bca6c00
--- /dev/null
+++ b/include/perfetto/base/event.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_EVENT_H_
+#define INCLUDE_PERFETTO_BASE_EVENT_H_
+
+#include "perfetto/base/build_config.h"
+#include "perfetto/base/scoped_file.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#define PERFETTO_USE_EVENTFD() 1
+#else
+#define PERFETTO_USE_EVENTFD() 0
+#endif
+
+namespace perfetto {
+namespace base {
+
+// A waitable event that can be used with poll/select.
+// This is really a wrapper around eventfd_create with a pipe-based fallback
+// for other platforms where eventfd is not supported.
+class Event {
+ public:
+ Event();
+ ~Event();
+ Event(Event&&) noexcept = default;
+ Event& operator=(Event&&) = default;
+
+ // The non-blocking file descriptor that can be polled to wait for the event.
+ int fd() const { return fd_.get(); }
+
+ // Can be called from any thread.
+ void Notify();
+
+ // Can be called from any thread. If more Notify() are queued a Clear() call
+ // can clear all of them (up to 16 per call).
+ void Clear();
+
+ private:
+ // The eventfd, when eventfd is supported, otherwise this is the read end of
+ // the pipe for fallback mode.
+ ScopedFile fd_;
+
+#if !PERFETTO_USE_EVENTFD()
+ // The write end of the wakeup pipe.
+ ScopedFile write_fd_;
+#endif
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_BASE_EVENT_H_
diff --git a/include/perfetto/base/file_utils.h b/include/perfetto/base/file_utils.h
index 1efb450..71f716f 100644
--- a/include/perfetto/base/file_utils.h
+++ b/include/perfetto/base/file_utils.h
@@ -21,6 +21,8 @@
#include <string>
+#include "perfetto/base/utils.h" // For ssize_t on Windows.
+
namespace perfetto {
namespace base {
diff --git a/include/perfetto/base/unix_task_runner.h b/include/perfetto/base/unix_task_runner.h
index 65c8361..3d1a896 100644
--- a/include/perfetto/base/unix_task_runner.h
+++ b/include/perfetto/base/unix_task_runner.h
@@ -18,6 +18,7 @@
#define INCLUDE_PERFETTO_BASE_UNIX_TASK_RUNNER_H_
#include "perfetto/base/build_config.h"
+#include "perfetto/base/event.h"
#include "perfetto/base/scoped_file.h"
#include "perfetto/base/task_runner.h"
#include "perfetto/base/thread_checker.h"
@@ -30,13 +31,6 @@
#include <mutex>
#include <vector>
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
- PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#define PERFETTO_USE_EVENTFD() 1
-#else
-#define PERFETTO_USE_EVENTFD() 0
-#endif
-
namespace perfetto {
namespace base {
@@ -75,11 +69,7 @@
// On Linux, an eventfd(2) used to waking up the task runner when a new task
// is posted. Otherwise the read end of a pipe used for the same purpose.
- ScopedFile event_;
-#if !PERFETTO_USE_EVENTFD()
- // The write end of the wakeup pipe.
- ScopedFile event_write_;
-#endif
+ Event event_;
std::vector<struct pollfd> poll_fds_;
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index 019cd7b..ad3f170 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -37,6 +37,7 @@
# TODO(brucedawson): Enable these for Windows when possible.
if (!is_win) {
sources += [
+ "event.cc",
"temp_file.cc",
"unix_task_runner.cc",
]
diff --git a/src/base/android_task_runner.cc b/src/base/android_task_runner.cc
index d8e7cc7..23697c8 100644
--- a/src/base/android_task_runner.cc
+++ b/src/base/android_task_runner.cc
@@ -17,7 +17,6 @@
#include "perfetto/base/android_task_runner.h"
#include <errno.h>
-#include <sys/eventfd.h>
#include <sys/timerfd.h>
namespace perfetto {
@@ -25,13 +24,11 @@
AndroidTaskRunner::AndroidTaskRunner()
: looper_(ALooper_prepare(0 /* require callbacks */)),
- immediate_event_(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC)),
delayed_timer_(
timerfd_create(kWallTimeClockSource, TFD_NONBLOCK | TFD_CLOEXEC)) {
ALooper_acquire(looper_);
- PERFETTO_CHECK(immediate_event_);
PERFETTO_CHECK(delayed_timer_);
- AddFileDescriptorWatch(immediate_event_.get(),
+ AddFileDescriptorWatch(immediate_event_.fd(),
std::bind(&AndroidTaskRunner::RunImmediateTask, this));
AddFileDescriptorWatch(delayed_timer_.get(),
std::bind(&AndroidTaskRunner::RunDelayedTask, this));
@@ -81,11 +78,7 @@
}
void AndroidTaskRunner::RunImmediateTask() {
- uint64_t unused = 0;
- if (read(immediate_event_.get(), &unused, sizeof(unused)) != sizeof(unused) &&
- errno != EAGAIN) {
- PERFETTO_DPLOG("read");
- }
+ immediate_event_.Clear();
// If locking overhead becomes an issue, add a separate work queue.
bool has_next;
@@ -133,11 +126,7 @@
}
void AndroidTaskRunner::ScheduleImmediateWakeUp() {
- uint64_t value = 1;
- if (write(immediate_event_.get(), &value, sizeof(value)) == -1 &&
- errno != EAGAIN) {
- PERFETTO_DPLOG("write");
- }
+ immediate_event_.Notify();
}
void AndroidTaskRunner::ScheduleDelayedWakeUp(TimeMillis time) {
diff --git a/src/base/event.cc b/src/base/event.cc
new file mode 100644
index 0000000..4085618
--- /dev/null
+++ b/src/base/event.cc
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2018 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 <unistd.h>
+
+#include "perfetto/base/event.h"
+#include "perfetto/base/logging.h"
+
+#if PERFETTO_USE_EVENTFD()
+#include <sys/eventfd.h>
+#endif
+
+namespace perfetto {
+namespace base {
+
+Event::Event() {
+#if PERFETTO_USE_EVENTFD()
+ fd_.reset(eventfd(/* start value */ 0, EFD_CLOEXEC | EFD_NONBLOCK));
+ PERFETTO_CHECK(fd_);
+#else
+ int pipe_fds[2];
+ PERFETTO_CHECK(pipe(pipe_fds) == 0);
+
+ // Make the pipe non-blocking so that we never block the waking thread (either
+ // the main thread or another one) when scheduling a wake-up.
+ for (auto fd : pipe_fds) {
+ int flags = fcntl(fd, F_GETFL, 0);
+ PERFETTO_CHECK(flags != -1);
+ PERFETTO_CHECK(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0);
+ PERFETTO_CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
+ }
+ fd_.reset(pipe_fds[0]);
+ write_fd_.reset(pipe_fds[1]);
+#endif // !PERFETTO_USE_EVENTFD()
+}
+
+Event::~Event() = default;
+
+void Event::Notify() {
+ const uint64_t value = 1;
+
+#if PERFETTO_USE_EVENTFD()
+ ssize_t ret = write(fd_.get(), &value, sizeof(value));
+#else
+ ssize_t ret = write(write_fd_.get(), &value, sizeof(uint8_t));
+#endif
+
+ if (ret <= 0 && errno != EAGAIN) {
+ PERFETTO_DPLOG("write()");
+ PERFETTO_DCHECK(false);
+ }
+}
+
+void Event::Clear() {
+#if PERFETTO_USE_EVENTFD()
+ uint64_t value;
+ ssize_t ret = read(fd_.get(), &value, sizeof(value));
+#else
+ // Drain the byte(s) written to the wake-up pipe. We can potentially read
+ // more than one byte if several wake-ups have been scheduled.
+ char buffer[16];
+ ssize_t ret = read(fd_.get(), &buffer[0], sizeof(buffer));
+#endif
+ if (ret <= 0 && errno != EAGAIN)
+ PERFETTO_DPLOG("read()");
+}
+
+} // namespace base
+} // namespace perfetto
diff --git a/src/base/unix_task_runner.cc b/src/base/unix_task_runner.cc
index 006b7af..44501df 100644
--- a/src/base/unix_task_runner.cc
+++ b/src/base/unix_task_runner.cc
@@ -24,32 +24,11 @@
#include <limits>
-#if PERFETTO_USE_EVENTFD()
-#include <sys/eventfd.h>
-#endif
-
namespace perfetto {
namespace base {
UnixTaskRunner::UnixTaskRunner() {
-#if PERFETTO_USE_EVENTFD()
- event_.reset(eventfd(/* start value */ 0, EFD_CLOEXEC | EFD_NONBLOCK));
-#else
- int pipe_fds[2];
- PERFETTO_CHECK(pipe(pipe_fds) == 0);
-
- // Make the pipe non-blocking so that we never block the waking thread (either
- // the main thread or another one) when scheduling a wake-up.
- for (auto fd : pipe_fds) {
- int flags = fcntl(fd, F_GETFL, 0);
- PERFETTO_CHECK(flags != -1);
- PERFETTO_CHECK(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0);
- PERFETTO_CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
- }
- event_.reset(pipe_fds[0]);
- event_write_.reset(pipe_fds[1]);
-#endif // !PERFETTO_USE_EVENTFD()
- AddFileDescriptorWatch(event_.get(), [] {
+ AddFileDescriptorWatch(event_.fd(), [] {
// Not reached -- see PostFileDescriptorWatches().
PERFETTO_DCHECK(false);
});
@@ -58,14 +37,7 @@
UnixTaskRunner::~UnixTaskRunner() = default;
void UnixTaskRunner::WakeUp() {
- const uint64_t value = 1;
-#if PERFETTO_USE_EVENTFD()
- ssize_t ret = write(event_.get(), &value, sizeof(value));
-#else
- ssize_t ret = write(event_write_.get(), &value, sizeof(uint8_t));
-#endif
- if (ret <= 0 && errno != EAGAIN)
- PERFETTO_DPLOG("write()");
+ event_.Notify();
}
void UnixTaskRunner::Run() {
@@ -153,18 +125,8 @@
// The wake-up event is handled inline to avoid an infinite recursion of
// posted tasks.
- if (poll_fds_[i].fd == event_.get()) {
-#if PERFETTO_USE_EVENTFD()
- uint64_t value;
- ssize_t ret = read(event_.get(), &value, sizeof(value));
-#else
- // Drain the byte(s) written to the wake-up pipe. We can potentially read
- // more than one byte if several wake-ups have been scheduled.
- char buffer[16];
- ssize_t ret = read(event_.get(), &buffer[0], sizeof(buffer));
-#endif
- if (ret <= 0 && errno != EAGAIN)
- PERFETTO_DPLOG("read()");
+ if (poll_fds_[i].fd == event_.fd()) {
+ event_.Clear();
continue;
}
diff --git a/src/trace_processor/counters_table_unittest.cc b/src/trace_processor/counters_table_unittest.cc
index 211cb78..dc2ff0a 100644
--- a/src/trace_processor/counters_table_unittest.cc
+++ b/src/trace_processor/counters_table_unittest.cc
@@ -62,12 +62,16 @@
TEST_F(CountersTableUnittest, SelectWhereCpu) {
uint64_t timestamp = 1000;
uint32_t freq = 3000;
+
context_.storage->mutable_counters()->AddCounter(
- timestamp, 0, 1, freq, 0, 1 /* cpu */, RefType::kCPU_ID);
+ timestamp, 0 /* dur */, 1, freq, 0 /* value delta */, 1 /* cpu */,
+ RefType::kCPU_ID);
context_.storage->mutable_counters()->AddCounter(
- timestamp + 1, 1, 1, freq + 1000, 1000, 1 /* cpu */, RefType::kCPU_ID);
+ timestamp + 1, 1 /* dur */, 1, freq + 1000, 1000 /* value delta */,
+ 1 /* cpu */, RefType::kCPU_ID);
context_.storage->mutable_counters()->AddCounter(
- timestamp + 2, 1, 1, freq + 2000, 1000, 2 /* cpu */, RefType::kCPU_ID);
+ timestamp + 2, 1 /* dur */, 1, freq + 2000, 1000 /* value delta */,
+ 2 /* cpu */, RefType::kCPU_ID);
PrepareValidStatement("SELECT ts, dur, value FROM counters where ref = 1");
@@ -88,6 +92,7 @@
uint64_t timestamp = 1000;
uint32_t freq = 3000;
uint32_t name_id = 1;
+
context_.storage->mutable_counters()->AddCounter(
timestamp, 1 /* dur */, name_id, freq, 0 /* value delta */, 1 /* cpu */,
RefType::kCPU_ID);
diff --git a/src/trace_processor/process_tracker_unittest.cc b/src/trace_processor/process_tracker_unittest.cc
index 7ebeb5b..eac2bab 100644
--- a/src/trace_processor/process_tracker_unittest.cc
+++ b/src/trace_processor/process_tracker_unittest.cc
@@ -78,12 +78,9 @@
static const char kCommProc2[] = "process2";
context.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, prev_state,
- kCommProc1,
- /*tid=*/4);
+ /*tid=*/4, kCommProc1);
context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
- prev_state, kCommProc2,
-
- /*tid=*/1);
+ prev_state, /*tid=*/1, kCommProc2);
context.process_tracker->UpdateProcess(2, "test");
context.process_tracker->UpdateThread(4, 2);
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
index c82982a..1cb2086 100644
--- a/src/trace_processor/proto_trace_parser.cc
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -465,7 +465,7 @@
uint32_t prev_pid = 0;
uint32_t prev_state = 0;
- base::StringView prev_comm;
+ base::StringView next_comm;
uint32_t next_pid = 0;
for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
switch (fld.id) {
@@ -475,18 +475,18 @@
case protos::SchedSwitchFtraceEvent::kPrevStateFieldNumber:
prev_state = fld.as_uint32();
break;
- case protos::SchedSwitchFtraceEvent::kPrevCommFieldNumber:
- prev_comm = fld.as_string();
- break;
case protos::SchedSwitchFtraceEvent::kNextPidFieldNumber:
next_pid = fld.as_uint32();
break;
+ case protos::SchedSwitchFtraceEvent::kNextCommFieldNumber:
+ next_comm = fld.as_string();
+ break;
default:
break;
}
}
context_->sched_tracker->PushSchedSwitch(cpu, timestamp, prev_pid, prev_state,
- prev_comm, next_pid);
+ next_pid, next_comm);
PERFETTO_DCHECK(decoder.IsEndOfBuffer());
}
diff --git a/src/trace_processor/proto_trace_parser_unittest.cc b/src/trace_processor/proto_trace_parser_unittest.cc
index e502da5..1e6c9b6 100644
--- a/src/trace_processor/proto_trace_parser_unittest.cc
+++ b/src/trace_processor/proto_trace_parser_unittest.cc
@@ -48,8 +48,8 @@
uint64_t timestamp,
uint32_t prev_pid,
uint32_t prev_state,
- base::StringView prev_comm,
- uint32_t next_pid));
+ uint32_t next_pid,
+ base::StringView next_comm));
MOCK_METHOD5(PushCounter,
void(uint64_t timestamp,
@@ -119,11 +119,11 @@
auto* sched_switch = event->mutable_sched_switch();
sched_switch->set_prev_pid(10);
sched_switch->set_prev_state(32);
- sched_switch->set_prev_comm(kProcName);
+ sched_switch->set_next_comm(kProcName);
sched_switch->set_next_pid(100);
- EXPECT_CALL(*sched_, PushSchedSwitch(10, 1000, 10, 32,
- base::StringView(kProcName), 100));
+ EXPECT_CALL(*sched_, PushSchedSwitch(10, 1000, 10, 32, 100,
+ base::StringView(kProcName)));
Tokenize(trace);
}
@@ -140,7 +140,7 @@
auto* sched_switch = event->mutable_sched_switch();
sched_switch->set_prev_pid(10);
sched_switch->set_prev_state(32);
- sched_switch->set_prev_comm(kProcName1);
+ sched_switch->set_next_comm(kProcName1);
sched_switch->set_next_pid(100);
event = bundle->add_event();
@@ -150,14 +150,14 @@
sched_switch = event->mutable_sched_switch();
sched_switch->set_prev_pid(100);
sched_switch->set_prev_state(32);
- sched_switch->set_prev_comm(kProcName2);
+ sched_switch->set_next_comm(kProcName2);
sched_switch->set_next_pid(10);
- EXPECT_CALL(*sched_, PushSchedSwitch(10, 1000, 10, 32,
- base::StringView(kProcName1), 100));
+ EXPECT_CALL(*sched_, PushSchedSwitch(10, 1000, 10, 32, 100,
+ base::StringView(kProcName1)));
- EXPECT_CALL(*sched_, PushSchedSwitch(10, 1001, 100, 32,
- base::StringView(kProcName2), 10));
+ EXPECT_CALL(*sched_, PushSchedSwitch(10, 1001, 100, 32, 10,
+ base::StringView(kProcName2)));
Tokenize(trace);
}
@@ -175,7 +175,7 @@
auto* sched_switch = event->mutable_sched_switch();
sched_switch->set_prev_pid(10);
sched_switch->set_prev_state(32);
- sched_switch->set_prev_comm(kProcName1);
+ sched_switch->set_next_comm(kProcName1);
sched_switch->set_next_pid(100);
bundle = trace.add_packet()->mutable_ftrace_events();
@@ -188,14 +188,14 @@
sched_switch = event->mutable_sched_switch();
sched_switch->set_prev_pid(100);
sched_switch->set_prev_state(32);
- sched_switch->set_prev_comm(kProcName2);
+ sched_switch->set_next_comm(kProcName2);
sched_switch->set_next_pid(10);
- EXPECT_CALL(*sched_, PushSchedSwitch(10, 1000, 10, 32,
- base::StringView(kProcName1), 100));
+ EXPECT_CALL(*sched_, PushSchedSwitch(10, 1000, 10, 32, 100,
+ base::StringView(kProcName1)));
- EXPECT_CALL(*sched_, PushSchedSwitch(10, 1001, 100, 32,
- base::StringView(kProcName2), 10));
+ EXPECT_CALL(*sched_, PushSchedSwitch(10, 1001, 100, 32, 10,
+ base::StringView(kProcName2)));
Tokenize(trace);
}
@@ -209,7 +209,7 @@
auto* sched_switch = event->mutable_sched_switch();
sched_switch->set_prev_pid(10);
sched_switch->set_prev_state(32);
- sched_switch->set_prev_comm(kProcName1);
+ sched_switch->set_next_comm(kProcName1);
sched_switch->set_next_pid(100);
protos::Trace trace_2;
@@ -221,15 +221,15 @@
sched_switch = event->mutable_sched_switch();
sched_switch->set_prev_pid(100);
sched_switch->set_prev_state(32);
- sched_switch->set_prev_comm(kProcName2);
+ sched_switch->set_next_comm(kProcName2);
sched_switch->set_next_pid(10);
- EXPECT_CALL(*sched_, PushSchedSwitch(10, 1000, 10, 32,
- base::StringView(kProcName1), 100));
+ EXPECT_CALL(*sched_, PushSchedSwitch(10, 1000, 10, 32, 100,
+ base::StringView(kProcName1)));
Tokenize(trace_1);
- EXPECT_CALL(*sched_, PushSchedSwitch(10, 1001, 100, 32,
- base::StringView(kProcName2), 10));
+ EXPECT_CALL(*sched_, PushSchedSwitch(10, 1001, 100, 32, 10,
+ base::StringView(kProcName2)));
Tokenize(trace_2);
}
diff --git a/src/trace_processor/sched_slice_table_unittest.cc b/src/trace_processor/sched_slice_table_unittest.cc
index 1f3cc18..57b0a95 100644
--- a/src/trace_processor/sched_slice_table_unittest.cc
+++ b/src/trace_processor/sched_slice_table_unittest.cc
@@ -70,15 +70,16 @@
static const char kCommProc2[] = "process2";
uint32_t pid_2 = 4;
context_.sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, prev_state,
- kCommProc1, pid_2);
+ pid_2, kCommProc1);
context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 3, pid_2, prev_state,
- kCommProc2, pid_1);
+ pid_1, kCommProc2);
context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 4, pid_1, prev_state,
- kCommProc1, pid_2);
+ pid_2, kCommProc1);
context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 10, pid_2,
- prev_state, kCommProc2, pid_1);
+ prev_state, pid_1, kCommProc2);
- PrepareValidStatement("SELECT dur, ts, cpu FROM sched ORDER BY dur");
+ PrepareValidStatement(
+ "SELECT dur, ts, cpu FROM sched where dur != 0 ORDER BY dur");
ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
ASSERT_EQ(sqlite3_column_int64(*stmt_, 0), 1 /* duration */);
@@ -109,19 +110,20 @@
static const char kCommProc2[] = "process2";
uint32_t pid_2 = 4;
context_.sched_tracker->PushSchedSwitch(cpu_3, timestamp - 2, pid_1,
- prev_state, kCommProc1, pid_2);
+ prev_state, pid_2, kCommProc1);
context_.sched_tracker->PushSchedSwitch(cpu_3, timestamp - 1, pid_2,
- prev_state, kCommProc2, pid_1);
+ prev_state, pid_1, kCommProc2);
context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp, pid_1, prev_state,
- kCommProc1, pid_2);
+ pid_2, kCommProc1);
context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 3, pid_2,
- prev_state, kCommProc2, pid_1);
+ prev_state, pid_1, kCommProc2);
context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp + 4, pid_1,
- prev_state, kCommProc1, pid_2);
+ prev_state, pid_2, kCommProc1);
context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 10, pid_2,
- prev_state, kCommProc2, pid_1);
+ prev_state, pid_1, kCommProc2);
- PrepareValidStatement("SELECT dur, ts, cpu FROM sched ORDER BY dur desc");
+ PrepareValidStatement(
+ "SELECT dur, ts, cpu FROM sched where dur != 0 ORDER BY dur desc");
ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
ASSERT_EQ(sqlite3_column_int64(*stmt_, 0), 7 /* duration */);
@@ -151,15 +153,16 @@
static const char kCommProc2[] = "process2";
uint32_t pid_2 = 4;
context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp, pid_1, prev_state,
- kCommProc1, pid_2);
+ pid_2, kCommProc1);
context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 3, pid_2,
- prev_state, kCommProc2, pid_1);
+ prev_state, pid_1, kCommProc2);
context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp + 4, pid_1,
- prev_state, kCommProc1, pid_2);
+ prev_state, pid_2, kCommProc1);
context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 10, pid_2,
- prev_state, kCommProc2, pid_1);
+ prev_state, pid_1, kCommProc2);
- PrepareValidStatement("SELECT dur, ts, cpu FROM sched WHERE cpu = 3");
+ PrepareValidStatement(
+ "SELECT dur, ts, cpu FROM sched WHERE dur != 0 and cpu = 3");
ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
ASSERT_EQ(sqlite3_column_int64(*stmt_, 0), 4 /* duration */);
@@ -178,15 +181,15 @@
static const char kCommProc2[] = "process2";
uint32_t pid_2 = 4;
context_.sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, prev_state,
- kCommProc1, pid_2);
+ pid_2, kCommProc1);
context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 3, pid_2, prev_state,
- kCommProc2, pid_1);
+ pid_1, kCommProc2);
context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 4, pid_1, prev_state,
- kCommProc1, pid_2);
+ pid_2, kCommProc1);
context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 10, pid_2,
- prev_state, kCommProc2, pid_1);
+ prev_state, pid_1, kCommProc2);
- PrepareValidStatement("SELECT utid FROM sched ORDER BY utid");
+ PrepareValidStatement("SELECT utid FROM sched where dur != 0 ORDER BY utid");
ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
ASSERT_EQ(sqlite3_column_int64(*stmt_, 0), 1 /* duration */);
@@ -211,15 +214,16 @@
// respectively, @ T=50 and T=70.
for (uint64_t i = 0; i <= 11; i++) {
context_.sched_tracker->PushSchedSwitch(cpu_5, 50 + i, pid_1, prev_state,
- "pid_1", pid_1);
+ pid_1, "pid_1");
}
for (uint64_t i = 0; i <= 11; i++) {
context_.sched_tracker->PushSchedSwitch(cpu_7, 70 + i, pid_2, prev_state,
- "pid_2", pid_2);
+ pid_2, "pid_2");
}
auto query = [this](const std::string& where_clauses) {
- PrepareValidStatement("SELECT ts from sched WHERE " + where_clauses);
+ PrepareValidStatement("SELECT ts from sched WHERE dur != 0 and " +
+ where_clauses);
std::vector<int> res;
while (sqlite3_step(*stmt_) == SQLITE_ROW) {
res.push_back(sqlite3_column_int(*stmt_, 0));
diff --git a/src/trace_processor/sched_tracker.cc b/src/trace_processor/sched_tracker.cc
index 4dcc097..67071a0 100644
--- a/src/trace_processor/sched_tracker.cc
+++ b/src/trace_processor/sched_tracker.cc
@@ -30,12 +30,16 @@
SchedTracker::~SchedTracker() = default;
+StringId SchedTracker::GetThreadNameId(uint32_t tid, base::StringView comm) {
+ return tid == 0 ? idle_string_id_ : context_->storage->InternString(comm);
+}
+
void SchedTracker::PushSchedSwitch(uint32_t cpu,
uint64_t timestamp,
uint32_t prev_pid,
- uint32_t prev_state,
- base::StringView prev_comm,
- uint32_t next_pid) {
+ uint32_t,
+ uint32_t next_pid,
+ base::StringView next_comm) {
// At this stage all events should be globally timestamp ordered.
if (timestamp < prev_timestamp_) {
PERFETTO_ELOG("sched_switch event out of order by %.4f ms, skipping",
@@ -44,31 +48,29 @@
}
prev_timestamp_ = timestamp;
PERFETTO_DCHECK(cpu < base::kMaxCpus);
- SchedSwitchEvent* prev = &last_sched_per_cpu_[cpu];
- // If we had a valid previous event, then inform the storage about the
- // slice.
- if (prev->valid()) {
- uint64_t duration = timestamp - prev->timestamp;
- StringId prev_thread_name_id =
- prev->next_pid == 0 ? idle_string_id_
- : context_->storage->InternString(prev_comm);
- UniqueTid utid = context_->process_tracker->UpdateThread(
- prev->timestamp, prev->next_pid /* == prev_pid */, prev_thread_name_id);
- context_->storage->AddSliceToCpu(cpu, prev->timestamp, duration, utid);
+
+ auto* slices = context_->storage->mutable_slices();
+ auto* pending_slice = &pending_sched_per_cpu_[cpu];
+ if (pending_slice->storage_index < std::numeric_limits<size_t>::max()) {
+ // If the this events previous pid does not match the previous event's next
+ // pid, make a note of this.
+ if (prev_pid != pending_slice->pid) {
+ context_->storage->AddMismatchedSchedSwitch();
+ }
+
+ size_t idx = pending_slice->storage_index;
+ uint64_t duration = timestamp - slices->start_ns()[idx];
+ slices->set_duration(idx, duration);
}
- // If the this events previous pid does not match the previous event's next
- // pid, make a note of this.
- if (prev_pid != prev->next_pid) {
- context_->storage->AddMismatchedSchedSwitch();
- }
+ StringId name_id = GetThreadNameId(next_pid, next_comm);
+ auto utid =
+ context_->process_tracker->UpdateThread(timestamp, next_pid, name_id);
- // Update the map with the current event.
- prev->timestamp = timestamp;
- prev->prev_pid = prev_pid;
- prev->prev_state = prev_state;
- prev->next_pid = next_pid;
-};
+ pending_slice->storage_index =
+ slices->AddSlice(cpu, timestamp, 0 /* duration */, utid);
+ pending_slice->pid = next_pid;
+}
void SchedTracker::PushCounter(uint64_t timestamp,
double value,
@@ -82,24 +84,22 @@
}
prev_timestamp_ = timestamp;
- // The previous counter with the same ref and name_id.
- Counter& prev = prev_counters_[CounterKey{ref, name_id}];
+ auto* counters = context_->storage->mutable_counters();
+ const auto& key = CounterKey{ref, name_id};
+ auto counter_it = pending_counters_per_key_.find(key);
+ if (counter_it != pending_counters_per_key_.end()) {
+ size_t idx = counter_it->second;
- uint64_t duration = 0;
- double value_delta = 0;
-
- if (prev.timestamp != 0) {
- duration = timestamp - prev.timestamp;
- value_delta = value - prev.value;
-
- context_->storage->mutable_counters()->AddCounter(
- prev.timestamp, duration, name_id, prev.value, value_delta,
- static_cast<int64_t>(ref), ref_type);
+ uint64_t duration = timestamp - counters->timestamps()[idx];
+ double value_delta = value - counters->values()[idx];
+ counters->set_duration(idx, duration);
+ counters->set_value_delta(idx, value_delta);
}
- prev.timestamp = timestamp;
- prev.value = value;
-};
+ pending_counters_per_key_[key] = counters->AddCounter(
+ timestamp, 0 /* duration */, name_id, value, 0 /* value_delta */,
+ static_cast<int64_t>(ref), ref_type);
+}
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/sched_tracker.h b/src/trace_processor/sched_tracker.h
index b2c5791..3679240 100644
--- a/src/trace_processor/sched_tracker.h
+++ b/src/trace_processor/sched_tracker.h
@@ -18,6 +18,7 @@
#define SRC_TRACE_PROCESSOR_SCHED_TRACKER_H_
#include <array>
+#include <limits>
#include "perfetto/base/string_view.h"
#include "perfetto/base/utils.h"
@@ -37,23 +38,25 @@
SchedTracker& operator=(const SchedTracker&) = delete;
virtual ~SchedTracker();
- struct SchedSwitchEvent {
- uint64_t timestamp = 0;
- uint32_t prev_pid = 0;
- uint32_t prev_state = 0;
- uint32_t next_pid = 0;
+ StringId GetThreadNameId(uint32_t tid, base::StringView comm);
- bool valid() const { return timestamp != 0; }
- };
+ // This method is called when a sched switch event is seen in the trace.
+ virtual void PushSchedSwitch(uint32_t cpu,
+ uint64_t timestamp,
+ uint32_t prev_pid,
+ uint32_t prev_state,
+ uint32_t next_pid,
+ base::StringView next_comm);
- // A Counter is a trace event that has a value attached to a timestamp.
- // These include CPU frequency ftrace events and systrace trace_marker
- // counter events.
- struct Counter {
- uint64_t timestamp = 0;
- double value = 0;
- };
+ // This method is called when a cpu freq event is seen in the trace.
+ // TODO(taylori): Move to a more appropriate class or rename class.
+ virtual void PushCounter(uint64_t timestamp,
+ double value,
+ StringId name_id,
+ uint64_t ref,
+ RefType ref_type);
+ private:
// Used as the key in |prev_counters_| to find the previous counter with the
// same ref and name_id.
struct CounterKey {
@@ -73,29 +76,18 @@
};
};
- // This method is called when a sched switch event is seen in the trace.
- virtual void PushSchedSwitch(uint32_t cpu,
- uint64_t timestamp,
- uint32_t prev_pid,
- uint32_t prev_state,
- base::StringView prev_comm,
- uint32_t next_pid);
+ // Represents a slice which is currently pending.
+ struct PendingSchedSlice {
+ size_t storage_index = std::numeric_limits<size_t>::max();
+ uint32_t pid = 0;
+ };
- // This method is called when a cpu freq event is seen in the trace.
- // TODO(taylori): Move to a more appropriate class or rename class.
- virtual void PushCounter(uint64_t timestamp,
- double value,
- StringId name_id,
- uint64_t ref,
- RefType ref_type);
+ // Store pending sched slices for each CPU.
+ std::array<PendingSchedSlice, base::kMaxCpus> pending_sched_per_cpu_{};
- private:
- // Store the previous sched event to calculate the duration before storing it.
- std::array<SchedSwitchEvent, base::kMaxCpus> last_sched_per_cpu_;
-
- // Store the previous counter event to calculate the duration and value delta
- // before storing it in trace storage.
- std::unordered_map<CounterKey, Counter, CounterKey::Hasher> prev_counters_;
+ // Store pending counters for each counter key.
+ std::unordered_map<CounterKey, size_t, CounterKey::Hasher>
+ pending_counters_per_key_;
// Timestamp of the previous event. Used to discard events arriving out
// of order.
diff --git a/src/trace_processor/sched_tracker_unittest.cc b/src/trace_processor/sched_tracker_unittest.cc
index a8a70c3..863052e 100644
--- a/src/trace_processor/sched_tracker_unittest.cc
+++ b/src/trace_processor/sched_tracker_unittest.cc
@@ -51,18 +51,18 @@
const auto& timestamps = context.storage->slices().start_ns();
context.sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, prev_state,
- kCommProc1, pid_2);
- ASSERT_EQ(timestamps.size(), 0);
+ pid_2, kCommProc1);
+ ASSERT_EQ(timestamps.size(), 1);
context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, pid_2, prev_state,
- kCommProc2, pid_1);
+ pid_1, kCommProc2);
- ASSERT_EQ(timestamps.size(), 1ul);
+ ASSERT_EQ(timestamps.size(), 2ul);
ASSERT_EQ(timestamps[0], timestamp);
ASSERT_EQ(context.storage->GetThread(1).start_ns, timestamp);
ASSERT_EQ(std::string(context.storage->GetString(
context.storage->GetThread(1).name_id)),
- kCommProc2);
+ kCommProc1);
ASSERT_EQ(context.storage->slices().utids().front(), 1);
}
@@ -75,21 +75,20 @@
const auto& timestamps = context.storage->slices().start_ns();
context.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/4, prev_state,
- kCommProc1,
- /*tid=*/2);
- ASSERT_EQ(timestamps.size(), 0);
+ /*tid=*/2, kCommProc1);
+ ASSERT_EQ(timestamps.size(), 1);
context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/2,
- prev_state, kCommProc1,
- /*tid=*/4);
+ prev_state,
+ /*tid=*/4, kCommProc1);
context.sched_tracker->PushSchedSwitch(cpu, timestamp + 11, /*tid=*/4,
- prev_state, kCommProc2,
- /*tid=*/2);
+ prev_state,
+ /*tid=*/2, kCommProc2);
context.sched_tracker->PushSchedSwitch(cpu, timestamp + 31, /*tid=*/4,
- prev_state, kCommProc1,
- /*tid=*/2);
+ prev_state,
+ /*tid=*/2, kCommProc1);
- ASSERT_EQ(timestamps.size(), 3ul);
+ ASSERT_EQ(timestamps.size(), 4ul);
ASSERT_EQ(timestamps[0], timestamp);
ASSERT_EQ(context.storage->GetThread(1).start_ns, timestamp);
ASSERT_EQ(context.storage->slices().durations().at(0), 1u);
@@ -112,7 +111,7 @@
context.sched_tracker->PushCounter(timestamp + 9, 1000, name_id, cpu,
RefType::kCPU_ID);
- ASSERT_EQ(context.storage->counters().counter_count(), 3ul);
+ ASSERT_EQ(context.storage->counters().counter_count(), 4ul);
ASSERT_EQ(context.storage->counters().timestamps().at(0), timestamp);
ASSERT_EQ(context.storage->counters().durations().at(0), 1);
ASSERT_EQ(context.storage->counters().values().at(0), 1000);
@@ -141,7 +140,7 @@
context.sched_tracker->PushCounter(timestamp + 9, 1, name_id_upid, upid,
RefType::kUTID);
- ASSERT_EQ(context.storage->counters().counter_count(), 2ul);
+ ASSERT_EQ(context.storage->counters().counter_count(), 4ul);
ASSERT_EQ(context.storage->counters().timestamps().at(0), timestamp);
ASSERT_EQ(context.storage->counters().durations().at(0), 3);
ASSERT_EQ(context.storage->counters().values().at(0), 1000);
diff --git a/src/trace_processor/thread_table_unittest.cc b/src/trace_processor/thread_table_unittest.cc
index 49c0efc..10e1622 100644
--- a/src/trace_processor/thread_table_unittest.cc
+++ b/src/trace_processor/thread_table_unittest.cc
@@ -71,9 +71,9 @@
static const char kThreadName2[] = "thread2";
context_.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, prev_state,
- kThreadName1, /*tid=*/4);
+ /*tid=*/4, kThreadName1);
context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
- prev_state, kThreadName2, /*tid=*/1);
+ prev_state, /*tid=*/1, kThreadName2);
context_.process_tracker->UpdateProcess(2, "test");
context_.process_tracker->UpdateThread(4 /*tid*/, 2 /*pid*/);
@@ -83,7 +83,7 @@
ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 1 /* utid */);
ASSERT_EQ(sqlite3_column_int(*stmt_, 1), 1 /* upid */);
ASSERT_EQ(sqlite3_column_int(*stmt_, 2), 4 /* tid */);
- ASSERT_STREQ(GetColumnAsText(3), kThreadName2);
+ ASSERT_STREQ(GetColumnAsText(3), kThreadName1);
ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
}
@@ -96,13 +96,12 @@
static const char kThreadName2[] = "thread2";
context_.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, prev_state,
- kThreadName1,
- /*tid=*/4);
+ /*tid=*/4, kThreadName1);
context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
- prev_state, kThreadName2,
- /*tid=*/1);
+ prev_state,
+ /*tid=*/1, kThreadName2);
context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 2, /*tid=*/1,
- prev_state, kThreadName1, /*tid=*/4);
+ prev_state, /*tid=*/4, kThreadName1);
context_.process_tracker->UpdateProcess(2, "test");
context_.process_tracker->UpdateThread(4 /*tid*/, 2 /*pid*/);
@@ -114,7 +113,7 @@
ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 1 /* utid */);
ASSERT_EQ(sqlite3_column_int(*stmt_, 1), 1 /* upid */);
ASSERT_EQ(sqlite3_column_int(*stmt_, 2), 4 /* tid */);
- ASSERT_STREQ(GetColumnAsText(3), kThreadName2);
+ ASSERT_STREQ(GetColumnAsText(3), kThreadName1);
ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
}
@@ -127,13 +126,10 @@
static const char kThreadName2[] = "thread2";
context_.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, prev_state,
- kThreadName1,
-
- /*tid=*/4);
+ /*tid=*/4, kThreadName1);
context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
- prev_state, kThreadName2,
-
- /*tid=*/1);
+ prev_state,
+ /*tid=*/1, kThreadName2);
// Also create a process for which we haven't seen any thread.
context_.process_tracker->UpdateProcess(7, "pid7");
@@ -166,7 +162,7 @@
ASSERT_EQ(sqlite3_column_int(*stmt_, 1), 4 /* tid */);
ASSERT_EQ(sqlite3_column_int(*stmt_, 4), 2 /* pid */);
ASSERT_EQ(sqlite3_column_int(*stmt_, 3), 2 /* upid */);
- ASSERT_STREQ(GetColumnAsText(2), kThreadName2);
+ ASSERT_STREQ(GetColumnAsText(2), kThreadName1);
ASSERT_STREQ(GetColumnAsText(5), "pid2");
ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
diff --git a/src/trace_processor/trace_database_integrationtest.cc b/src/trace_processor/trace_database_integrationtest.cc
index f191161..d6bf701 100644
--- a/src/trace_processor/trace_database_integrationtest.cc
+++ b/src/trace_processor/trace_database_integrationtest.cc
@@ -66,7 +66,10 @@
TEST_F(TraceProcessorIntegrationTest, AndroidSchedAndPs) {
ASSERT_TRUE(LoadTrace("android_sched_and_ps.pb"));
protos::RawQueryResult res;
- Query("select count(*), max(ts) - min(ts) from sched where utid != 0", &res);
+ Query(
+ "select count(*), max(ts) - min(ts) from sched "
+ "where dur != 0 and utid != 0",
+ &res);
ASSERT_EQ(res.num_records(), 1);
ASSERT_EQ(res.columns(0).long_values(0), 139789);
ASSERT_EQ(res.columns(1).long_values(0), 19684308497);
diff --git a/src/trace_processor/trace_storage.cc b/src/trace_processor/trace_storage.cc
index 4443af0..e219c67 100644
--- a/src/trace_processor/trace_storage.cc
+++ b/src/trace_processor/trace_storage.cc
@@ -33,13 +33,6 @@
TraceStorage::~TraceStorage() {}
-void TraceStorage::AddSliceToCpu(uint32_t cpu,
- uint64_t start_ns,
- uint64_t duration_ns,
- UniqueTid utid) {
- slices_.AddSlice(cpu, start_ns, duration_ns, utid);
-}
-
StringId TraceStorage::InternString(base::StringView str) {
auto hash = str.Hash();
auto id_it = string_index_.find(hash);
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 9a86cf4..eef8094 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -80,14 +80,19 @@
class Slices {
public:
- inline void AddSlice(uint32_t cpu,
- uint64_t start_ns,
- uint64_t duration_ns,
- UniqueTid utid) {
+ inline size_t AddSlice(uint32_t cpu,
+ uint64_t start_ns,
+ uint64_t duration_ns,
+ UniqueTid utid) {
cpus_.emplace_back(cpu);
start_ns_.emplace_back(start_ns);
durations_.emplace_back(duration_ns);
utids_.emplace_back(utid);
+ return slice_count() - 1;
+ }
+
+ void set_duration(size_t index, uint64_t duration_ns) {
+ durations_[index] = duration_ns;
}
size_t slice_count() const { return start_ns_.size(); }
@@ -154,13 +159,13 @@
class Counters {
public:
- inline void AddCounter(uint64_t timestamp,
- uint64_t duration,
- StringId name_id,
- double value,
- double value_delta,
- int64_t ref,
- RefType type) {
+ inline size_t AddCounter(uint64_t timestamp,
+ uint64_t duration,
+ StringId name_id,
+ double value,
+ double value_delta,
+ int64_t ref,
+ RefType type) {
timestamps_.emplace_back(timestamp);
durations_.emplace_back(duration);
name_ids_.emplace_back(name_id);
@@ -168,7 +173,17 @@
value_deltas_.emplace_back(value_delta);
refs_.emplace_back(ref);
types_.emplace_back(type);
+ return counter_count() - 1;
}
+
+ void set_duration(size_t index, uint64_t duration) {
+ durations_[index] = duration;
+ }
+
+ void set_value_delta(size_t index, double value_delta) {
+ value_deltas_[index] = value_delta;
+ }
+
size_t counter_count() const { return timestamps_.size(); }
const std::deque<uint64_t>& timestamps() const { return timestamps_; }
@@ -197,11 +212,6 @@
void ResetStorage();
- void AddSliceToCpu(uint32_t cpu,
- uint64_t start_ns,
- uint64_t duration_ns,
- UniqueTid utid);
-
UniqueTid AddEmptyThread(uint32_t tid) {
unique_threads_.emplace_back(tid);
return static_cast<UniqueTid>(unique_threads_.size() - 1);
@@ -247,6 +257,8 @@
}
const Slices& slices() const { return slices_; }
+ Slices* mutable_slices() { return &slices_; }
+
const NestableSlices& nestable_slices() const { return nestable_slices_; }
NestableSlices* mutable_nestable_slices() { return &nestable_slices_; }