ftrace_reader: Add cpu_reader.cc micro benchmark

Add a micro-benchmark to test the performance of cpu_reader.cc
Also refactor:
- The benchmarking target (so the main lives in benchmark_main.cc)
- The cpu reader test support code (into test/cpu_reader_support.cc)

Change-Id: Ia03df7d9453c098ba3d20d1fc92a95dfc42d678b
diff --git a/Android.bp b/Android.bp
index aca62f5..95237e3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -196,7 +196,9 @@
     "src/ftrace_reader/ftrace_procfs.cc",
     "src/ftrace_reader/ftrace_procfs_integrationtest.cc",
     "src/ftrace_reader/proto_translation_table.cc",
+    "src/ftrace_reader/test/cpu_reader_support.cc",
     "src/ftrace_reader/test/scattered_stream_delegate_for_testing.cc",
+    "src/ftrace_reader/test/scattered_stream_null_delegate.cc",
     "src/ipc/buffered_frame_deserializer.cc",
     "src/ipc/client_impl.cc",
     "src/ipc/deferred.cc",
@@ -1014,7 +1016,9 @@
     "src/ftrace_reader/ftrace_procfs.cc",
     "src/ftrace_reader/proto_translation_table.cc",
     "src/ftrace_reader/proto_translation_table_unittest.cc",
+    "src/ftrace_reader/test/cpu_reader_support.cc",
     "src/ftrace_reader/test/scattered_stream_delegate_for_testing.cc",
+    "src/ftrace_reader/test/scattered_stream_null_delegate.cc",
     "src/ipc/buffered_frame_deserializer.cc",
     "src/ipc/buffered_frame_deserializer_unittest.cc",
     "src/ipc/client_impl.cc",
diff --git a/BUILD.gn b/BUILD.gn
index d6ddccd..1d4b663 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -68,7 +68,9 @@
     testonly = true
     deps = [
       "gn:default_deps",
+      "src/ftrace_reader:ftrace_reader_benchmarks",
       "src/tracing:tracing_benchmarks",
+      "test:benchmark_main",
     ]
   }
 
diff --git a/src/base/test/benchmark_main.cc b/src/base/test/benchmark_main.cc
new file mode 100644
index 0000000..f904cfc
--- /dev/null
+++ b/src/base/test/benchmark_main.cc
@@ -0,0 +1,17 @@
+// 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 "benchmark/benchmark.h"
+
+BENCHMARK_MAIN();
diff --git a/src/ftrace_reader/BUILD.gn b/src/ftrace_reader/BUILD.gn
index 43878da..e78fa8e 100644
--- a/src/ftrace_reader/BUILD.gn
+++ b/src/ftrace_reader/BUILD.gn
@@ -19,12 +19,17 @@
 source_set("test_support") {
   testonly = true
   deps = [
+    ":ftrace_reader",
     "../../gn:default_deps",
     "../protozero",
   ]
   sources = [
+    "test/cpu_reader_support.cc",
+    "test/cpu_reader_support.h",
     "test/scattered_stream_delegate_for_testing.cc",
     "test/scattered_stream_delegate_for_testing.h",
+    "test/scattered_stream_null_delegate.cc",
+    "test/scattered_stream_null_delegate.h",
   ]
 }
 
@@ -108,3 +113,18 @@
     "proto_translation_table.h",
   ]
 }
