Add StringView class and switch trace processor to use it

In the TraceProcessor most of the strings derived from
protos are not terminated. Instead of passing a pointer and
a length, just pass a StringView.

Test: perfetto_unittests --gtest_filter=StringViewTest.*
Change-Id: Ibd44f54b921fb0960e6cd06b89d625a0402757e3
diff --git a/Android.bp b/Android.bp
index 71bfd05..aae56a8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3659,6 +3659,7 @@
     "src/base/string_splitter_unittest.cc",
     "src/base/string_utils.cc",
     "src/base/string_utils_unittest.cc",
+    "src/base/string_view_unittest.cc",
     "src/base/task_runner_unittest.cc",
     "src/base/temp_file.cc",
     "src/base/temp_file_unittest.cc",
diff --git a/include/perfetto/base/BUILD.gn b/include/perfetto/base/BUILD.gn
index ae08e9b..ea5fa38 100644
--- a/include/perfetto/base/BUILD.gn
+++ b/include/perfetto/base/BUILD.gn
@@ -24,6 +24,7 @@
     "small_set.h",
     "string_splitter.h",
     "string_utils.h",
+    "string_view.h",
     "task_runner.h",
     "temp_file.h",
     "thread_checker.h",
diff --git a/include/perfetto/base/string_view.h b/include/perfetto/base/string_view.h
new file mode 100644
index 0000000..2c42e91
--- /dev/null
+++ b/include/perfetto/base/string_view.h
@@ -0,0 +1,91 @@
+/*
+ * 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_STRING_VIEW_H_
+#define INCLUDE_PERFETTO_BASE_STRING_VIEW_H_
+
+#include <string.h>
+
+#include <string>
+
+namespace perfetto {
+namespace base {
+
+// A string-like object that refers to a non-owned piece of memory.
+// Strings are internally NOT null terminated.
+class StringView {
+ public:
+  StringView() : data_(""), size_(0) {}
+  StringView(const StringView&) = default;
+  StringView& operator=(const StringView&) = default;
+  StringView(const char* data, size_t size) : data_(data), size_(size) {}
+
+  // Creates a StringView from a null-terminated C string.
+  // Deliberately not "explicit".
+  StringView(const char* cstr) : data_(cstr), size_(strlen(cstr)) {}
+
+  // This instead has to be explicit, as creating a StringView out of a
+  // std::string can be subtle.
+  explicit StringView(const std::string& str)
+      : data_(str.data()), size_(str.size()) {}
+
+  bool empty() const { return size_ == 0; }
+  size_t size() const { return size_; }
+  const char* data() const { return data_; }
+
+  std::string ToStdString() const { return std::string(data_, size_); }
+
+  uint64_t Hash() const {
+    if (size_ == 0)
+      return 0;
+    uint64_t hash = 0xcbf29ce484222325;  // FNV-1a-64 offset basis.
+    for (size_t i = 0; i < size_; ++i) {
+      hash ^= static_cast<decltype(hash)>(data_[i]);
+      hash *= 1099511628211;  // FNV-1a-64 prime.
+    }
+    return hash;
+  }
+
+ private:
+  const char* data_ = nullptr;
+  size_t size_ = 0;
+};
+
+inline bool operator==(const StringView& x, const StringView& y) {
+  if (x.size() != y.size())
+    return false;
+  return memcmp(x.data(), y.data(), x.size()) == 0;
+}
+
+inline bool operator!=(const StringView& x, const StringView& y) {
+  return !(x == y);
+}
+
+}  // namespace base
+}  // namespace perfetto
+
+namespace std {
+
+template <>
+struct hash<::perfetto::base::StringView> {
+  size_t operator()(const ::perfetto::base::StringView& sv) const {
+    return static_cast<size_t>(sv.Hash());
+  }
+};
+
+}  // namespace std
+
+#endif  // INCLUDE_PERFETTO_BASE_STRING_VIEW_H_
diff --git a/include/perfetto/protozero/proto_decoder.h b/include/perfetto/protozero/proto_decoder.h
index fccef59..077f4c8 100644
--- a/include/perfetto/protozero/proto_decoder.h
+++ b/include/perfetto/protozero/proto_decoder.h
@@ -21,6 +21,7 @@
 #include <memory>
 
 #include "perfetto/base/logging.h"
+#include "perfetto/base/string_view.h"
 #include "perfetto/protozero/proto_utils.h"
 
 namespace protozero {
@@ -30,6 +31,8 @@
 // performance sensitive contexts.
 class ProtoDecoder {
  public:
+  using StringView = ::perfetto::base::StringView;
+
   // The field of a protobuf message. |id| == 0 if the tag is not valid (e.g.
   // because the full tag was unable to be read etc.).
   struct Field {
@@ -51,10 +54,11 @@
       return static_cast<uint32_t>(int_value);
     }
 
-    inline const char* as_char_ptr() const {
+    inline StringView as_string() const {
       PERFETTO_DCHECK(type ==
                       proto_utils::FieldType::kFieldTypeLengthDelimited);
-      return reinterpret_cast<const char*>(length_limited.data);
+      return StringView(reinterpret_cast<const char*>(length_limited.data),
+                        length_limited.length);
     }
 
     inline const uint8_t* data() const {
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index e51aaa5..80f9f00 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -128,6 +128,7 @@
     "scoped_file_unittest.cc",
     "string_splitter_unittest.cc",
     "string_utils_unittest.cc",
+    "string_view_unittest.cc",
     "time_unittest.cc",
     "weak_ptr_unittest.cc",
   ]
diff --git a/src/base/string_view_unittest.cc b/src/base/string_view_unittest.cc
new file mode 100644
index 0000000..b9e97b4
--- /dev/null
+++ b/src/base/string_view_unittest.cc
@@ -0,0 +1,92 @@
+/*
+ * 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 "perfetto/base/string_view.h"
+
+#include <forward_list>
+#include <unordered_map>
+#include <unordered_set>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace perfetto {
+namespace base {
+namespace {
+
+TEST(StringViewTest, BasicCases) {
+  EXPECT_EQ(StringView(""), StringView(""));
+  EXPECT_EQ(StringView(""), StringView("", 0));
+  EXPECT_EQ(StringView("ab"), StringView("ab", 2));
+  EXPECT_EQ(StringView("ax", 1), StringView("ay", 1));
+  EXPECT_EQ(StringView("ax", 1), StringView("a"));
+  EXPECT_EQ(StringView("ax", 1), "a");
+  EXPECT_EQ(StringView("foo|", 3).ToStdString(), std::string("foo"));
+  EXPECT_TRUE(StringView("x") != StringView(""));
+  EXPECT_TRUE(StringView("") != StringView("y"));
+  EXPECT_TRUE(StringView("a") != StringView("b"));
+  EXPECT_EQ(StringView("").size(), 0);
+  EXPECT_NE(StringView("").data(), nullptr);
+  EXPECT_TRUE(StringView("").empty());
+  EXPECT_FALSE(StringView("x").empty());
+
+  {
+    StringView x("abc");
+    EXPECT_EQ(x.size(), 3u);
+    EXPECT_EQ(x.data()[0], 'a');
+    EXPECT_EQ(x.data()[2], 'c');
+    EXPECT_TRUE(x == "abc");
+    EXPECT_TRUE(x == StringView("abc"));
+    EXPECT_TRUE(x != StringView("abcd"));
+  }
+}
+
+TEST(StringViewTest, HashCollisions) {
+  std::unordered_map<uint64_t, StringView> hashes;
+  std::unordered_set<StringView> sv_set;
+  auto insert_sv = [&hashes, &sv_set](StringView sv) {
+    hashes.emplace(sv.Hash(), sv);
+    size_t prev_set_size = sv_set.size();
+    sv_set.insert(sv);
+    ASSERT_EQ(sv_set.size(), prev_set_size + 1);
+  };
+
+  insert_sv("");
+  EXPECT_EQ(hashes.size(), 1u);
+  size_t last_size = 1;
+  std::forward_list<std::string> strings;
+  for (uint8_t c = 0; c < 0x80; c++) {
+    char buf[500];
+    memset(buf, static_cast<char>(c), sizeof(buf));
+    for (size_t i = 1; i <= sizeof(buf); i++) {
+      strings.emplace_front(buf, i);
+      StringView sv(strings.front());
+      auto other = hashes.find(sv.Hash());
+      if (other == hashes.end()) {
+        insert_sv(sv);
+        ++last_size;
+        ASSERT_EQ(hashes.size(), last_size);
+        continue;
+      }
+      EXPECT_TRUE(false) << "H(" << sv.ToStdString() << ") = "
+                         << "H(" << other->second.ToStdString() << ")";
+    }
+  }
+}
+
+}  // namespace
+}  // namespace base
+}  // namespace perfetto
diff --git a/src/trace_processor/json_trace_parser.cc b/src/trace_processor/json_trace_parser.cc
index 66d204c..ccbb838 100644
--- a/src/trace_processor/json_trace_parser.cc
+++ b/src/trace_processor/json_trace_parser.cc
@@ -127,8 +127,8 @@
     uint64_t ts = value["ts"].asLargestUInt() * 1000;
     const char* cat = value["cat"].asCString();
     const char* name = value["name"].asCString();
-    StringId cat_id = storage->InternString(cat, strlen(cat));
-    StringId name_id = storage->InternString(name, strlen(name));
+    StringId cat_id = storage->InternString(cat);
+    StringId name_id = storage->InternString(name);
     UniqueTid utid = procs->UpdateThread(tid, pid);
     SlicesStack& stack = threads_[utid];
 
@@ -171,12 +171,12 @@
       case 'M': {  // Metadata events (process and thread names).
         if (strcmp(value["name"].asCString(), "thread_name") == 0) {
           const char* thread_name = value["args"]["name"].asCString();
-          procs->UpdateThreadName(tid, pid, thread_name, strlen(thread_name));
+          procs->UpdateThreadName(tid, pid, thread_name);
           break;
         }
         if (strcmp(value["name"].asCString(), "process_name") == 0) {
           const char* proc_name = value["args"]["name"].asCString();
-          procs->UpdateProcess(pid, proc_name, strlen(proc_name));
+          procs->UpdateProcess(pid, proc_name);
           break;
         }
       }
diff --git a/src/trace_processor/process_table_unittest.cc b/src/trace_processor/process_table_unittest.cc
index 1ecd984..cab6a67 100644
--- a/src/trace_processor/process_table_unittest.cc
+++ b/src/trace_processor/process_table_unittest.cc
@@ -64,8 +64,8 @@
 TEST_F(ProcessTableUnittest, SelectUpidAndName) {
   static const char kCommProc1[] = "process1";
   static const char kCommProc2[] = "process2";
-  context_.process_tracker->UpdateProcess(1, kCommProc1, 8);
-  context_.process_tracker->UpdateProcess(2, kCommProc2, 8);
+  context_.process_tracker->UpdateProcess(1, kCommProc1);
+  context_.process_tracker->UpdateProcess(2, kCommProc2);
 
   PrepareValidStatement("SELECT upid, name FROM process");
 
@@ -83,8 +83,8 @@
 TEST_F(ProcessTableUnittest, SelectUpidAndNameWithFilter) {
   static const char kCommProc1[] = "process1";
   static const char kCommProc2[] = "process2";
-  context_.process_tracker->UpdateProcess(1, kCommProc1, 8);
-  context_.process_tracker->UpdateProcess(2, kCommProc2, 8);
+  context_.process_tracker->UpdateProcess(1, kCommProc1);
+  context_.process_tracker->UpdateProcess(2, kCommProc2);
 
   PrepareValidStatement("SELECT upid, name FROM process where upid = 2");
 
@@ -98,8 +98,8 @@
 TEST_F(ProcessTableUnittest, SelectUpidAndNameWithOrder) {
   static const char kCommProc1[] = "process1";
   static const char kCommProc2[] = "process2";
-  context_.process_tracker->UpdateProcess(1, kCommProc1, 8);
-  context_.process_tracker->UpdateProcess(2, kCommProc2, 8);
+  context_.process_tracker->UpdateProcess(1, kCommProc1);
+  context_.process_tracker->UpdateProcess(2, kCommProc2);
 
   PrepareValidStatement("SELECT upid, name FROM process ORDER BY upid desc");
 
@@ -117,8 +117,8 @@
 TEST_F(ProcessTableUnittest, SelectUpidAndNameFilterGt) {
   static const char kCommProc1[] = "process1";
   static const char kCommProc2[] = "process2";
-  context_.process_tracker->UpdateProcess(1, kCommProc1, 8);
-  context_.process_tracker->UpdateProcess(2, kCommProc2, 8);
+  context_.process_tracker->UpdateProcess(1, kCommProc1);
+  context_.process_tracker->UpdateProcess(2, kCommProc2);
 
   PrepareValidStatement("SELECT upid, name FROM process where upid > 1");
 
@@ -132,8 +132,8 @@
 TEST_F(ProcessTableUnittest, SelectUpidAndNameFilterName) {
   static const char kCommProc1[] = "process1";
   static const char kCommProc2[] = "process2";
-  context_.process_tracker->UpdateProcess(1, kCommProc1, 8);
-  context_.process_tracker->UpdateProcess(2, kCommProc2, 8);
+  context_.process_tracker->UpdateProcess(1, kCommProc1);
+  context_.process_tracker->UpdateProcess(2, kCommProc2);
 
   PrepareValidStatement(
       "SELECT upid, name FROM process where name = \"process2\"");
@@ -148,8 +148,8 @@
 TEST_F(ProcessTableUnittest, SelectUpidAndNameFilterDifferentOr) {
   static const char kCommProc1[] = "process1";
   static const char kCommProc2[] = "process2";
-  context_.process_tracker->UpdateProcess(1, kCommProc1, 8);
-  context_.process_tracker->UpdateProcess(2, kCommProc2, 8);
+  context_.process_tracker->UpdateProcess(1, kCommProc1);
+  context_.process_tracker->UpdateProcess(2, kCommProc2);
 
   PrepareValidStatement(
       "SELECT upid, name FROM process where upid = 2 or name = \"process2\"");
@@ -164,8 +164,8 @@
 TEST_F(ProcessTableUnittest, SelectUpidAndNameFilterSameOr) {
   static const char kCommProc1[] = "process1";
   static const char kCommProc2[] = "process2";
-  context_.process_tracker->UpdateProcess(1, kCommProc1, 8);
-  context_.process_tracker->UpdateProcess(2, kCommProc2, 8);
+  context_.process_tracker->UpdateProcess(1, kCommProc1);
+  context_.process_tracker->UpdateProcess(2, kCommProc2);
 
   PrepareValidStatement(
       "SELECT upid, name FROM process where upid = 1 or upid = 2");
diff --git a/src/trace_processor/process_tracker.cc b/src/trace_processor/process_tracker.cc
index ff76da7..fc10f26 100644
--- a/src/trace_processor/process_tracker.cc
+++ b/src/trace_processor/process_tracker.cc
@@ -54,11 +54,10 @@
 
 void ProcessTracker::UpdateThreadName(uint32_t tid,
                                       uint32_t pid,
-                                      const char* name,
-                                      size_t name_len) {
+                                      base::StringView name) {
   UniqueTid utid = UpdateThread(tid, pid);
   auto* thread = context_->storage->GetMutableThread(utid);
-  auto name_id = context_->storage->InternString(name, name_len);
+  auto name_id = context_->storage->InternString(name);
   thread->name_id = name_id;
 }
 
@@ -103,11 +102,8 @@
   return utid;
 }
 
-UniquePid ProcessTracker::UpdateProcess(uint32_t pid,
-                                        const char* process_name,
-                                        size_t process_name_len) {
-  auto proc_name_id =
-      context_->storage->InternString(process_name, process_name_len);
+UniquePid ProcessTracker::UpdateProcess(uint32_t pid, base::StringView name) {
+  auto proc_name_id = context_->storage->InternString(name);
   UniquePid upid;
   TraceStorage::Process* process;
   std::tie(upid, process) = GetOrCreateProcess(pid, 0 /* start_ns */);
