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_; }