+
+if (!build_with_chromium) {
+  source_set("ftrace_reader_benchmarks") {
+    testonly = true
+    deps = [
+      ":ftrace_reader",
+      ":test_support",
+      "../../gn:default_deps",
+      "//buildtools:benchmark",
+    ]
+    sources = [
+      "cpu_reader_benchmark.cc",
+    ]
+  }
+}
diff --git a/src/ftrace_reader/cpu_reader_benchmark.cc b/src/ftrace_reader/cpu_reader_benchmark.cc
new file mode 100644
index 0000000..078b46a
--- /dev/null
+++ b/src/ftrace_reader/cpu_reader_benchmark.cc
@@ -0,0 +1,320 @@
+// 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 "benchmark/benchmark.h"
+
+#include "cpu_reader.h"
+
+#include "perfetto/protozero/scattered_stream_writer.h"
+
+#include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "test/cpu_reader_support.h"
+#include "test/scattered_stream_null_delegate.h"
+
+namespace {
+
+const size_t kPageSize = 4096;
+
+perfetto::ExamplePage g_full_page_sched_switch{
+    "synthetic",
+    R"(
+00000000: 31f2 7622 1a00 0000 b40f 0000 0000 0000  1.v"............
+00000010: 1e00 0000 0000 0000 1000 0000 2f00 0103  ............/...
+00000020: 140d 0000 4a69 7420 7468 7265 6164 2070  ....Jit thread p
+00000030: 6f6f 6c00 140d 0000 8100 0000 0008 0000  ool.............
+00000040: 0000 0000 4576 656e 7454 6872 6561 6400  ....EventThread.
+00000050: 6572 0000 7002 0000 6100 0000 f057 0e00  er..p...a....W..
+00000060: 2f00 0103 7002 0000 4576 656e 7454 6872  /...p...EventThr
+00000070: 6561 6400 6572 0000 7002 0000 6100 0000  ead.er..p...a...
+00000080: 0100 0000 0000 0000 4a69 7420 7468 7265  ........Jit thre
+00000090: 6164 2070 6f6f 6c00 140d 0000 8100 0000  ad pool.........
+000000a0: 50c2 0910 2f00 0103 140d 0000 4a69 7420  P.../.......Jit 
+000000b0: 7468 7265 6164 2070 6f6f 6c00 140d 0000  thread pool.....
+000000c0: 8100 0000 0100 0000 0000 0000 7377 6170  ............swap
+000000d0: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+000000e0: 7800 0000 901a c80e 2f00 0103 0000 0000  x......./.......
+000000f0: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000100: 0000 0000 7800 0000 0000 0000 0000 0000  ....x...........
+00000110: 4469 7370 5379 6e63 0069 6e67 6572 0000  DispSync.inger..
+00000120: 6f02 0000 6100 0000 1064 1e00 2f00 0103  o...a....d../...
+00000130: 6f02 0000 4469 7370 5379 6e63 0069 6e67  o...DispSync.ing
+00000140: 6572 0000 6f02 0000 6100 0000 0100 0000  er..o...a.......
+00000150: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000160: 0000 0000 0000 0000 7800 0000 9074 8600  ........x....t..
+00000170: 2f00 0103 0000 0000 7377 6170 7065 722f  /.......swapper/
+00000180: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000190: 0000 0000 0000 0000 4576 656e 7454 6872  ........EventThr
+000001a0: 6561 6400 6572 0000 7002 0000 6100 0000  ead.er..p...a...
+000001b0: d071 0b00 2f00 0103 7002 0000 4576 656e  .q../...p...Even
+000001c0: 7454 6872 6561 6400 6572 0000 7002 0000  tThread.er..p...
+000001d0: 6100 0000 0100 0000 0000 0000 7377 6170  a...........swap
+000001e0: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+000001f0: 7800 0000 10cd 4504 2f00 0103 0000 0000  x.....E./.......
+00000200: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000210: 0000 0000 7800 0000 0000 0000 0000 0000  ....x...........
+00000220: 7375 676f 763a 3000 0000 0000 0000 0000  sugov:0.........
+00000230: 3802 0000 3100 0000 30d6 1300 2f00 0103  8...1...0.../...
+00000240: 3802 0000 7375 676f 763a 3000 0000 0000  8...sugov:0.....
+00000250: 0000 0000 3802 0000 3100 0000 0100 0000  ....8...1.......
+00000260: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000270: 0000 0000 0000 0000 7800 0000 3049 a202  ........x...0I..
+00000280: 2f00 0103 0000 0000 7377 6170 7065 722f  /.......swapper/
+00000290: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+000002a0: 0000 0000 0000 0000 4469 7370 5379 6e63  ........DispSync
+000002b0: 0069 6e67 6572 0000 6f02 0000 6100 0000  .inger..o...a...
+000002c0: d07a 1000 2f00 0103 6f02 0000 4469 7370  .z../...o...Disp
+000002d0: 5379 6e63 0069 6e67 6572 0000 6f02 0000  Sync.inger..o...
+000002e0: 6100 0000 0100 0000 0000 0000 7377 6170  a...........swap
+000002f0: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000300: 7800 0000 d085 1100 2f00 0103 0000 0000  x......./.......
+00000310: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000320: 0000 0000 7800 0000 0000 0000 0000 0000  ....x...........
+00000330: 7375 7266 6163 6566 6c69 6e67 6572 0000  surfaceflinger..
+00000340: 4b02 0000 6200 0000 907a f000 2f00 0103  K...b....z../...
+00000350: 4b02 0000 7375 7266 6163 6566 6c69 6e67  K...surfacefling
+00000360: 6572 0000 4b02 0000 6200 0000 0100 0000  er..K...b.......
+00000370: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000380: 0000 0000 0000 0000 7800 0000 305a 6400  ........x...0Zd.
+00000390: 2f00 0103 0000 0000 7377 6170 7065 722f  /.......swapper/
+000003a0: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+000003b0: 0000 0000 0000 0000 6d64 7373 5f66 6230  ........mdss_fb0
+000003c0: 0000 0000 0000 0000 5714 0000 5300 0000  ........W...S...
+000003d0: 10b1 9e03 2f00 0103 5714 0000 6d64 7373  ..../...W...mdss
+000003e0: 5f66 6230 0000 0000 0000 0000 5714 0000  _fb0........W...
+000003f0: 5300 0000 0200 0000 0000 0000 6b73 6f66  S...........ksof
+00000400: 7469 7271 642f 3000 0000 0000 0300 0000  tirqd/0.........
+00000410: 7800 0000 90bb 9900 2f00 0103 0300 0000  x......./.......
+00000420: 6b73 6f66 7469 7271 642f 3000 0000 0000  ksoftirqd/0.....
+00000430: 0300 0000 7800 0000 0100 0000 0000 0000  ....x...........
+00000440: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000450: 0000 0000 7800 0000 701e 5305 2f00 0103  ....x...p.S./...
+00000460: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000470: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+00000480: 0000 0000 6b77 6f72 6b65 722f 7531 363a  ....kworker/u16:
+00000490: 3600 0000 6401 0000 7800 0000 90a1 2900  6...d...x.....).
+000004a0: 2f00 0103 6401 0000 6b77 6f72 6b65 722f  /...d...kworker/
+000004b0: 7531 363a 3600 0000 6401 0000 7800 0000  u16:6...d...x...
+000004c0: 0200 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+000004d0: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+000004e0: b0e5 4f04 2f00 0103 0000 0000 7377 6170  ..O./.......swap
+000004f0: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000500: 7800 0000 0000 0000 0000 0000 4269 6e64  x...........Bind
+00000510: 6572 3a32 3136 385f 3135 0000 e614 0000  er:2168_15......
+00000520: 7800 0000 b0bd 7c00 2f00 0103 e614 0000  x.....|./.......
+00000530: 4269 6e64 6572 3a32 3136 385f 3135 0000  Binder:2168_15..
+00000540: e614 0000 7800 0000 0100 0000 0000 0000  ....x...........
+00000550: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000560: 0000 0000 7800 0000 d0bd 7e01 2f00 0103  ....x.....~./...
+00000570: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000580: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+00000590: 0000 0000 6b77 6f72 6b65 722f 7531 363a  ....kworker/u16:
+000005a0: 3900 0000 e204 0000 7800 0000 7016 0800  9.......x...p...
+000005b0: 2f00 0103 e204 0000 6b77 6f72 6b65 722f  /.......kworker/
+000005c0: 7531 363a 3900 0000 e204 0000 7800 0000  u16:9.......x...
+000005d0: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+000005e0: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+000005f0: 1004 5200 2f00 0103 0000 0000 7377 6170  ..R./.......swap
+00000600: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000610: 7800 0000 0000 0000 0000 0000 6b77 6f72  x...........kwor
+00000620: 6b65 722f 7531 363a 3900 0000 e204 0000  ker/u16:9.......
+00000630: 7800 0000 d0db 0700 2f00 0103 e204 0000  x......./.......
+00000640: 6b77 6f72 6b65 722f 7531 363a 3900 0000  kworker/u16:9...
+00000650: e204 0000 7800 0000 0100 0000 0000 0000  ....x...........
+00000660: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000670: 0000 0000 7800 0000 b0a2 8c00 2f00 0103  ....x......./...
+00000680: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000690: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+000006a0: 0000 0000 6b77 6f72 6b65 722f 7531 363a  ....kworker/u16:
+000006b0: 3900 0000 e204 0000 7800 0000 d02b 0400  9.......x....+..
+000006c0: 2f00 0103 e204 0000 6b77 6f72 6b65 722f  /.......kworker/
+000006d0: 7531 363a 3900 0000 e204 0000 7800 0000  u16:9.......x...
+000006e0: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+000006f0: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000700: d064 ef05 2f00 0103 0000 0000 7377 6170  .d../.......swap
+00000710: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000720: 7800 0000 0000 0000 0000 0000 4469 7370  x...........Disp
+00000730: 5379 6e63 0069 6e67 6572 0000 6f02 0000  Sync.inger..o...
+00000740: 6100 0000 f07d 1b00 2f00 0103 6f02 0000  a....}../...o...
+00000750: 4469 7370 5379 6e63 0069 6e67 6572 0000  DispSync.inger..
+00000760: 6f02 0000 6100 0000 0100 0000 0000 0000  o...a...........
+00000770: 6b73 6f66 7469 7271 642f 3000 0000 0000  ksoftirqd/0.....
+00000780: 0300 0000 7800 0000 304c 2000 2f00 0103  ....x...0L ./...
+00000790: 0300 0000 6b73 6f66 7469 7271 642f 3000  ....ksoftirqd/0.
+000007a0: 0000 0000 0300 0000 7800 0000 0100 0000  ........x.......
+000007b0: 0000 0000 6465 7832 6f61 7400 3935 5f33  ....dex2oat.95_3
+000007c0: 0000 0000 341f 0000 8200 0000 700b 0700  ....4.......p...
+000007d0: 2f00 0103 341f 0000 6465 7832 6f61 7400  /...4...dex2oat.
+000007e0: 3935 5f33 0000 0000 341f 0000 8200 0000  95_3....4.......
+000007f0: 0000 0000 0000 0000 7375 676f 763a 3000  ........sugov:0.
+00000800: 0000 0000 0000 0000 3802 0000 3100 0000  ........8...1...
+00000810: 50b0 0600 2f00 0103 3802 0000 7375 676f  P.../...8...sugo
+00000820: 763a 3000 0000 0000 0000 0000 3802 0000  v:0.........8...
+00000830: 3100 0000 0008 0000 0000 0000 6d69 6772  1...........migr
+00000840: 6174 696f 6e2f 3000 0000 0000 0d00 0000  ation/0.........
+00000850: 0000 0000 d09c 0600 2f00 0103 0d00 0000  ......../.......
+00000860: 6d69 6772 6174 696f 6e2f 3000 0000 0000  migration/0.....
+00000870: 0d00 0000 0000 0000 0100 0000 0000 0000  ................
+00000880: 7375 676f 763a 3000 0000 0000 0000 0000  sugov:0.........
+00000890: 3802 0000 3100 0000 7061 1900 2f00 0103  8...1...pa../...
+000008a0: 3802 0000 7375 676f 763a 3000 0000 0000  8...sugov:0.....
+000008b0: 0000 0000 3802 0000 3100 0000 0100 0000  ....8...1.......
+000008c0: 0000 0000 6465 7832 6f61 7400 3935 5f33  ....dex2oat.95_3
+000008d0: 0000 0000 341f 0000 8200 0000 f03c 5600  ....4........<V.
+000008e0: 2f00 0103 341f 0000 6465 7832 6f61 7400  /...4...dex2oat.
+000008f0: 3935 5f33 0000 0000 341f 0000 8200 0000  95_3....4.......
+00000900: 0200 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+00000910: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000920: 5013 c400 2f00 0103 0000 0000 7377 6170  P.../.......swap
+00000930: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000940: 7800 0000 0000 0000 0000 0000 616e 6472  x...........andr
+00000950: 6f69 642e 6861 7264 7761 7200 d20a 0000  oid.hardwar.....
+00000960: 7800 0000 30c9 1300 2f00 0103 d20a 0000  x...0.../.......
+00000970: 616e 6472 6f69 642e 6861 7264 7761 7200  android.hardwar.
+00000980: d20a 0000 7800 0000 0100 0000 0000 0000  ....x...........
+00000990: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+000009a0: 0000 0000 7800 0000 7097 c000 2f00 0103  ....x...p.../...
+000009b0: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+000009c0: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+000009d0: 0000 0000 616e 6472 6f69 642e 6861 7264  ....android.hard
+000009e0: 7761 7200 d20a 0000 7800 0000 305c 0c00  war.....x...0\..
+000009f0: 2f00 0103 d20a 0000 616e 6472 6f69 642e  /.......android.
+00000a00: 6861 7264 7761 7200 d20a 0000 7800 0000  hardwar.....x...
+00000a10: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+00000a20: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000a30: d0aa 1401 2f00 0103 0000 0000 7377 6170  ..../.......swap
+00000a40: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000a50: 7800 0000 0000 0000 0000 0000 616e 6472  x...........andr
+00000a60: 6f69 642e 6861 7264 7761 7200 d20a 0000  oid.hardwar.....
+00000a70: 7800 0000 903b 0c00 2f00 0103 d20a 0000  x....;../.......
+00000a80: 616e 6472 6f69 642e 6861 7264 7761 7200  android.hardwar.
+00000a90: d20a 0000 7800 0000 0100 0000 0000 0000  ....x...........
+00000aa0: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000ab0: 0000 0000 7800 0000 f024 5401 2f00 0103  ....x....$T./...
+00000ac0: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000ad0: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+00000ae0: 0000 0000 616e 6472 6f69 642e 6861 7264  ....android.hard
+00000af0: 7761 7200 d20a 0000 7800 0000 f0f3 0b00  war.....x.......
+00000b00: 2f00 0103 d20a 0000 616e 6472 6f69 642e  /.......android.
+00000b10: 6861 7264 7761 7200 d20a 0000 7800 0000  hardwar.....x...
+00000b20: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+00000b30: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000b40: d0b5 bf02 2f00 0103 0000 0000 7377 6170  ..../.......swap
+00000b50: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000b60: 7800 0000 0000 0000 0000 0000 4469 7370  x...........Disp
+00000b70: 5379 6e63 0069 6e67 6572 0000 6f02 0000  Sync.inger..o...
+00000b80: 6100 0000 90cd 1400 2f00 0103 6f02 0000  a......./...o...
+00000b90: 4469 7370 5379 6e63 0069 6e67 6572 0000  DispSync.inger..
+00000ba0: 6f02 0000 6100 0000 0100 0000 0000 0000  o...a...........
+00000bb0: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000bc0: 0000 0000 7800 0000 50a6 1100 2f00 0103  ....x...P.../...
+00000bd0: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000be0: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+00000bf0: 0000 0000 7375 7266 6163 6566 6c69 6e67  ....surfacefling
+00000c00: 6572 0000 4b02 0000 6200 0000 b04c 4200  er..K...b....LB.
+00000c10: 2f00 0103 4b02 0000 7375 7266 6163 6566  /...K...surfacef
+00000c20: 6c69 6e67 6572 0000 4b02 0000 6200 0000  linger..K...b...
+00000c30: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+00000c40: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000c50: b025 060a 2f00 0103 0000 0000 7377 6170  .%../.......swap
+00000c60: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000c70: 7800 0000 0000 0000 0000 0000 6b77 6f72  x...........kwor
+00000c80: 6b65 722f 7531 363a 3600 0000 6401 0000  ker/u16:6...d...
+00000c90: 7800 0000 d0b6 0600 2f00 0103 6401 0000  x......./...d...
+00000ca0: 6b77 6f72 6b65 722f 7531 363a 3600 0000  kworker/u16:6...
+00000cb0: 6401 0000 7800 0000 0100 0000 0000 0000  d...x...........
+00000cc0: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000cd0: 0000 0000 7800 0000 f0a0 5800 2f00 0103  ....x.....X./...
+00000ce0: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000cf0: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+00000d00: 0000 0000 6b77 6f72 6b65 722f 7531 363a  ....kworker/u16:
+00000d10: 3600 0000 6401 0000 7800 0000 f07a 1300  6...d...x....z..
+00000d20: 2f00 0103 6401 0000 6b77 6f72 6b65 722f  /...d...kworker/
+00000d30: 7531 363a 3600 0000 6401 0000 7800 0000  u16:6...d...x...
+00000d40: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+00000d50: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000d60: b080 b101 2f00 0103 0000 0000 7377 6170  ..../.......swap
+00000d70: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000d80: 7800 0000 0000 0000 0000 0000 6b77 6f72  x...........kwor
+00000d90: 6b65 722f 7531 363a 3600 0000 6401 0000  ker/u16:6...d...
+00000da0: 7800 0000 103c 1200 2f00 0103 6401 0000  x....<../...d...
+00000db0: 6b77 6f72 6b65 722f 7531 363a 3600 0000  kworker/u16:6...
+00000dc0: 6401 0000 7800 0000 0100 0000 0000 0000  d...x...........
+00000dd0: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000de0: 0000 0000 7800 0000 50ea 3800 2f00 0103  ....x...P.8./...
+00000df0: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000e00: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+00000e10: 0000 0000 6b77 6f72 6b65 722f 7531 363a  ....kworker/u16:
+00000e20: 3600 0000 6401 0000 7800 0000 5032 0400  6...d...x...P2..
+00000e30: 2f00 0103 6401 0000 6b77 6f72 6b65 722f  /...d...kworker/
+00000e40: 7531 363a 3600 0000 6401 0000 7800 0000  u16:6...d...x...
+00000e50: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+00000e60: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000e70: 70f5 9000 2f00 0103 0000 0000 7377 6170  p.../.......swap
+00000e80: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000e90: 7800 0000 0000 0000 0000 0000 6b77 6f72  x...........kwor
+00000ea0: 6b65 722f 7531 363a 3600 0000 6401 0000  ker/u16:6...d...
+00000eb0: 7800 0000 10d7 0300 2f00 0103 6401 0000  x......./...d...
+00000ec0: 6b77 6f72 6b65 722f 7531 363a 3600 0000  kworker/u16:6...
+00000ed0: 6401 0000 7800 0000 0100 0000 0000 0000  d...x...........
+00000ee0: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000ef0: 0000 0000 7800 0000 907c 0900 2f00 0103  ....x....|../...
+00000f00: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000f10: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+00000f20: 0000 0000 6b77 6f72 6b65 722f 7531 363a  ....kworker/u16:
+00000f30: 3600 0000 6401 0000 7800 0000 7082 0300  6...d...x...p...
+00000f40: 2f00 0103 6401 0000 6b77 6f72 6b65 722f  /...d...kworker/
+00000f50: 7531 363a 3600 0000 6401 0000 7800 0000  u16:6...d...x...
+00000f60: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+00000f70: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000f80: f0ec 2100 2f00 0103 0000 0000 7377 6170  ..!./.......swap
+00000f90: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000fa0: 7800 0000 0000 0000 0000 0000 6b77 6f72  x...........kwor
+00000fb0: 6b65 722f 7531 363a 3600 0000 6401 0000  ker/u16:6...d...
+00000fc0: 7800 0000 0000 0000 0000 0000 0000 0000  x...............
+00000fd0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000fe0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000ff0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+    )",
+};
+
+}  // namespace
+
+using perfetto::ExamplePage;
+using perfetto::EventFilter;
+using perfetto::ProtoTranslationTable;
+using perfetto::ScatteredStreamNullDelegate;
+using perfetto::GetTable;
+using perfetto::PageFromXxd;
+using perfetto::protos::pbzero::FtraceEventBundle;
+using perfetto::CpuReader;
+
+static void BM_ParsePageFullOfSchedSwitch(benchmark::State& state) {
+  const ExamplePage* test_case = &g_full_page_sched_switch;
+
+  ScatteredStreamNullDelegate delegate(kPageSize);
+  protozero::ScatteredStreamWriter stream(&delegate);
+  FtraceEventBundle writer;
+
+  ProtoTranslationTable* table = GetTable(test_case->name);
+  auto page = PageFromXxd(test_case->data);
+
+  EventFilter filter(*table, std::set<std::string>({"sched_switch"}));
+
+  while (state.KeepRunning()) {
+    writer.Reset(&stream);
+    CpuReader::ParsePage(42 /* cpu number */, page.get(), &filter, &writer,
+                         table);
+  }
+}
+BENCHMARK(BM_ParsePageFullOfSchedSwitch);
diff --git a/src/ftrace_reader/cpu_reader_unittest.cc b/src/ftrace_reader/cpu_reader_unittest.cc
index fe0c204..4180d02 100644
--- a/src/ftrace_reader/cpu_reader_unittest.cc
+++ b/src/ftrace_reader/cpu_reader_unittest.cc
@@ -17,7 +17,6 @@
 #include "cpu_reader.h"
 
 #include "event_info.h"