@@ -142,9 +138,10 @@
   // because of the ring buffer wrapping over).
   if (process->name_id == 0) {
     char process_name[64];
-    int len = sprintf(process_name, "[pid:%" PRIu32 "]", pid);
+    size_t len =
+        static_cast<size_t>(sprintf(process_name, "[pid:%" PRIu32 "]", pid));
     process->name_id =
-        context_->storage->InternString(process_name, static_cast<size_t>(len));
+        context_->storage->InternString(base::StringView(process_name, len));
   }
 
   return std::make_tuple(upid, process);
diff --git a/src/trace_processor/process_tracker.h b/src/trace_processor/process_tracker.h
index 38ae285..5bd4d2b 100644
--- a/src/trace_processor/process_tracker.h
+++ b/src/trace_processor/process_tracker.h
@@ -19,6 +19,7 @@
 
 #include <tuple>
 
+#include "perfetto/base/string_view.h"
 #include "src/trace_processor/trace_processor_context.h"
 #include "src/trace_processor/trace_storage.h"
 
@@ -59,17 +60,12 @@
   virtual UniqueTid UpdateThread(uint32_t tid, uint32_t tgid);
 
   // Sets the name of the thread identified by the tuple (tid,pid).
-  void UpdateThreadName(uint32_t tid,
-                        uint32_t pid,
-                        const char* name,
-                        size_t name_len);
+  void UpdateThreadName(uint32_t tid, uint32_t pid, base::StringView name);
 
   // Called when a process is seen in a process tree. Retrieves the UniquePid
   // for that pid or assigns a new one.
   // Virtual for testing.
-  virtual UniquePid UpdateProcess(uint32_t pid,
-                                  const char* process_name,
-                                  size_t process_name_len);
+  virtual UniquePid UpdateProcess(uint32_t pid, base::StringView name);
 
   // Returns the bounds of a range that includes all UniquePids that have the
   // requested pid.
diff --git a/src/trace_processor/process_tracker_unittest.cc b/src/trace_processor/process_tracker_unittest.cc
index 2e0b1dd..3db0e57 100644
--- a/src/trace_processor/process_tracker_unittest.cc
+++ b/src/trace_processor/process_tracker_unittest.cc
@@ -43,22 +43,22 @@
 
 TEST_F(ProcessTrackerTest, PushProcess) {
   TraceStorage storage;
-  context.process_tracker->UpdateProcess(1, "test", 4);
+  context.process_tracker->UpdateProcess(1, "test");
   auto pair_it = context.process_tracker->UpidsForPid(1);
   ASSERT_EQ(pair_it.first->second, 1);
 }
 
 TEST_F(ProcessTrackerTest, PushTwoProcessEntries_SamePidAndName) {
-  context.process_tracker->UpdateProcess(1, "test", 4);
-  context.process_tracker->UpdateProcess(1, "test", 4);
+  context.process_tracker->UpdateProcess(1, "test");
+  context.process_tracker->UpdateProcess(1, "test");
   auto pair_it = context.process_tracker->UpidsForPid(1);
   ASSERT_EQ(pair_it.first->second, 1);
   ASSERT_EQ(++pair_it.first, pair_it.second);
 }
 
 TEST_F(ProcessTrackerTest, PushTwoProcessEntries_DifferentPid) {
-  context.process_tracker->UpdateProcess(1, "test", 4);
-  context.process_tracker->UpdateProcess(3, "test", 4);
+  context.process_tracker->UpdateProcess(1, "test");
+  context.process_tracker->UpdateProcess(3, "test");
   auto pair_it = context.process_tracker->UpidsForPid(1);
   ASSERT_EQ(pair_it.first->second, 1);
   auto second_pair_it = context.process_tracker->UpidsForPid(3);
@@ -66,7 +66,7 @@
 }
 
 TEST_F(ProcessTrackerTest, AddProcessEntry_CorrectName) {
-  context.process_tracker->UpdateProcess(1, "test", 4);
+  context.process_tracker->UpdateProcess(1, "test");
   ASSERT_EQ(context.storage->GetString(context.storage->GetProcess(1).name_id),
             "test");
 }