-#include "ftrace_procfs.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "proto_translation_table.h"
@@ -30,6 +29,7 @@
 #include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
 #include "perfetto/trace/ftrace/ftrace_event_bundle.pb.h"
 #include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "src/ftrace_reader/test/cpu_reader_support.h"
 #include "src/ftrace_reader/test/test_messages.pb.h"
 #include "src/ftrace_reader/test/test_messages.pbzero.h"
 
@@ -58,14 +58,6 @@
   }
 }
 
-struct ExamplePage {
-  // The name of the format file set used in the collection of this example
-  // page. Should name a directory under src/ftrace_reader/test/data
-  const char* name;
-  // The non-zero prefix of xxd'ing the page.
-  const char* data;
-};
-
 // Single class to manage the whole protozero -> scattered stream -> chunks ->
 // single buffer -> real proto dance. Has a method: writer() to get an
 // protozero ftrace bundle writer and a method ParseProto() to attempt to
@@ -100,7 +92,7 @@
   ProtoProvider& operator=(const ProtoProvider&) = delete;
 
   size_t chunk_size_;
-  perfetto::ScatteredStreamDelegateForTesting delegate_;
+  ScatteredStreamDelegateForTesting delegate_;
   protozero::ScatteredStreamWriter stream_;
   ZeroT writer_;
 };
@@ -108,47 +100,6 @@
 using BundleProvider =
     ProtoProvider<protos::pbzero::FtraceEventBundle, protos::FtraceEventBundle>;
 
-// Create a ProtoTranslationTable uing the fomat files in
-// directory |name|. Caches the table for subsequent lookups.
-std::map<std::string, std::unique_ptr<ProtoTranslationTable>>* g_tables;
-ProtoTranslationTable* GetTable(const std::string& name) {
-  if (!g_tables)
-    g_tables =
-        new std::map<std::string, std::unique_ptr<ProtoTranslationTable>>();
-  if (!g_tables->count(name)) {
-    std::string path = "src/ftrace_reader/test/data/" + name + "/";
-    FtraceProcfs ftrace(path);
-    auto table = ProtoTranslationTable::Create(&ftrace, GetStaticEventInfo(),
-                                               GetStaticCommonFieldsInfo());
-    g_tables->emplace(name, std::move(table));
-  }
-  return g_tables->at(name).get();
-}
-
-// Convert xxd output into binary data.
-std::unique_ptr<uint8_t[]> PageFromXxd(const std::string& text) {
-  auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[base::kPageSize]);
-  const char* ptr = text.data();
-  memset(buffer.get(), 0xfa, base::kPageSize);
-  uint8_t* out = buffer.get();
-  while (*ptr != '\0') {
-    if (*(ptr++) != ':')
-      continue;
-    for (int i = 0; i < 8; i++) {
-      PERFETTO_CHECK(text.size() >=
-                     static_cast<size_t>((ptr - text.data()) + 5));
-      PERFETTO_CHECK(*(ptr++) == ' ');
-      int n = sscanf(ptr, "%02hhx%02hhx", out, out + 1);
-      PERFETTO_CHECK(n == 2);
-      out += n;
-      ptr += 4;
-    }
-    while (*ptr != '\n')
-      ptr++;
-  }
-  return buffer;
-}
-
 class BinaryWriter {
  public:
   BinaryWriter()
@@ -704,4 +655,473 @@
   EXPECT_EQ(event->all_fields().field_char(), "Goodbye");
 }
 