@@ -79,14 +79,14 @@
   static const char kCommProc2[] = "process2";
 
   context.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, prev_state,
-                                         kCommProc1, sizeof(kCommProc1) - 1,
+                                         kCommProc1,
                                          /*tid=*/4);
   context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
                                          prev_state, kCommProc2,
-                                         sizeof(kCommProc2) - 1,
+
                                          /*tid=*/1);
 
-  context.process_tracker->UpdateProcess(2, "test", strlen("test"));
+  context.process_tracker->UpdateProcess(2, "test");
   context.process_tracker->UpdateThread(4, 2);
 
   TraceStorage::Thread thread = context.storage->GetThread(/*utid=*/1);
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
index 96472ce..f11ccc0 100644
--- a/src/trace_processor/proto_trace_parser.cc
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -19,6 +19,7 @@
 #include <string>
 
 #include "perfetto/base/logging.h"
+#include "perfetto/base/string_view.h"
 #include "perfetto/base/utils.h"
 #include "perfetto/protozero/proto_decoder.h"
 #include "src/trace_processor/blob_reader.h"
@@ -136,24 +137,21 @@
 void ProtoTraceParser::ParseProcess(const uint8_t* data, size_t length) {
   ProtoDecoder decoder(data, length);
   uint32_t pid = 0;
-  const char* process_name = nullptr;
-  size_t process_name_len = 0;
+  base::StringView process_name;
   for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
     switch (fld.id) {
       case protos::ProcessTree::Process::kPidFieldNumber:
         pid = fld.as_uint32();
         break;
       case protos::ProcessTree::Process::kCmdlineFieldNumber:
-        if (process_name == nullptr) {
-          process_name = fld.as_char_ptr();
-          process_name_len = fld.size();
-        }
+        if (process_name.empty())
+          process_name = fld.as_string();
         break;
       default:
         break;
     }
   }
-  context_->process_tracker->UpdateProcess(pid, process_name, process_name_len);
+  context_->process_tracker->UpdateProcess(pid, process_name);
 
   PERFETTO_DCHECK(decoder.IsEndOfBuffer());
 }
@@ -214,8 +212,7 @@
 
   uint32_t prev_pid = 0;
   uint32_t prev_state = 0;
-  const char* prev_comm = nullptr;
-  size_t prev_comm_len = 0;
+  base::StringView prev_comm;
   uint32_t next_pid = 0;
   for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
     switch (fld.id) {
@@ -226,8 +223,7 @@
         prev_state = fld.as_uint32();
         break;
       case protos::SchedSwitchFtraceEvent::kPrevCommFieldNumber:
-        prev_comm = fld.as_char_ptr();
-        prev_comm_len = fld.size();
+        prev_comm = fld.as_string();
         break;
       case protos::SchedSwitchFtraceEvent::kNextPidFieldNumber:
         next_pid = fld.as_uint32();
@@ -237,7 +233,7 @@
     }
   }
   context_->sched_tracker->PushSchedSwitch(cpu, timestamp, prev_pid, prev_state,
-                                           prev_comm, prev_comm_len, next_pid);
+                                           prev_comm, next_pid);
 
   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 3f33b56..cd2326a 100644