+// # tracer: nop
+// #
+// # entries-in-buffer/entries-written: 86106/86106   #P:8
+// #
+// #                              _-----=> irqs-off
+// #                             / _----=> need-resched
+// #                            | / _---=> hardirq/softirq
+// #                            || / _--=> preempt-depth
+// #                            ||| /     delay
+// #           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
+// #              | |       |   ||||       |         |
+//            <...>-3348  [000] d..3   112.247370: sched_switch: prev_comm=Jit
+//            thread pool prev_pid=3348 prev_prio=129 prev_state=R+ ==>
+//            next_comm=EventThread next_pid=624 next_prio=97
+//      EventThread-624   [000] d..3   112.247400: sched_switch:
+//      prev_comm=EventThread prev_pid=624 prev_prio=97 prev_state=S ==>
+//      next_comm=Jit thread pool next_pid=3348 next_prio=129
+//            <...>-3348  [000] d..3   112.255808: sched_switch: prev_comm=Jit
+//            thread pool prev_pid=3348 prev_prio=129 prev_state=S ==>
+//            next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.263558: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=DispSync next_pid=623 next_prio=97
+//         DispSync-623   [000] d..3   112.263620: sched_switch:
+//         prev_comm=DispSync prev_pid=623 prev_prio=97 prev_state=S ==>
+//         next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.263896: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=EventThread next_pid=624 next_prio=97
+//      EventThread-624   [000] d..3   112.263919: sched_switch:
+//      prev_comm=EventThread prev_pid=624 prev_prio=97 prev_state=S ==>
+//      next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.266159: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=sugov:0 next_pid=568 next_prio=49
+//            <...>-568   [000] d..3   112.266200: sched_switch:
+//            prev_comm=sugov:0 prev_pid=568 prev_prio=49 prev_state=S ==>
+//            next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.267581: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=DispSync next_pid=623 next_prio=97
+//         DispSync-623   [000] d..3   112.267615: sched_switch:
+//         prev_comm=DispSync prev_pid=623 prev_prio=97 prev_state=S ==>
+//         next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.267650: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=surfaceflinger next_pid=587 next_prio=98
+//   surfaceflinger-587   [000] d..3   112.268143: sched_switch:
+//   prev_comm=surfaceflinger prev_pid=587 prev_prio=98 prev_state=S ==>
+//   next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.268348: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=mdss_fb0 next_pid=5207 next_prio=83
+//         mdss_fb0-5207  [000] d..3   112.270246: sched_switch:
+//         prev_comm=mdss_fb0 prev_pid=5207 prev_prio=83 prev_state=D ==>
+//         next_comm=ksoftirqd/0 next_pid=3 next_prio=120
+//            <...>-3     [000] d..3   112.270561: sched_switch:
+//            prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==>
+//            next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.273353: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=kworker/u16:6 next_pid=356 next_prio=120
+//            <...>-356   [000] d..3   112.273438: sched_switch:
+//            prev_comm=kworker/u16:6 prev_pid=356 prev_prio=120 prev_state=D
+//            ==> next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.275699: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=Binder:2168_15 next_pid=5350 next_prio=120
+//            <...>-5350  [000] d..3   112.275954: sched_switch:
+//            prev_comm=Binder:2168_15 prev_pid=5350 prev_prio=120 prev_state=S
+//            ==> next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.276738: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=kworker/u16:9 next_pid=1250 next_prio=120
+//    kworker/u16:9-1250  [000] d..3   112.276755: sched_switch:
+//    prev_comm=kworker/u16:9 prev_pid=1250 prev_prio=120 prev_state=S ==>
+//    next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.276923: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=kworker/u16:9 next_pid=1250 next_prio=120
+//    kworker/u16:9-1250  [000] d..3   112.276939: sched_switch:
+//    prev_comm=kworker/u16:9 prev_pid=1250 prev_prio=120 prev_state=S ==>
+//    next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.277227: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=kworker/u16:9 next_pid=1250 next_prio=120
+//    kworker/u16:9-1250  [000] d..3   112.277235: sched_switch:
+//    prev_comm=kworker/u16:9 prev_pid=1250 prev_prio=120 prev_state=S ==>
+//    next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.280347: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=DispSync next_pid=623 next_prio=97
+//         DispSync-623   [000] d..3   112.280403: sched_switch:
+//         prev_comm=DispSync prev_pid=623 prev_prio=97 prev_state=S ==>
+//         next_comm=ksoftirqd/0 next_pid=3 next_prio=120
+//            <...>-3     [000] d..3   112.280470: sched_switch:
+//            prev_comm=ksoftirqd/0 prev_pid=3 prev_prio=120 prev_state=S ==>
+//            next_comm=dex2oat next_pid=7988 next_prio=130
+//            <...>-7988  [000] d..3   112.280484: sched_switch:
+//            prev_comm=dex2oat prev_pid=7988 prev_prio=130 prev_state=R ==>
+//            next_comm=sugov:0 next_pid=568 next_prio=49
+//            <...>-568   [000] d..3   112.280498: sched_switch:
+//            prev_comm=sugov:0 prev_pid=568 prev_prio=49 prev_state=R+ ==>
+//            next_comm=migration/0 next_pid=13 next_prio=0
+//      migration/0-13    [000] d..3   112.280511: sched_switch:
+//      prev_comm=migration/0 prev_pid=13 prev_prio=0 prev_state=S ==>
+//      next_comm=sugov:0 next_pid=568 next_prio=49
+//            <...>-568   [000] d..3   112.280563: sched_switch:
+//            prev_comm=sugov:0 prev_pid=568 prev_prio=49 prev_state=S ==>
+//            next_comm=dex2oat next_pid=7988 next_prio=130
+//            <...>-7988  [000] d..3   112.280740: sched_switch:
+//            prev_comm=dex2oat prev_pid=7988 prev_prio=130 prev_state=D ==>
+//            next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.281141: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=android.hardwar next_pid=2770 next_prio=120
+//            <...>-2770  [000] d..3   112.281182: sched_switch:
+//            prev_comm=android.hardwar prev_pid=2770 prev_prio=120 prev_state=S
+//            ==> next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.281576: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=android.hardwar next_pid=2770 next_prio=120
+//            <...>-2770  [000] d..3   112.281602: sched_switch:
+//            prev_comm=android.hardwar prev_pid=2770 prev_prio=120 prev_state=S
+//            ==> next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.282168: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=android.hardwar next_pid=2770 next_prio=120
+//            <...>-2770  [000] d..3   112.282193: sched_switch:
+//            prev_comm=android.hardwar prev_pid=2770 prev_prio=120 prev_state=S
+//            ==> next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.282890: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=android.hardwar next_pid=2770 next_prio=120
+//            <...>-2770  [000] d..3   112.282914: sched_switch:
+//            prev_comm=android.hardwar prev_pid=2770 prev_prio=120 prev_state=S
+//            ==> next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.284356: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=DispSync next_pid=623 next_prio=97
+//         DispSync-623   [000] d..3   112.284398: sched_switch:
+//         prev_comm=DispSync prev_pid=623 prev_prio=97 prev_state=S ==>
+//         next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.284434: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=surfaceflinger next_pid=587 next_prio=98
+//   surfaceflinger-587   [000] d..3   112.284570: sched_switch:
+//   prev_comm=surfaceflinger prev_pid=587 prev_prio=98 prev_state=S ==>
+//   next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.289826: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=kworker/u16:6 next_pid=356 next_prio=120
+//            <...>-356   [000] d..3   112.289839: sched_switch:
+//            prev_comm=kworker/u16:6 prev_pid=356 prev_prio=120 prev_state=S
+//            ==> next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.290021: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=kworker/u16:6 next_pid=356 next_prio=120
+//            <...>-356   [000] d..3   112.290061: sched_switch:
+//            prev_comm=kworker/u16:6 prev_pid=356 prev_prio=120 prev_state=S
+//            ==> next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.290949: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=kworker/u16:6 next_pid=356 next_prio=120
+//            <...>-356   [000] d..3   112.290986: sched_switch:
+//            prev_comm=kworker/u16:6 prev_pid=356 prev_prio=120 prev_state=S
+//            ==> next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.291102: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=kworker/u16:6 next_pid=356 next_prio=120
+//            <...>-356   [000] d..3   112.291111: sched_switch:
+//            prev_comm=kworker/u16:6 prev_pid=356 prev_prio=120 prev_state=S
+//            ==> next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.291408: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=kworker/u16:6 next_pid=356 next_prio=120
+//            <...>-356   [000] d..3   112.291416: sched_switch:
+//            prev_comm=kworker/u16:6 prev_pid=356 prev_prio=120 prev_state=S
+//            ==> next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.291435: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=kworker/u16:6 next_pid=356 next_prio=120
+//            <...>-356   [000] d..3   112.291442: sched_switch:
+//            prev_comm=kworker/u16:6 prev_pid=356 prev_prio=120 prev_state=S
+//            ==> next_comm=swapper/0 next_pid=0 next_prio=120
+//           <idle>-0     [000] d..3   112.291512: sched_switch:
+//           prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==>
+//           next_comm=kworker/u16:6 next_pid=356 next_prio=120
+
+ExamplePage g_full_page_sched_switch{
+    "synthetic",
+    R"(
+00000000: 31f2 7622 1a00 0000 b40f 0000 0000 0000  1.v"............
+00000010: 1e00 0000 0000 0000 1000 0000 2f00 0103  ............/...
+00000020: 140d 0000 4a69 7420 7468 7265 6164 2070  ....Jit thread p
+00000030: 6f6f 6c00 140d 0000 8100 0000 0008 0000  ool.............
+00000040: 0000 0000 4576 656e 7454 6872 6561 6400  ....EventThread.
+00000050: 6572 0000 7002 0000 6100 0000 f057 0e00  er..p...a....W..
+00000060: 2f00 0103 7002 0000 4576 656e 7454 6872  /...p...EventThr
+00000070: 6561 6400 6572 0000 7002 0000 6100 0000  ead.er..p...a...
+00000080: 0100 0000 0000 0000 4a69 7420 7468 7265  ........Jit thre
+00000090: 6164 2070 6f6f 6c00 140d 0000 8100 0000  ad pool.........
+000000a0: 50c2 0910 2f00 0103 140d 0000 4a69 7420  P.../.......Jit 
+000000b0: 7468 7265 6164 2070 6f6f 6c00 140d 0000  thread pool.....
+000000c0: 8100 0000 0100 0000 0000 0000 7377 6170  ............swap
+000000d0: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+000000e0: 7800 0000 901a c80e 2f00 0103 0000 0000  x......./.......
+000000f0: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000100: 0000 0000 7800 0000 0000 0000 0000 0000  ....x...........
+00000110: 4469 7370 5379 6e63 0069 6e67 6572 0000  DispSync.inger..
+00000120: 6f02 0000 6100 0000 1064 1e00 2f00 0103  o...a....d../...
+00000130: 6f02 0000 4469 7370 5379 6e63 0069 6e67  o...DispSync.ing
+00000140: 6572 0000 6f02 0000 6100 0000 0100 0000  er..o...a.......
+00000150: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000160: 0000 0000 0000 0000 7800 0000 9074 8600  ........x....t..
+00000170: 2f00 0103 0000 0000 7377 6170 7065 722f  /.......swapper/
+00000180: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000190: 0000 0000 0000 0000 4576 656e 7454 6872  ........EventThr
+000001a0: 6561 6400 6572 0000 7002 0000 6100 0000  ead.er..p...a...
+000001b0: d071 0b00 2f00 0103 7002 0000 4576 656e  .q../...p...Even
+000001c0: 7454 6872 6561 6400 6572 0000 7002 0000  tThread.er..p...
+000001d0: 6100 0000 0100 0000 0000 0000 7377 6170  a...........swap
+000001e0: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+000001f0: 7800 0000 10cd 4504 2f00 0103 0000 0000  x.....E./.......
+00000200: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000210: 0000 0000 7800 0000 0000 0000 0000 0000  ....x...........
+00000220: 7375 676f 763a 3000 0000 0000 0000 0000  sugov:0.........
+00000230: 3802 0000 3100 0000 30d6 1300 2f00 0103  8...1...0.../...
+00000240: 3802 0000 7375 676f 763a 3000 0000 0000  8...sugov:0.....
+00000250: 0000 0000 3802 0000 3100 0000 0100 0000  ....8...1.......
+00000260: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000270: 0000 0000 0000 0000 7800 0000 3049 a202  ........x...0I..
+00000280: 2f00 0103 0000 0000 7377 6170 7065 722f  /.......swapper/
+00000290: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+000002a0: 0000 0000 0000 0000 4469 7370 5379 6e63  ........DispSync
+000002b0: 0069 6e67 6572 0000 6f02 0000 6100 0000  .inger..o...a...
+000002c0: d07a 1000 2f00 0103 6f02 0000 4469 7370  .z../...o...Disp
+000002d0: 5379 6e63 0069 6e67 6572 0000 6f02 0000  Sync.inger..o...
+000002e0: 6100 0000 0100 0000 0000 0000 7377 6170  a...........swap
+000002f0: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000300: 7800 0000 d085 1100 2f00 0103 0000 0000  x......./.......
+00000310: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000320: 0000 0000 7800 0000 0000 0000 0000 0000  ....x...........
+00000330: 7375 7266 6163 6566 6c69 6e67 6572 0000  surfaceflinger..
+00000340: 4b02 0000 6200 0000 907a f000 2f00 0103  K...b....z../...
+00000350: 4b02 0000 7375 7266 6163 6566 6c69 6e67  K...surfacefling
+00000360: 6572 0000 4b02 0000 6200 0000 0100 0000  er..K...b.......
+00000370: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000380: 0000 0000 0000 0000 7800 0000 305a 6400  ........x...0Zd.
+00000390: 2f00 0103 0000 0000 7377 6170 7065 722f  /.......swapper/
+000003a0: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+000003b0: 0000 0000 0000 0000 6d64 7373 5f66 6230  ........mdss_fb0
+000003c0: 0000 0000 0000 0000 5714 0000 5300 0000  ........W...S...
+000003d0: 10b1 9e03 2f00 0103 5714 0000 6d64 7373  ..../...W...mdss
+000003e0: 5f66 6230 0000 0000 0000 0000 5714 0000  _fb0........W...
+000003f0: 5300 0000 0200 0000 0000 0000 6b73 6f66  S...........ksof
+00000400: 7469 7271 642f 3000 0000 0000 0300 0000  tirqd/0.........
+00000410: 7800 0000 90bb 9900 2f00 0103 0300 0000  x......./.......
+00000420: 6b73 6f66 7469 7271 642f 3000 0000 0000  ksoftirqd/0.....
+00000430: 0300 0000 7800 0000 0100 0000 0000 0000  ....x...........
+00000440: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000450: 0000 0000 7800 0000 701e 5305 2f00 0103  ....x...p.S./...
+00000460: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000470: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+00000480: 0000 0000 6b77 6f72 6b65 722f 7531 363a  ....kworker/u16:
+00000490: 3600 0000 6401 0000 7800 0000 90a1 2900  6...d...x.....).
+000004a0: 2f00 0103 6401 0000 6b77 6f72 6b65 722f  /...d...kworker/
+000004b0: 7531 363a 3600 0000 6401 0000 7800 0000  u16:6...d...x...
+000004c0: 0200 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+000004d0: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+000004e0: b0e5 4f04 2f00 0103 0000 0000 7377 6170  ..O./.......swap
+000004f0: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000500: 7800 0000 0000 0000 0000 0000 4269 6e64  x...........Bind
+00000510: 6572 3a32 3136 385f 3135 0000 e614 0000  er:2168_15......
+00000520: 7800 0000 b0bd 7c00 2f00 0103 e614 0000  x.....|./.......
+00000530: 4269 6e64 6572 3a32 3136 385f 3135 0000  Binder:2168_15..
+00000540: e614 0000 7800 0000 0100 0000 0000 0000  ....x...........
+00000550: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000560: 0000 0000 7800 0000 d0bd 7e01 2f00 0103  ....x.....~./...
+00000570: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000580: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+00000590: 0000 0000 6b77 6f72 6b65 722f 7531 363a  ....kworker/u16:
+000005a0: 3900 0000 e204 0000 7800 0000 7016 0800  9.......x...p...
+000005b0: 2f00 0103 e204 0000 6b77 6f72 6b65 722f  /.......kworker/
+000005c0: 7531 363a 3900 0000 e204 0000 7800 0000  u16:9.......x...
+000005d0: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+000005e0: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+000005f0: 1004 5200 2f00 0103 0000 0000 7377 6170  ..R./.......swap
+00000600: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000610: 7800 0000 0000 0000 0000 0000 6b77 6f72  x...........kwor
+00000620: 6b65 722f 7531 363a 3900 0000 e204 0000  ker/u16:9.......
+00000630: 7800 0000 d0db 0700 2f00 0103 e204 0000  x......./.......
+00000640: 6b77 6f72 6b65 722f 7531 363a 3900 0000  kworker/u16:9...
+00000650: e204 0000 7800 0000 0100 0000 0000 0000  ....x...........
+00000660: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000670: 0000 0000 7800 0000 b0a2 8c00 2f00 0103  ....x......./...
+00000680: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000690: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+000006a0: 0000 0000 6b77 6f72 6b65 722f 7531 363a  ....kworker/u16:
+000006b0: 3900 0000 e204 0000 7800 0000 d02b 0400  9.......x....+..
+000006c0: 2f00 0103 e204 0000 6b77 6f72 6b65 722f  /.......kworker/
+000006d0: 7531 363a 3900 0000 e204 0000 7800 0000  u16:9.......x...
+000006e0: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+000006f0: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000700: d064 ef05 2f00 0103 0000 0000 7377 6170  .d../.......swap
+00000710: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000720: 7800 0000 0000 0000 0000 0000 4469 7370  x...........Disp
+00000730: 5379 6e63 0069 6e67 6572 0000 6f02 0000  Sync.inger..o...
+00000740: 6100 0000 f07d 1b00 2f00 0103 6f02 0000  a....}../...o...
+00000750: 4469 7370 5379 6e63 0069 6e67 6572 0000  DispSync.inger..
+00000760: 6f02 0000 6100 0000 0100 0000 0000 0000  o...a...........
+00000770: 6b73 6f66 7469 7271 642f 3000 0000 0000  ksoftirqd/0.....
+00000780: 0300 0000 7800 0000 304c 2000 2f00 0103  ....x...0L ./...
+00000790: 0300 0000 6b73 6f66 7469 7271 642f 3000  ....ksoftirqd/0.
+000007a0: 0000 0000 0300 0000 7800 0000 0100 0000  ........x.......
+000007b0: 0000 0000 6465 7832 6f61 7400 3935 5f33  ....dex2oat.95_3
+000007c0: 0000 0000 341f 0000 8200 0000 700b 0700  ....4.......p...
+000007d0: 2f00 0103 341f 0000 6465 7832 6f61 7400  /...4...dex2oat.
+000007e0: 3935 5f33 0000 0000 341f 0000 8200 0000  95_3....4.......
+000007f0: 0000 0000 0000 0000 7375 676f 763a 3000  ........sugov:0.
+00000800: 0000 0000 0000 0000 3802 0000 3100 0000  ........8...1...
+00000810: 50b0 0600 2f00 0103 3802 0000 7375 676f  P.../...8...sugo
+00000820: 763a 3000 0000 0000 0000 0000 3802 0000  v:0.........8...
+00000830: 3100 0000 0008 0000 0000 0000 6d69 6772  1...........migr
+00000840: 6174 696f 6e2f 3000 0000 0000 0d00 0000  ation/0.........
+00000850: 0000 0000 d09c 0600 2f00 0103 0d00 0000  ......../.......
+00000860: 6d69 6772 6174 696f 6e2f 3000 0000 0000  migration/0.....
+00000870: 0d00 0000 0000 0000 0100 0000 0000 0000  ................
+00000880: 7375 676f 763a 3000 0000 0000 0000 0000  sugov:0.........
+00000890: 3802 0000 3100 0000 7061 1900 2f00 0103  8...1...pa../...
+000008a0: 3802 0000 7375 676f 763a 3000 0000 0000  8...sugov:0.....
+000008b0: 0000 0000 3802 0000 3100 0000 0100 0000  ....8...1.......
+000008c0: 0000 0000 6465 7832 6f61 7400 3935 5f33  ....dex2oat.95_3
+000008d0: 0000 0000 341f 0000 8200 0000 f03c 5600  ....4........<V.
+000008e0: 2f00 0103 341f 0000 6465 7832 6f61 7400  /...4...dex2oat.
+000008f0: 3935 5f33 0000 0000 341f 0000 8200 0000  95_3....4.......
+00000900: 0200 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+00000910: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000920: 5013 c400 2f00 0103 0000 0000 7377 6170  P.../.......swap
+00000930: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000940: 7800 0000 0000 0000 0000 0000 616e 6472  x...........andr
+00000950: 6f69 642e 6861 7264 7761 7200 d20a 0000  oid.hardwar.....
+00000960: 7800 0000 30c9 1300 2f00 0103 d20a 0000  x...0.../.......
+00000970: 616e 6472 6f69 642e 6861 7264 7761 7200  android.hardwar.
+00000980: d20a 0000 7800 0000 0100 0000 0000 0000  ....x...........
+00000990: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+000009a0: 0000 0000 7800 0000 7097 c000 2f00 0103  ....x...p.../...
+000009b0: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+000009c0: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+000009d0: 0000 0000 616e 6472 6f69 642e 6861 7264  ....android.hard
+000009e0: 7761 7200 d20a 0000 7800 0000 305c 0c00  war.....x...0\..
+000009f0: 2f00 0103 d20a 0000 616e 6472 6f69 642e  /.......android.
+00000a00: 6861 7264 7761 7200 d20a 0000 7800 0000  hardwar.....x...
+00000a10: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+00000a20: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000a30: d0aa 1401 2f00 0103 0000 0000 7377 6170  ..../.......swap
+00000a40: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000a50: 7800 0000 0000 0000 0000 0000 616e 6472  x...........andr
+00000a60: 6f69 642e 6861 7264 7761 7200 d20a 0000  oid.hardwar.....
+00000a70: 7800 0000 903b 0c00 2f00 0103 d20a 0000  x....;../.......
+00000a80: 616e 6472 6f69 642e 6861 7264 7761 7200  android.hardwar.
+00000a90: d20a 0000 7800 0000 0100 0000 0000 0000  ....x...........
+00000aa0: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000ab0: 0000 0000 7800 0000 f024 5401 2f00 0103  ....x....$T./...
+00000ac0: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000ad0: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+00000ae0: 0000 0000 616e 6472 6f69 642e 6861 7264  ....android.hard
+00000af0: 7761 7200 d20a 0000 7800 0000 f0f3 0b00  war.....x.......
+00000b00: 2f00 0103 d20a 0000 616e 6472 6f69 642e  /.......android.
+00000b10: 6861 7264 7761 7200 d20a 0000 7800 0000  hardwar.....x...
+00000b20: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+00000b30: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000b40: d0b5 bf02 2f00 0103 0000 0000 7377 6170  ..../.......swap
+00000b50: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000b60: 7800 0000 0000 0000 0000 0000 4469 7370  x...........Disp
+00000b70: 5379 6e63 0069 6e67 6572 0000 6f02 0000  Sync.inger..o...
+00000b80: 6100 0000 90cd 1400 2f00 0103 6f02 0000  a......./...o...
+00000b90: 4469 7370 5379 6e63 0069 6e67 6572 0000  DispSync.inger..
+00000ba0: 6f02 0000 6100 0000 0100 0000 0000 0000  o...a...........
+00000bb0: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000bc0: 0000 0000 7800 0000 50a6 1100 2f00 0103  ....x...P.../...
+00000bd0: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000be0: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+00000bf0: 0000 0000 7375 7266 6163 6566 6c69 6e67  ....surfacefling
+00000c00: 6572 0000 4b02 0000 6200 0000 b04c 4200  er..K...b....LB.
+00000c10: 2f00 0103 4b02 0000 7375 7266 6163 6566  /...K...surfacef
+00000c20: 6c69 6e67 6572 0000 4b02 0000 6200 0000  linger..K...b...
+00000c30: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+00000c40: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000c50: b025 060a 2f00 0103 0000 0000 7377 6170  .%../.......swap
+00000c60: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000c70: 7800 0000 0000 0000 0000 0000 6b77 6f72  x...........kwor
+00000c80: 6b65 722f 7531 363a 3600 0000 6401 0000  ker/u16:6...d...
+00000c90: 7800 0000 d0b6 0600 2f00 0103 6401 0000  x......./...d...
+00000ca0: 6b77 6f72 6b65 722f 7531 363a 3600 0000  kworker/u16:6...
+00000cb0: 6401 0000 7800 0000 0100 0000 0000 0000  d...x...........
+00000cc0: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000cd0: 0000 0000 7800 0000 f0a0 5800 2f00 0103  ....x.....X./...
+00000ce0: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000cf0: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+00000d00: 0000 0000 6b77 6f72 6b65 722f 7531 363a  ....kworker/u16:
+00000d10: 3600 0000 6401 0000 7800 0000 f07a 1300  6...d...x....z..
+00000d20: 2f00 0103 6401 0000 6b77 6f72 6b65 722f  /...d...kworker/
+00000d30: 7531 363a 3600 0000 6401 0000 7800 0000  u16:6...d...x...
+00000d40: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+00000d50: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000d60: b080 b101 2f00 0103 0000 0000 7377 6170  ..../.......swap
+00000d70: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000d80: 7800 0000 0000 0000 0000 0000 6b77 6f72  x...........kwor
+00000d90: 6b65 722f 7531 363a 3600 0000 6401 0000  ker/u16:6...d...
+00000da0: 7800 0000 103c 1200 2f00 0103 6401 0000  x....<../...d...
+00000db0: 6b77 6f72 6b65 722f 7531 363a 3600 0000  kworker/u16:6...
+00000dc0: 6401 0000 7800 0000 0100 0000 0000 0000  d...x...........
+00000dd0: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000de0: 0000 0000 7800 0000 50ea 3800 2f00 0103  ....x...P.8./...
+00000df0: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000e00: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+00000e10: 0000 0000 6b77 6f72 6b65 722f 7531 363a  ....kworker/u16:
+00000e20: 3600 0000 6401 0000 7800 0000 5032 0400  6...d...x...P2..
+00000e30: 2f00 0103 6401 0000 6b77 6f72 6b65 722f  /...d...kworker/
+00000e40: 7531 363a 3600 0000 6401 0000 7800 0000  u16:6...d...x...
+00000e50: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+00000e60: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000e70: 70f5 9000 2f00 0103 0000 0000 7377 6170  p.../.......swap
+00000e80: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000e90: 7800 0000 0000 0000 0000 0000 6b77 6f72  x...........kwor
+00000ea0: 6b65 722f 7531 363a 3600 0000 6401 0000  ker/u16:6...d...
+00000eb0: 7800 0000 10d7 0300 2f00 0103 6401 0000  x......./...d...
+00000ec0: 6b77 6f72 6b65 722f 7531 363a 3600 0000  kworker/u16:6...
+00000ed0: 6401 0000 7800 0000 0100 0000 0000 0000  d...x...........
+00000ee0: 7377 6170 7065 722f 3000 0000 0000 0000  swapper/0.......
+00000ef0: 0000 0000 7800 0000 907c 0900 2f00 0103  ....x....|../...
+00000f00: 0000 0000 7377 6170 7065 722f 3000 0000  ....swapper/0...
+00000f10: 0000 0000 0000 0000 7800 0000 0000 0000  ........x.......
+00000f20: 0000 0000 6b77 6f72 6b65 722f 7531 363a  ....kworker/u16:
+00000f30: 3600 0000 6401 0000 7800 0000 7082 0300  6...d...x...p...
+00000f40: 2f00 0103 6401 0000 6b77 6f72 6b65 722f  /...d...kworker/
+00000f50: 7531 363a 3600 0000 6401 0000 7800 0000  u16:6...d...x...
+00000f60: 0100 0000 0000 0000 7377 6170 7065 722f  ........swapper/
+00000f70: 3000 0000 0000 0000 0000 0000 7800 0000  0...........x...
+00000f80: f0ec 2100 2f00 0103 0000 0000 7377 6170  ..!./.......swap
+00000f90: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
+00000fa0: 7800 0000 0000 0000 0000 0000 6b77 6f72  x...........kwor
+00000fb0: 6b65 722f 7531 363a 3600 0000 6401 0000  ker/u16:6...d...
+00000fc0: 7800 0000 0000 0000 0000 0000 0000 0000  x...............
+00000fd0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000fe0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000ff0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+    )",
+};
+
+TEST(CpuReaderTest, ParseFullPageSchedSwitch) {
+  const ExamplePage* test_case = &g_full_page_sched_switch;
+
+  BundleProvider bundle_provider(base::kPageSize);
+  ProtoTranslationTable* table = GetTable(test_case->name);
+  auto page = PageFromXxd(test_case->data);
+
+  EventFilter filter(*table, std::set<std::string>({"sched_switch"}));
+
+  ASSERT_TRUE(CpuReader::ParsePage(42 /* cpu number */, page.get(), &filter,
+                                   bundle_provider.writer(), table));
+
+  auto bundle = bundle_provider.ParseProto();
+  ASSERT_TRUE(bundle);
+  EXPECT_EQ(bundle->cpu(), 42ul);
+  EXPECT_EQ(bundle->event().size(), 59);
+}
+
 }  // namespace perfetto