--- a/src/trace_processor/proto_trace_parser_unittest.cc
+++ b/src/trace_processor/proto_trace_parser_unittest.cc
@@ -29,11 +29,11 @@
 namespace trace_processor {
 namespace {
 
+using ::testing::_;
 using ::testing::Args;
 using ::testing::ElementsAreArray;
 using ::testing::Eq;
 using ::testing::Pointwise;
-using ::testing::_;
 
 class FakeStringBlobReader : public BlobReader {
  public:
@@ -57,13 +57,12 @@
   MockSchedTracker(TraceProcessorContext* context) : SchedTracker(context) {}
   virtual ~MockSchedTracker() = default;
 
-  MOCK_METHOD7(PushSchedSwitch,
+  MOCK_METHOD6(PushSchedSwitch,
                void(uint32_t cpu,
                     uint64_t timestamp,
                     uint32_t prev_pid,
                     uint32_t prev_state,
-                    const char* prev_comm,
-                    size_t prev_comm_len,
+                    base::StringView prev_comm,
                     uint32_t next_pid));
 };
 
@@ -72,10 +71,8 @@
   MockProcessTracker(TraceProcessorContext* context)
       : ProcessTracker(context) {}
 
-  MOCK_METHOD3(UpdateProcess,
-               UniquePid(uint32_t pid,
-                         const char* process_name,
-                         size_t process_name_len));
+  MOCK_METHOD2(UpdateProcess,
+               UniquePid(uint32_t pid, base::StringView process_name));
 
   MOCK_METHOD2(UpdateThread, UniqueTid(uint32_t tid, uint32_t tgid));
 };
@@ -99,8 +96,8 @@
   TraceProcessorContext context;
   MockSchedTracker* sched = new MockSchedTracker(&context);
   context.sched_tracker.reset(sched);
-  EXPECT_CALL(*sched, PushSchedSwitch(10, 1000, 10, 32, _, _, 100))
-      .With(Args<4, 5>(ElementsAreArray(kProcName, sizeof(kProcName) - 1)));
+  EXPECT_CALL(*sched, PushSchedSwitch(10, 1000, 10, 32,
+                                      base::StringView(kProcName), 100));
 
   FakeStringBlobReader reader(trace.SerializeAsString());
   ProtoTraceParser parser(&reader, &context);
@@ -136,11 +133,11 @@
   TraceProcessorContext context;
   MockSchedTracker* sched = new MockSchedTracker(&context);
   context.sched_tracker.reset(sched);
-  EXPECT_CALL(*sched, PushSchedSwitch(10, 1000, 10, 32, _, _, 100))
-      .With(Args<4, 5>(ElementsAreArray(kProcName1, sizeof(kProcName1) - 1)));
+  EXPECT_CALL(*sched, PushSchedSwitch(10, 1000, 10, 32,
+                                      base::StringView(kProcName1), 100));
 
-  EXPECT_CALL(*sched, PushSchedSwitch(10, 1001, 100, 32, _, _, 10))
-      .With(Args<4, 5>(ElementsAreArray(kProcName2, sizeof(kProcName2) - 1)));
+  EXPECT_CALL(*sched, PushSchedSwitch(10, 1001, 100, 32,
+                                      base::StringView(kProcName2), 10));
 
   FakeStringBlobReader reader(trace.SerializeAsString());
   ProtoTraceParser parser(&reader, &context);
@@ -179,11 +176,11 @@
   TraceProcessorContext context;
   MockSchedTracker* sched = new MockSchedTracker(&context);
   context.sched_tracker.reset(sched);
-  EXPECT_CALL(*sched, PushSchedSwitch(10, 1000, 10, 32, _, _, 100))
-      .With(Args<4, 5>(ElementsAreArray(kProcName1, sizeof(kProcName1) - 1)));
+  EXPECT_CALL(*sched, PushSchedSwitch(10, 1000, 10, 32,
+                                      base::StringView(kProcName1), 100));
 
-  EXPECT_CALL(*sched, PushSchedSwitch(10, 1001, 100, 32, _, _, 10))
-      .With(Args<4, 5>(ElementsAreArray(kProcName2, sizeof(kProcName2) - 1)));
+  EXPECT_CALL(*sched, PushSchedSwitch(10, 1001, 100, 32,
+                                      base::StringView(kProcName2), 10));
 
   FakeStringBlobReader reader(trace.SerializeAsString());
   ProtoTraceParser parser(&reader, &context);
@@ -225,16 +222,16 @@
   TraceProcessorContext context;
   MockSchedTracker* sched = new MockSchedTracker(&context);
   context.sched_tracker.reset(sched);
-  EXPECT_CALL(*sched, PushSchedSwitch(10, 1000, 10, 32, _, _, 100))
-      .With(Args<4, 5>(ElementsAreArray(kProcName1, sizeof(kProcName1) - 1)));
+  EXPECT_CALL(*sched, PushSchedSwitch(10, 1000, 10, 32,
+                                      base::StringView(kProcName1), 100));
 
   FakeStringBlobReader reader(trace.SerializeAsString());
   ProtoTraceParser parser(&reader, &context);
   parser.set_chunk_size_for_testing(chunk_size);
   parser.ParseNextChunk();
 
-  EXPECT_CALL(*sched, PushSchedSwitch(10, 1001, 100, 32, _, _, 10))
-      .With(Args<4, 5>(ElementsAreArray(kProcName2, sizeof(kProcName2) - 1)));
+  EXPECT_CALL(*sched, PushSchedSwitch(10, 1001, 100, 32,
+                                      base::StringView(kProcName2), 10));
 
   parser.ParseNextChunk();
 }
@@ -253,8 +250,7 @@
   TraceProcessorContext context;
   MockProcessTracker* process_tracker = new MockProcessTracker(&context);
   context.process_tracker.reset(process_tracker);
-  EXPECT_CALL(*process_tracker, UpdateProcess(1, _, _))
-      .With(Args<1, 2>(ElementsAreArray(kProcName1, sizeof(kProcName1) - 1)));
+  EXPECT_CALL(*process_tracker, UpdateProcess(1, base::StringView(kProcName1)));
   FakeStringBlobReader reader(trace.SerializeAsString());
   ProtoTraceParser parser(&reader, &context);
   parser.ParseNextChunk();
@@ -276,8 +272,7 @@
   TraceProcessorContext context;
   MockProcessTracker* process_tracker = new MockProcessTracker(&context);
   context.process_tracker.reset(process_tracker);
-  EXPECT_CALL(*process_tracker, UpdateProcess(1, _, _))
-      .With(Args<1, 2>(ElementsAreArray(kProcName1, sizeof(kProcName1) - 1)));
+  EXPECT_CALL(*process_tracker, UpdateProcess(1, base::StringView(kProcName1)));
   FakeStringBlobReader reader(trace.SerializeAsString());
   ProtoTraceParser parser(&reader, &context);
   parser.ParseNextChunk();
diff --git a/src/trace_processor/sched_slice_table_unittest.cc b/src/trace_processor/sched_slice_table_unittest.cc
index 8109a5f..6237e5b 100644
--- a/src/trace_processor/sched_slice_table_unittest.cc
+++ b/src/trace_processor/sched_slice_table_unittest.cc
@@ -71,17 +71,13 @@
   static const char kCommProc2[] = "process2";
   uint32_t pid_2 = 4;
   context_.sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, prev_state,
-                                          kCommProc1, sizeof(kCommProc1) - 1,
-                                          pid_2);
+                                          kCommProc1, pid_2);
   context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 3, pid_2, prev_state,