diff --git a/src/ftrace_reader/test/cpu_reader_support.cc b/src/ftrace_reader/test/cpu_reader_support.cc
new file mode 100644
index 0000000..7f22722
--- /dev/null
+++ b/src/ftrace_reader/test/cpu_reader_support.cc
@@ -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.
+ */
+
+#include "cpu_reader_support.h"
+
+#include "src/ftrace_reader/ftrace_procfs.h"
+
+namespace perfetto {
+namespace {
+
+const size_t kPageSize = 4096;
+
+std::map<std::string, std::unique_ptr<ProtoTranslationTable>>* g_tables;
+
+}  // namespace
+
+ProtoTranslationTable* GetTable(const std::string& name) {
+  if (!g_tables)
+    g_tables =
+        new std::map<std::string, std::unique_ptr<ProtoTranslationTable>>();
+  if (!g_tables->count(name)) {
+    std::string path = "src/ftrace_reader/test/data/" + name + "/";
+    FtraceProcfs ftrace(path);
+    auto table = ProtoTranslationTable::Create(&ftrace, GetStaticEventInfo(),
+                                               GetStaticCommonFieldsInfo());
+    g_tables->emplace(name, std::move(table));
+  }
+  return g_tables->at(name).get();
+}
+
+std::unique_ptr<uint8_t[]> PageFromXxd(const std::string& text) {
+  auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[kPageSize]);
+  const char* ptr = text.data();
+  memset(buffer.get(), 0xfa, kPageSize);
+  uint8_t* out = buffer.get();
+  while (*ptr != '\0') {
+    if (*(ptr++) != ':')
+      continue;
+    for (int i = 0; i < 8; i++) {
+      PERFETTO_CHECK(text.size() >=
+                     static_cast<size_t>((ptr - text.data()) + 5));
+      PERFETTO_CHECK(*(ptr++) == ' ');
+      int n = sscanf(ptr, "%02hhx%02hhx", out, out + 1);
+      PERFETTO_CHECK(n == 2);
+      out += n;
+      ptr += 4;
+    }
+    while (*ptr != '\n')
+      ptr++;
+  }
+  return buffer;
+}
+
+}  // namespace perfetto
diff --git a/src/ftrace_reader/test/cpu_reader_support.h b/src/ftrace_reader/test/cpu_reader_support.h
new file mode 100644
index 0000000..5e27aa8
--- /dev/null
+++ b/src/ftrace_reader/test/cpu_reader_support.h
@@ -0,0 +1,44 @@
+/*
+ * 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 SRC_FTRACE_READER_TEST_CPU_READER_SUPPORT_H_
+#define SRC_FTRACE_READER_TEST_CPU_READER_SUPPORT_H_
+
+#include <memory>
+#include <string>
+
+#include "src/ftrace_reader/proto_translation_table.h"
+
+namespace perfetto {
+
+struct ExamplePage {
+  // The name of the format file set used in the collection of this example
+  // page. Should name a directory under src/ftrace_reader/test/data
+  const char* name;
+  // The non-zero prefix of xxd'ing the page.
+  const char* data;
+};
+
+// Create a ProtoTranslationTable uing the fomat files in
+// directory |name|. Caches the table for subsequent lookups.
+ProtoTranslationTable* GetTable(const std::string& name);
+
+// Convert xxd output into binary data.
+std::unique_ptr<uint8_t[]> PageFromXxd(const std::string& text);
+
+}  // namespace perfetto
+
+#endif  // SRC_FTRACE_READER_TEST_CPU_READER_SUPPORT_H_
diff --git a/src/ftrace_reader/test/scattered_stream_null_delegate.cc b/src/ftrace_reader/test/scattered_stream_null_delegate.cc
new file mode 100644
index 0000000..562a3db
--- /dev/null
+++ b/src/ftrace_reader/test/scattered_stream_null_delegate.cc
@@ -0,0 +1,35 @@
+/*
+ * 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 "src/ftrace_reader/test/scattered_stream_null_delegate.h"
+
+namespace perfetto {
+
+// An implementation of ScatteredStreamWriter::Delegate which always returns
+// the same bit of memory (to better measure performance of users of
+// ScatteredStreamWriter without noisy allocations).
+
+ScatteredStreamNullDelegate::ScatteredStreamNullDelegate(size_t chunk_size)
+    : chunk_size_(chunk_size),
+      chunk_(std::unique_ptr<uint8_t[]>(new uint8_t[chunk_size_])){};
+
+ScatteredStreamNullDelegate::~ScatteredStreamNullDelegate() {}
+
+protozero::ContiguousMemoryRange ScatteredStreamNullDelegate::GetNewBuffer() {
+  return {chunk_.get(), chunk_.get() + chunk_size_};
+}
+
+}  // namespace perfetto
diff --git a/src/ftrace_reader/test/scattered_stream_null_delegate.h b/src/ftrace_reader/test/scattered_stream_null_delegate.h
new file mode 100644
index 0000000..41e2bd8
--- /dev/null
+++ b/src/ftrace_reader/test/scattered_stream_null_delegate.h
@@ -0,0 +1,44 @@
+/*
+ * 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 SRC_FTRACE_READER_TEST_SCATTERED_STREAM_NULL_DELEGATE_H_
+#define SRC_FTRACE_READER_TEST_SCATTERED_STREAM_NULL_DELEGATE_H_
+
+#include <memory>
+#include <vector>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/protozero/scattered_stream_writer.h"
+
+namespace perfetto {
+
+class ScatteredStreamNullDelegate
+    : public protozero::ScatteredStreamWriter::Delegate {
+ public:
+  explicit ScatteredStreamNullDelegate(size_t chunk_size);
+  ~ScatteredStreamNullDelegate() override;
+
+  // protozero::ScatteredStreamWriter::Delegate implementation.
+  protozero::ContiguousMemoryRange GetNewBuffer() override;
+
+ private:
+  const size_t chunk_size_;
+  std::unique_ptr<uint8_t[]> chunk_;
+};
+
+}  // namespace perfetto
+
+#endif  // SRC_FTRACE_READER_TEST_SCATTERED_STREAM_NULL_DELEGATE_H_
diff --git a/src/tracing/test/hello_world_benchmark.cc b/src/tracing/test/hello_world_benchmark.cc
index 85476ec..c554de9 100644
--- a/src/tracing/test/hello_world_benchmark.cc
+++ b/src/tracing/test/hello_world_benchmark.cc
@@ -7,12 +7,3 @@
 // Register the function as a benchmark
 BENCHMARK(BM_StringCreation);
 
-// Define another benchmark
-static void BM_StringCopy(benchmark::State& state) {
-  std::string x = "hello";
-  while (state.KeepRunning())
-    std::string copy(x);  // NOLINT
-}
-BENCHMARK(BM_StringCopy);
-
-BENCHMARK_MAIN();
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 6ab056e..a578f64 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -83,3 +83,16 @@
     "task_runner_thread.h",
   ]
 }
+
+if (!build_with_chromium) {
+  source_set("benchmark_main") {
+    testonly = true
+    deps = [
+      "../../gn:default_deps",
+      "//buildtools:benchmark",
+    ]
+    sources = [
+      "benchmark_main.cc",
+    ]
+  }
+}
diff --git a/test/benchmark_main.cc b/test/benchmark_main.cc
new file mode 100644
index 0000000..f904cfc
--- /dev/null
+++ b/test/benchmark_main.cc
@@ -0,0 +1,17 @@
+// 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 "benchmark/benchmark.h"
+
+BENCHMARK_MAIN();