-                                          kCommProc2, sizeof(kCommProc2) - 1,
-                                          pid_1);
+                                          kCommProc2, pid_1);
   context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 4, pid_1, prev_state,
-                                          kCommProc1, sizeof(kCommProc1) - 1,
-                                          pid_2);
+                                          kCommProc1, pid_2);
   context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 10, pid_2,
-                                          prev_state, kCommProc2,
-                                          sizeof(kCommProc2) - 1, pid_1);
+                                          prev_state, kCommProc2, pid_1);
 
   PrepareValidStatement("SELECT dur, ts, cpu FROM sched ORDER BY dur");
 
@@ -114,23 +110,17 @@
   static const char kCommProc2[] = "process2";
   uint32_t pid_2 = 4;
   context_.sched_tracker->PushSchedSwitch(cpu_3, timestamp - 2, pid_1,
-                                          prev_state, kCommProc1,
-                                          sizeof(kCommProc1) - 1, pid_2);
+                                          prev_state, kCommProc1, pid_2);
   context_.sched_tracker->PushSchedSwitch(cpu_3, timestamp - 1, pid_2,
-                                          prev_state, kCommProc2,
-                                          sizeof(kCommProc2) - 1, pid_1);
+                                          prev_state, kCommProc2, pid_1);
   context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp, pid_1, prev_state,
-                                          kCommProc1, sizeof(kCommProc1) - 1,
-                                          pid_2);
+                                          kCommProc1, pid_2);
   context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 3, pid_2,
-                                          prev_state, kCommProc2,
-                                          sizeof(kCommProc2) - 1, pid_1);
+                                          prev_state, kCommProc2, pid_1);
   context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp + 4, pid_1,
-                                          prev_state, kCommProc1,
-                                          sizeof(kCommProc1) - 1, pid_2);
+                                          prev_state, kCommProc1, pid_2);
   context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 10, pid_2,
-                                          prev_state, kCommProc2,
-                                          sizeof(kCommProc2) - 1, pid_1);
+                                          prev_state, kCommProc2, pid_1);
 
   PrepareValidStatement("SELECT dur, ts, cpu FROM sched ORDER BY dur desc");
 
@@ -162,17 +152,13 @@
   static const char kCommProc2[] = "process2";
   uint32_t pid_2 = 4;
   context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp, pid_1, prev_state,
-                                          kCommProc1, sizeof(kCommProc1) - 1,
-                                          pid_2);
+                                          kCommProc1, pid_2);
   context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 3, pid_2,
-                                          prev_state, kCommProc2,
-                                          sizeof(kCommProc2) - 1, pid_1);
+                                          prev_state, kCommProc2, pid_1);
   context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp + 4, pid_1,
-                                          prev_state, kCommProc1,
-                                          sizeof(kCommProc1) - 1, pid_2);
+                                          prev_state, kCommProc1, pid_2);
   context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 10, pid_2,
-                                          prev_state, kCommProc2,
-                                          sizeof(kCommProc2) - 1, pid_1);
+                                          prev_state, kCommProc2, pid_1);
 
   PrepareValidStatement("SELECT dur, ts, cpu FROM sched WHERE cpu = 3");
 
@@ -194,17 +180,13 @@
   static const char kCommProc2[] = "process2";
   uint32_t pid_2 = 4;
   context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp, pid_1, prev_state,
-                                          kCommProc1, sizeof(kCommProc1) - 1,
-                                          pid_2);
+                                          kCommProc1, pid_2);
   context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp + 3, pid_2,
-                                          prev_state, kCommProc2,
-                                          sizeof(kCommProc2) - 1, pid_1);
+                                          prev_state, kCommProc2, pid_1);
   context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 4, pid_1,
-                                          prev_state, kCommProc1,
-                                          sizeof(kCommProc1) - 1, pid_2);
+                                          prev_state, kCommProc1, pid_2);
   context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp + 10, pid_2,
-                                          prev_state, kCommProc2,
-                                          sizeof(kCommProc2) - 1, pid_1);
+                                          prev_state, kCommProc2, pid_1);
 
   PrepareValidStatement(
       "SELECT dur, ts, cpu FROM sched WHERE _quantum MATCH 5 ORDER BY cpu");
@@ -240,17 +222,13 @@
   static const char kCommProc2[] = "process2";
   uint32_t pid_2 = 4;
   context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp, pid_1, prev_state,
-                                          kCommProc1, sizeof(kCommProc1) - 1,
-                                          pid_2);
+                                          kCommProc1, pid_2);
   context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 3, pid_2,
-                                          prev_state, kCommProc2,
-                                          sizeof(kCommProc2) - 1, pid_1);
+                                          prev_state, kCommProc2, pid_1);
   context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp + 4, pid_1,
-                                          prev_state, kCommProc1,
-                                          sizeof(kCommProc1) - 1, pid_2);
+                                          prev_state, kCommProc1, pid_2);
   context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 10, pid_2,
-                                          prev_state, kCommProc2,
-                                          sizeof(kCommProc2) - 1, pid_1);
+                                          prev_state, kCommProc2, pid_1);
 
   PrepareValidStatement(
       "SELECT dur, ts, cpu FROM sched WHERE _quantum match 5 ORDER BY dur");
@@ -286,17 +264,13 @@
   static const char kCommProc2[] = "process2";
   uint32_t pid_2 = 4;
   context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp, pid_1, prev_state,
-                                          kCommProc1, sizeof(kCommProc1) - 1,
-                                          pid_2);
+                                          kCommProc1, pid_2);
   context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 3, pid_2,
-                                          prev_state, kCommProc2,
-                                          sizeof(kCommProc2) - 1, pid_1);
+                                          prev_state, kCommProc2, pid_1);
   context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp + 4, pid_1,
-                                          prev_state, kCommProc1,
-                                          sizeof(kCommProc1) - 1, pid_2);
+                                          prev_state, kCommProc1, pid_2);
   context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 10, pid_2,
-                                          prev_state, kCommProc2,
-                                          sizeof(kCommProc2) - 1, pid_1);
+                                          prev_state, kCommProc2, pid_1);
 
   PrepareValidStatement(
       "SELECT SUM(dur) as sum_dur "
@@ -323,17 +297,13 @@
   static const char kCommProc2[] = "process2";
   uint32_t pid_2 = 4;
   context_.sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, prev_state,
-                                          kCommProc1, sizeof(kCommProc1) - 1,
-                                          pid_2);
+                                          kCommProc1, pid_2);
   context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 3, pid_2, prev_state,
-                                          kCommProc2, sizeof(kCommProc2) - 1,
-                                          pid_1);
+                                          kCommProc2, pid_1);
   context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 4, pid_1, prev_state,
-                                          kCommProc1, sizeof(kCommProc1) - 1,
-                                          pid_2);
+                                          kCommProc1, pid_2);
   context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 10, pid_2,
-                                          prev_state, kCommProc2,
-                                          sizeof(kCommProc2) - 1, pid_1);
+                                          prev_state, kCommProc2, pid_1);
 
   PrepareValidStatement("SELECT utid FROM sched ORDER BY utid");
 
diff --git a/src/trace_processor/sched_tracker.cc b/src/trace_processor/sched_tracker.cc
index f52938a..ae2eefe 100644
--- a/src/trace_processor/sched_tracker.cc
+++ b/src/trace_processor/sched_tracker.cc
@@ -31,8 +31,7 @@
                                    uint64_t timestamp,
                                    uint32_t prev_pid,
                                    uint32_t prev_state,
-                                   const char* prev_comm,
-                                   size_t prev_comm_len,
+                                   base::StringView prev_comm,
                                    uint32_t next_pid) {
   PERFETTO_DCHECK(cpu < base::kMaxCpus);
   SchedSwitchEvent* prev = &last_sched_per_cpu_[cpu];
@@ -40,8 +39,7 @@
   // slice.
   if (prev->valid() && prev->next_pid != 0 /* Idle process (swapper/N) */) {
     uint64_t duration = timestamp - prev->timestamp;
-    StringId prev_thread_name_id =
-        context_->storage->InternString(prev_comm, prev_comm_len);
+    StringId prev_thread_name_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);
diff --git a/src/trace_processor/sched_tracker.h b/src/trace_processor/sched_tracker.h
index 3688d8e..ce059d4 100644
--- a/src/trace_processor/sched_tracker.h
+++ b/src/trace_processor/sched_tracker.h
@@ -19,6 +19,7 @@
 
 #include <array>
 
+#include "perfetto/base/string_view.h"
 #include "perfetto/base/utils.h"
 #include "src/trace_processor/trace_storage.h"
 
@@ -53,8 +54,7 @@
                                uint64_t timestamp,
                                uint32_t prev_pid,
                                uint32_t prev_state,
-                               const char* prev_comm,
-                               size_t prev_comm_len,
+                               base::StringView prev_comm,
                                uint32_t next_pid);
 
  private:
diff --git a/src/trace_processor/sched_tracker_unittest.cc b/src/trace_processor/sched_tracker_unittest.cc
index 0344446..82e7406 100644
--- a/src/trace_processor/sched_tracker_unittest.cc
+++ b/src/trace_processor/sched_tracker_unittest.cc
@@ -52,13 +52,11 @@
 
   const auto& timestamps = context.storage->SlicesForCpu(cpu).start_ns();
   context.sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, prev_state,
-                                         kCommProc1, sizeof(kCommProc1) - 1,
-                                         pid_2);
+                                         kCommProc1, pid_2);
   ASSERT_EQ(timestamps.size(), 0);
 
   context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, pid_2, prev_state,
-                                         kCommProc2, sizeof(kCommProc2) - 1,
-                                         pid_1);
+                                         kCommProc2, pid_1);
 
   ASSERT_EQ(timestamps.size(), 1ul);
   ASSERT_EQ(timestamps[0], timestamp);
@@ -78,21 +76,18 @@
 
   const auto& timestamps = context.storage->SlicesForCpu(cpu).start_ns();
   context.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/4, prev_state,
-                                         kCommProc1, sizeof(kCommProc1) - 1,
+                                         kCommProc1,
                                          /*tid=*/2);
   ASSERT_EQ(timestamps.size(), 0);
 
   context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/2,
                                          prev_state, kCommProc1,
-                                         sizeof(kCommProc1) - 1,
                                          /*tid=*/4);
   context.sched_tracker->PushSchedSwitch(cpu, timestamp + 11, /*tid=*/4,
                                          prev_state, kCommProc2,
-                                         sizeof(kCommProc2) - 1,
                                          /*tid=*/2);
   context.sched_tracker->PushSchedSwitch(cpu, timestamp + 31, /*tid=*/4,
                                          prev_state, kCommProc1,
-                                         sizeof(kCommProc1) - 1,
                                          /*tid=*/2);
 
   ASSERT_EQ(timestamps.size(), 3ul);
diff --git a/src/trace_processor/thread_table_unittest.cc b/src/trace_processor/thread_table_unittest.cc
index 854a58f..cf4843c 100644
--- a/src/trace_processor/thread_table_unittest.cc
+++ b/src/trace_processor/thread_table_unittest.cc
@@ -72,15 +72,11 @@
   static const char kThreadName2[] = "thread2";
 
   context_.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, prev_state,
-                                          kThreadName1,
-                                          sizeof(kThreadName1) - 1,
-                                          /*tid=*/4);
+                                          kThreadName1, /*tid=*/4);
   context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
-                                          prev_state, kThreadName2,
-                                          sizeof(kThreadName2) - 1,
-                                          /*tid=*/1);
+                                          prev_state, kThreadName2, /*tid=*/1);
 
-  context_.process_tracker->UpdateProcess(2, "test", strlen("test"));
+  context_.process_tracker->UpdateProcess(2, "test");
   context_.process_tracker->UpdateThread(4 /*tid*/, 2 /*pid*/);
   PrepareValidStatement("SELECT utid, upid, tid, name FROM thread where tid=4");
 
@@ -102,18 +98,14 @@
 
   context_.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, prev_state,
                                           kThreadName1,
-                                          sizeof(kThreadName1) - 1,
                                           /*tid=*/4);
   context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
                                           prev_state, kThreadName2,
-                                          sizeof(kThreadName2) - 1,
                                           /*tid=*/1);
   context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 2, /*tid=*/1,
-                                          prev_state, kThreadName1,
-                                          sizeof(kThreadName1) - 1,
-                                          /*tid=*/4);
+                                          prev_state, kThreadName1, /*tid=*/4);
 
-  context_.process_tracker->UpdateProcess(2, "test", strlen("test"));
+  context_.process_tracker->UpdateProcess(2, "test");
   context_.process_tracker->UpdateThread(4 /*tid*/, 2 /*pid*/);
   context_.process_tracker->UpdateThread(1 /*tid*/, 2 /*pid*/);
   PrepareValidStatement(
@@ -137,17 +129,17 @@
 
   context_.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, prev_state,
                                           kThreadName1,
-                                          sizeof(kThreadName1) - 1,
+
                                           /*tid=*/4);
   context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
                                           prev_state, kThreadName2,
-                                          sizeof(kThreadName2) - 1,
+
                                           /*tid=*/1);
 
   // Also create a process for which we haven't seen any thread.
-  context_.process_tracker->UpdateProcess(7, "pid7", strlen("pid7"));
+  context_.process_tracker->UpdateProcess(7, "pid7");
 
-  context_.process_tracker->UpdateProcess(2, "pid2", strlen("pid2"));
+  context_.process_tracker->UpdateProcess(2, "pid2");
   context_.process_tracker->UpdateThread(/*tid=*/4, /*pid=*/2);
 
   PrepareValidStatement(
diff --git a/src/trace_processor/trace_storage.cc b/src/trace_processor/trace_storage.cc
index 38cb414..2c2242c 100644
--- a/src/trace_processor/trace_storage.cc
+++ b/src/trace_processor/trace_storage.cc
@@ -27,7 +27,7 @@
   unique_threads_.emplace_back(0);
 
   // Reserve string ID 0 for the empty string.
-  InternString("", 0);
+  InternString("");
 }
 
 TraceStorage::~TraceStorage() {}
@@ -39,21 +39,14 @@
   cpu_events_[cpu].AddSlice(start_ns, duration_ns, utid);
 };
 
-StringId TraceStorage::InternString(const char* data, size_t length) {
-  uint32_t hash = 0x811c9dc5;  // FNV-1a-32 offset basis.
-  for (size_t i = 0; i < length; ++i) {
-    hash ^= static_cast<decltype(hash)>(data[i]);
-    hash *= 16777619;  // FNV-1a-32 prime.
-  }
+StringId TraceStorage::InternString(base::StringView str) {
+  auto hash = str.Hash();
   auto id_it = string_index_.find(hash);
   if (id_it != string_index_.end()) {
-    // TODO(lalitm): check if this DCHECK happens and if so, then change hash
-    // to 64bit.
-    PERFETTO_DCHECK(
-        strncmp(string_pool_[id_it->second].c_str(), data, length) == 0);
+    PERFETTO_DCHECK(base::StringView(string_pool_[id_it->second]) == str);
     return id_it->second;
   }
-  string_pool_.emplace_back(data, length);
+  string_pool_.emplace_back(str.ToStdString());
   StringId string_id = string_pool_.size() - 1;
   string_index_.emplace(hash, string_id);
   return string_id;
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index b45defe..98e796f 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -25,6 +25,7 @@
 #include <vector>
 
 #include "perfetto/base/logging.h"
+#include "perfetto/base/string_view.h"
 #include "perfetto/base/utils.h"
 
 namespace perfetto {
@@ -165,7 +166,7 @@
 
   // Return an unqiue identifier for the contents of each string.
   // The string is copied internally and can be destroyed after this called.
-  StringId InternString(const char* data, size_t length);
+  StringId InternString(base::StringView);
 
   Process* GetMutableProcess(UniquePid upid) {
     PERFETTO_DCHECK(upid > 0 && upid < unique_processes_.size());
@@ -215,7 +216,7 @@
  private:
   TraceStorage& operator=(const TraceStorage&) = default;
 
-  using StringHash = uint32_t;
+  using StringHash = uint64_t;
 
   // Metadata counters for events being added.
   Stats stats_;