Merge "[ui] Add a simple plugins management page." into main
diff --git a/Android.bp b/Android.bp
index cebcd7b..6cb6274 100644
--- a/Android.bp
+++ b/Android.bp
@@ -10948,6 +10948,11 @@
],
}
+// GN: //src/trace_processor/db:compare
+filegroup {
+ name: "perfetto_src_trace_processor_db_compare",
+}
+
// GN: //src/trace_processor/db:db
filegroup {
name: "perfetto_src_trace_processor_db_db",
@@ -13813,6 +13818,7 @@
":perfetto_src_shared_lib_unittests",
":perfetto_src_trace_processor_containers_containers",
":perfetto_src_trace_processor_containers_unittests",
+ ":perfetto_src_trace_processor_db_compare",
":perfetto_src_trace_processor_db_db",
":perfetto_src_trace_processor_db_storage_fake_storage",
":perfetto_src_trace_processor_db_storage_storage",
diff --git a/gn/standalone/libc++/BUILD.gn b/gn/standalone/libc++/BUILD.gn
index 49d91ba..c6ae0c1 100644
--- a/gn/standalone/libc++/BUILD.gn
+++ b/gn/standalone/libc++/BUILD.gn
@@ -21,10 +21,11 @@
"_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
]
if (is_debug) {
- # libc++ has two levels of debug mode. Setting _LIBCPP_DEBUG to zero
- # enables most assertions. Setting it to one additionally enables iterator
- # debugging, but that seems to require some extra link-time dependencies.
- # See https://libcxx.llvm.org/docs/DesignDocs/DebugMode.html
+ # Enable "lightweight" assertions in libc++ (e.g. bounds checking, empty
+ # optional dereferencing etc) with _LIBCPP_ENABLE_ASSERTIONS but do not
+ # enable iterator debugging with _LIBCPP_DEBUG (which can be very
+ # expensive).
+ defines += [ "_LIBCPP_ENABLE_ASSERTIONS=1" ]
defines += [ "_LIBCPP_DEBUG=0" ]
}
cflags_cc = [
diff --git a/include/perfetto/ext/tracing/core/shared_memory_abi.h b/include/perfetto/ext/tracing/core/shared_memory_abi.h
index 4e05599..dd146ea 100644
--- a/include/perfetto/ext/tracing/core/shared_memory_abi.h
+++ b/include/perfetto/ext/tracing/core/shared_memory_abi.h
@@ -153,8 +153,10 @@
// See PageLayout below.
static constexpr size_t kMaxChunksPerPage = 14;
- // Each TracePacket in the Chunk is prefixed by a 4 bytes redundant VarInt
- // (see proto_utils.h) stating its size.
+ // Each TracePacket fragment in the Chunk is prefixed by a VarInt stating its
+ // size that is up to 4 bytes long. Since the size is often known after the
+ // fragment has been filled, the VarInt is often redundantly encoded (see
+ // proto_utils.h) to be exactly 4 bytes.
static constexpr size_t kPacketHeaderSize = 4;
// TraceWriter specifies this invalid packet/fragment size to signal to the
@@ -416,19 +418,6 @@
return packets.count;
}
- // Increases |packets.count| to the given |packet_count|, but only if
- // |packet_count| is larger than the current value of |packets.count|.
- // Returns the new packet count. Same atomicity guarantees as
- // IncrementPacketCount().
- uint16_t IncreasePacketCountTo(uint16_t packet_count) {
- ChunkHeader* chunk_header = header();
- auto packets = chunk_header->packets.load(std::memory_order_relaxed);
- if (packets.count < packet_count)
- packets.count = packet_count & ChunkHeader::Packets::kMaxCount;
- chunk_header->packets.store(packets, std::memory_order_release);
- return packets.count;
- }
-
// Flags are cleared by TryAcquireChunk(), by passing the new header for
// the chunk, or through ClearNeedsPatchingFlag.
void SetFlag(ChunkHeader::Flags flag) {
diff --git a/python/perfetto/prebuilts/manifests/trace_processor_shell.py b/python/perfetto/prebuilts/manifests/trace_processor_shell.py
index 0196c4b..6fe447b 100755
--- a/python/perfetto/prebuilts/manifests/trace_processor_shell.py
+++ b/python/perfetto/prebuilts/manifests/trace_processor_shell.py
@@ -1,15 +1,15 @@
-# This file has been generated by: tools/roll-prebuilts v40.0
+# This file has been generated by: tools/roll-prebuilts 3e53e144bee271ec558363df2e561a77d7e0b789
TRACE_PROCESSOR_SHELL_MANIFEST = [{
'arch':
'mac-amd64',
'file_name':
'trace_processor_shell',
'file_size':
- 9978200,
+ 10142120,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-amd64/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-amd64/trace_processor_shell',
'sha256':
- 'f3e21eb29fb51cb2ea9b81b69132c5ae93ce3276c57ccd27fcf7c675306b4e41',
+ '44585789d420d0bc38edc3dd6fbade4c4a718dc535fb68ac7a2449bf1a251f30',
'platform':
'darwin',
'machine': ['x86_64']
@@ -19,11 +19,11 @@
'file_name':
'trace_processor_shell',
'file_size':
- 8493976,
+ 8659128,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-arm64/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-arm64/trace_processor_shell',
'sha256':
- '84f35765141374b8d883813ac533e0c004cf72d1c6f05aef0c973364ff541eb9',
+ 'bccca60b99fb2c587503a6430e0b15204ebeddb97607006d54f203e64ac923af',
'platform':
'darwin',
'machine': ['arm64']
@@ -33,11 +33,11 @@
'file_name':
'trace_processor_shell',
'file_size':
- 9830856,
+ 9987880,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-amd64/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-amd64/trace_processor_shell',
'sha256':
- 'b3dc0a9c641b84a57fa5d59637921ae2237e4f05b1778341a691df220faf0cd7',
+ '3510cfc89e627a95ede2d06e77d1ddd70d31ef99d0d213d1fbaba4f438030e4c',
'platform':
'linux',
'machine': ['x86_64']
@@ -47,11 +47,11 @@
'file_name':
'trace_processor_shell',
'file_size':
- 7231096,
+ 7389416,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm/trace_processor_shell',
'sha256':
- 'a21252830fb1bbb7b3fd9665ce6e70920cffa6b1e72c16589c90896c002c3348',
+ '2a87d3587e9a756ea486746ba08e7535dacf8872b1d2081e9381a612668d154d',
'platform':
'linux',
'machine': ['armv6l', 'armv7l', 'armv8l']
@@ -61,11 +61,11 @@
'file_name':
'trace_processor_shell',
'file_size':
- 9238056,
+ 9396856,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm64/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm64/trace_processor_shell',
'sha256':
- 'f77519ec19743ec2c22ed78fe3a20106a482a28d77c4154378af108c5f7bdd4a',
+ '42738a5aa187fe7644d87361fcf9854459f3d46a301026c9ac76ac4bf0ec9d3e',
'platform':
'linux',
'machine': ['aarch64']
@@ -75,55 +75,55 @@
'file_name':
'trace_processor_shell',
'file_size':
- 6870968,
+ 7018688,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm/trace_processor_shell',
'sha256':
- '2c7055fb44085ec60ad8bb970d495c9c88070fce08902f11fcd44e0ae3369876'
+ '9d8247c09b82835dc5019fed2f41e8844162a8cbf520e4243111852d6398911b'
}, {
'arch':
'android-arm64',
'file_name':
'trace_processor_shell',
'file_size':
- 8414568,
+ 8578936,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm64/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm64/trace_processor_shell',
'sha256':
- 'd8ca0dc2bab7ea604a6721f0ac0e2b433b43261f247c6c98c510dc17aafe5a72'
+ '91405004e1a47b1170eb32315f3d0a5b287bc71cb856e7403fad0f02e8b4dfd1'
}, {
'arch':
'android-x86',
'file_name':
'trace_processor_shell',
'file_size':
- 9328508,
+ 9492612,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x86/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x86/trace_processor_shell',
'sha256':
- 'de6a6ea45769888e59a1678d37b6e355b27b834d34a0b9e4980a942d333b88cc'
+ '01364fc6fb485b20d838326462239d14c8f2daf1e7dde524b2cba4fd5acb8a73'
}, {
'arch':
'android-x64',
'file_name':
'trace_processor_shell',
'file_size':
- 9577896,
+ 9742264,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x64/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x64/trace_processor_shell',
'sha256':
- 'cd4b16c5f78a060934204737ba8b312e824ff7cc28f3732daf7d64e733a727f9'
+ '43b456dcd0238f52f5730c6f5b9f8249f096df718d3fefa443c3246d66df4bd6'
}, {
'arch':
'windows-amd64',
'file_name':
'trace_processor_shell.exe',
'file_size':
- 9248256,
+ 9408000,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/windows-amd64/trace_processor_shell.exe',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/windows-amd64/trace_processor_shell.exe',
'sha256':
- '26584b4bbab40f8b0ad991a869e7483f92d7223e1473b879a6ceafa49b76390a',
+ 'b4dc6a7968673373265344e8e5249ccc31f7d12bb9df527370065dff71b1e74a',
'platform':
'win32',
'machine': ['amd64']
diff --git a/python/perfetto/prebuilts/manifests/tracebox.py b/python/perfetto/prebuilts/manifests/tracebox.py
index 21698c1..a694d8a 100755
--- a/python/perfetto/prebuilts/manifests/tracebox.py
+++ b/python/perfetto/prebuilts/manifests/tracebox.py
@@ -1,15 +1,15 @@
-# This file has been generated by: tools/roll-prebuilts v40.0
+# This file has been generated by: tools/roll-prebuilts 3e53e144bee271ec558363df2e561a77d7e0b789
TRACEBOX_MANIFEST = [{
'arch':
'mac-amd64',
'file_name':
'tracebox',
'file_size':
- 1498816,
+ 1515200,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-amd64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-amd64/tracebox',
'sha256':
- '185014447d35357edbd20e7ce9924842a0d5c6576bd2257abae2ed48b65fd3b8',
+ 'b451e873b1f6c8bd2fc3f1e12adc381c77a5b6dce9ec28ad8788e6f7f5efd348',
'platform':
'darwin',
'machine': ['x86_64']
@@ -21,9 +21,9 @@
'file_size':
1392776,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-arm64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-arm64/tracebox',
'sha256':
- '082bb50e64df5e232673eebb1cd8b0dd752a394105f600cb0262730833f6b7f3',
+ '8247045bd78e467aa010674277048658cdf04a95bd15b25dabc973fce011d6db',
'platform':
'darwin',
'machine': ['arm64']
@@ -33,11 +33,11 @@
'file_name':
'tracebox',
'file_size':
- 2229096,
+ 2236584,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-amd64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-amd64/tracebox',
'sha256':
- 'c99120caedb845e1c3fad4428263a683b44c357c76d65848dd8e437250066e38',
+ 'adf6f9ebb5686a7d2e056c8f059adf4d95e867ffa39d27b041bef16d3cb7e1c7',
'platform':
'linux',
'machine': ['x86_64']
@@ -47,11 +47,11 @@
'file_name':
'tracebox',
'file_size':
- 1339796,
+ 1344188,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm/tracebox',
'sha256':
- '6732165916b74f0b820991d1aaed2086a6b56e91f6c604291efe6636f0bdda71',
+ 'e2feeeaf38c3cd9efbf992dbe09f40fca81651d9fd9159e0f9a95868e2c4e07e',
'platform':
'linux',
'machine': ['armv6l', 'armv7l', 'armv8l']
@@ -61,11 +61,11 @@
'file_name':
'tracebox',
'file_size':
- 2157312,
+ 2164560,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm64/tracebox',
'sha256':
- '7d09865a6d7118e67d2acd0c56b2a94ce8bd5f614869d29a72fe633515ab1fbd',
+ '5d89a6c16819a74be44bf731f2d07bfb83924a2e560554a373feeb2bb9940ef1',
'platform':
'linux',
'machine': ['aarch64']
@@ -77,31 +77,31 @@
'file_size':
1247188,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm/tracebox',
'sha256':
- '4ecc192172ac2bca49557cbdbb1f7d660718d4fb4a7314fd19b2b2e52be8bc0c'
+ '5837e88a92b8bc00d5575f9dc02dd314f16b2e0a1bb174efb6c092a8f639e7c4'
}, {
'arch':
'android-arm64',
'file_name':
'tracebox',
'file_size':
- 1854120,
+ 1870504,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm64/tracebox',
'sha256':
- '1ca89113279d5c6a9ae273bde03b4d84373efe6923dc637cb840908f13b9639e'
+ '75431d11aec11f59b87a76fa31cf92a1f8e534ad4118357b3654a458cf547081'
}, {
'arch':
'android-x86',
'file_name':
'tracebox',
'file_size':
- 1853356,
+ 1869740,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x86/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x86/tracebox',
'sha256':
- 'cf689a191c1252734ebbfda3106600da324610f761515cfbffbeac2ebdfee715'
+ '388da3a4248f105bc56685db4835ce487633035334efa543b7190ac4a9e26bde'
}, {
'arch':
'android-x64',
@@ -110,7 +110,7 @@
'file_size':
2149032,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x64/tracebox',
'sha256':
- '99e9ebdb5b5308d95551a4ad060d615d7defb6877c4061d21c783c45a71d372f'
+ '1c3d50a4066f9b3478ad65431532c3503a2ad73ee89d346e6ee12f7fb0c93aaa'
}]
diff --git a/python/perfetto/prebuilts/manifests/traceconv.py b/python/perfetto/prebuilts/manifests/traceconv.py
index f01ef0a..92ad14a 100755
--- a/python/perfetto/prebuilts/manifests/traceconv.py
+++ b/python/perfetto/prebuilts/manifests/traceconv.py
@@ -1,15 +1,15 @@
-# This file has been generated by: tools/roll-prebuilts v40.0
+# This file has been generated by: tools/roll-prebuilts 3e53e144bee271ec558363df2e561a77d7e0b789
TRACECONV_MANIFEST = [{
'arch':
'mac-amd64',
'file_name':
'traceconv',
'file_size':
- 9184800,
+ 9348712,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-amd64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-amd64/traceconv',
'sha256':
- 'b651d0a5b5606c1c3e24723e94d8ecb233a01f0dfccc95a2c6a4e773cb8f52d7',
+ '466110b5d92cfc7951ae3223147156dc3ddfad055f8c7a93fea91b2f1844d013',
'platform':
'darwin',
'machine': ['x86_64']
@@ -19,11 +19,11 @@
'file_name':
'traceconv',
'file_size':
- 7761896,
+ 7927048,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-arm64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-arm64/traceconv',
'sha256':
- '3b019f5ddd5293d3181f7c30f91dc7b08f3a2e83ebb3b52b8f3905dc5161747d',
+ '46663d0eaa88bc821ad71872fd9789c340f9100e22a78494006b94225e2cfe9b',
'platform':
'darwin',
'machine': ['arm64']
@@ -33,11 +33,11 @@
'file_name':
'traceconv',
'file_size':
- 8928296,
+ 9091432,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-amd64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-amd64/traceconv',
'sha256':
- '830d20ffec266218d49f6b6c8efed4538bc59b51d8d2f735cbbb6a1435131b50',
+ 'bb0eabefb6cb22623368d1b51cd95a6d9485781f102a9293443659fdd826fc8f',
'platform':
'linux',
'machine': ['x86_64']
@@ -47,11 +47,11 @@
'file_name':
'traceconv',
'file_size':
- 6770204,
+ 6934532,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm/traceconv',
'sha256':
- '93a9e5ccb94559b871af8f6da45f858aee01801b31776703892dcf3d7ea769b7',
+ 'ce90e026c71a006b01e4d3c247772cfeeeb7581cd2ce1b003de35ddd87e9d349',
'platform':
'linux',
'machine': ['armv6l', 'armv7l', 'armv8l']
@@ -61,11 +61,11 @@
'file_name':
'traceconv',
'file_size':
- 8393944,
+ 8558824,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm64/traceconv',
'sha256':
- '88a92ccbcd8e851673e018b7f599514daf05dde9b7e4de9641fa5629124abf12',
+ 'f26446b306b0025c54d39dac5b62ae015e0d1771ff5ec461ccbbcc93f1dcb335',
'platform':
'linux',
'machine': ['aarch64']
@@ -75,55 +75,55 @@
'file_name':
'traceconv',
'file_size':
- 6378744,
+ 6542848,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm/traceconv',
'sha256':
- '6cb7d30d656aa4f172e6724f105a56e249e7043ecf637c65e1e3868885535cff'
+ '901512a8243b4015aeba59f547d40736fcf032edeedcd1ecb59c259bba0122cf'
}, {
'arch':
'android-arm64',
'file_name':
'traceconv',
'file_size':
- 7692488,
+ 7856856,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm64/traceconv',
'sha256':
- '1668808efbdf8d5b116d4716d61d2bd002f71ce465206d3b83af4fcc7a4c19cd'
+ '0eda603b5bc4925b98e0d9656dc18e3e7c4db4685c49f902fd3e1fad1be75efd'
}, {
'arch':
'android-x86',
'file_name':
'traceconv',
'file_size':
- 8557756,
+ 8721860,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x86/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x86/traceconv',
'sha256':
- '653733582cae0021eae0e1b5d8db387c1bae772d77b307f1e2111b78ec4ea67c'
+ 'd9bc2acf1b280198402a81019d6d5c9f75849d0254fd929b62671af6095d6f57'
}, {
'arch':
'android-x64',
'file_name':
'traceconv',
'file_size':
- 8708352,
+ 8872720,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x64/traceconv',
'sha256':
- '7fc564ac581b81d79573f57dae027c47bd7a857ff0f89df984380c3c657d5876'
+ '3c33c2f79a4fb9760cdf2348a09d6fb6fbb8b5098e014e83cd14d3f3dfb8661d'
}, {
'arch':
'windows-amd64',
'file_name':
'traceconv.exe',
'file_size':
- 8204288,
+ 8369664,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/windows-amd64/traceconv.exe',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/windows-amd64/traceconv.exe',
'sha256':
- 'e33bad8061f08f9c3cfe6e91ef6f1696b6ac90d0799edcb57052f24888b436e2',
+ '900f931d89af74b84229e1c396898a9c492d49acd15977692040c95a50499936',
'platform':
'win32',
'machine': ['amd64']
diff --git a/python/tools/check_imports.py b/python/tools/check_imports.py
index 3634419..a114982 100755
--- a/python/tools/check_imports.py
+++ b/python/tools/check_imports.py
@@ -353,10 +353,18 @@
return result
+def remove_prefix(s, prefix):
+ return s[len(prefix):] if s.startswith(prefix) else s
+
+
+def remove_suffix(s, suffix):
+ return s[:-len(suffix)] if s.endswith(suffix) else s
+
+
def find_imports(path):
src = path
- src = src.removeprefix(UI_SRC_DIR)
- src = src.removesuffix('.ts')
+ src = remove_prefix(src, UI_SRC_DIR)
+ src = remove_suffix(src, '.ts')
directory, _ = os.path.split(src)
with open(path) as f:
s = f.read()
diff --git a/src/trace_processor/db/BUILD.gn b/src/trace_processor/db/BUILD.gn
index 6b02d28..5dc4901 100644
--- a/src/trace_processor/db/BUILD.gn
+++ b/src/trace_processor/db/BUILD.gn
@@ -48,6 +48,14 @@
]
}
+source_set("compare") {
+ sources = [ "compare.h" ]
+ deps = [
+ "../../../include/perfetto/trace_processor",
+ "../containers",
+ ]
+}
+
perfetto_tp_tables("view_unittest") {
sources = [ "view_unittest.py" ]
}
diff --git a/src/trace_processor/db/query_executor.cc b/src/trace_processor/db/query_executor.cc
index cb9a2cf..a1df9f6 100644
--- a/src/trace_processor/db/query_executor.cc
+++ b/src/trace_processor/db/query_executor.cc
@@ -173,17 +173,6 @@
use_legacy = use_legacy || (col.overlay().size() != column_size &&
col.overlay().row_map().IsRange());
- // Comparing ints with doubles and doubles with ints.
- bool int_with_double =
- col.type() == SqlValue::kLong && c.value.type == SqlValue::kDouble;
- bool double_with_int =
- col.type() == SqlValue::kDouble && c.value.type == SqlValue::kLong;
- bool double_int_enabled_col_type = col.IsId() || col.IsSetId();
- use_legacy =
- use_legacy ||
- (!double_int_enabled_col_type && c.op != FilterOp::kIsNull &&
- c.op != FilterOp::kIsNotNull && (int_with_double || double_with_int));
-
// Extrinsically sorted columns.
use_legacy = use_legacy ||
(col.IsSorted() && col.overlay().row_map().IsIndexVector());
diff --git a/src/trace_processor/db/storage/BUILD.gn b/src/trace_processor/db/storage/BUILD.gn
index d13b530..065d787 100644
--- a/src/trace_processor/db/storage/BUILD.gn
+++ b/src/trace_processor/db/storage/BUILD.gn
@@ -81,6 +81,7 @@
deps = [
":fake_storage",
":storage",
+ "../:compare",
"../../../../gn:default_deps",
"../../../../gn:gtest_and_gmock",
"../../../../include/perfetto/trace_processor:basic_types",
diff --git a/src/trace_processor/db/storage/dense_null_storage.cc b/src/trace_processor/db/storage/dense_null_storage.cc
index cbe9743..7a59d09 100644
--- a/src/trace_processor/db/storage/dense_null_storage.cc
+++ b/src/trace_processor/db/storage/dense_null_storage.cc
@@ -78,7 +78,6 @@
} else {
res = std::move(inner_res).TakeIfBitVector();
}
- PERFETTO_DCHECK(res.size() == in.end);
if (op == FilterOp::kIsNull) {
// For IS NULL, we need to add any rows in |non_null_| which are zeros: we
@@ -93,6 +92,8 @@
// are removed as they would not match.
res.And(*non_null_);
}
+
+ PERFETTO_DCHECK(res.size() == in.end);
return RangeOrBitVector(std::move(res));
}
@@ -119,10 +120,8 @@
builder.Append(non_null_->IsSet(indices[i]));
}
BitVector non_null = std::move(builder).Build();
- PERFETTO_DCHECK(non_null.size() == indices_size);
BitVector res = std::move(inner_res).TakeIfBitVector();
- PERFETTO_DCHECK(res.size() == indices_size);
if (op == FilterOp::kIsNull) {
BitVector null = std::move(non_null);
@@ -131,6 +130,8 @@
} else {
res.And(non_null);
}
+
+ PERFETTO_DCHECK(res.size() == indices_size);
return RangeOrBitVector(std::move(res));
}
diff --git a/src/trace_processor/db/storage/null_storage.cc b/src/trace_processor/db/storage/null_storage.cc
index a1ca7d0..0ded1af 100644
--- a/src/trace_processor/db/storage/null_storage.cc
+++ b/src/trace_processor/db/storage/null_storage.cc
@@ -32,10 +32,10 @@
using Range = RowMap::Range;
-RangeOrBitVector ReconcileStorageResult(FilterOp op,
- const BitVector& non_null,
- RangeOrBitVector storage_result,
- Range in_range) {
+BitVector ReconcileStorageResult(FilterOp op,
+ const BitVector& non_null,
+ RangeOrBitVector storage_result,
+ Range in_range) {
PERFETTO_CHECK(in_range.end <= non_null.size());
// Reconcile the results of the Search operation with the non-null indices
@@ -68,7 +68,7 @@
null.Not();
res.Or(null);
}
- return RangeOrBitVector(std::move(res));
+ return res;
}
} // namespace
@@ -101,7 +101,7 @@
// intersect the |non_null_|.
BitVector res = non_null_->IntersectRange(in.start, in.end);
res.Not();
- res.Resize(non_null_->size(), false);
+ res.Resize(in.end, false);
return RangeOrBitVector(std::move(res));
}
case SearchValidationResult::kAllData:
@@ -115,9 +115,12 @@
// it.
uint32_t start = non_null_->CountSetBits(in.start);
uint32_t end = non_null_->CountSetBits(in.end);
- return ReconcileStorageResult(
+ BitVector res = ReconcileStorageResult(
op, *non_null_, storage_->Search(op, sql_val, RowMap::Range(start, end)),
in);
+
+ PERFETTO_DCHECK(res.size() == in.end);
+ return RangeOrBitVector(std::move(res));
}
RangeOrBitVector NullStorage::IndexSearch(FilterOp op,
@@ -158,8 +161,12 @@
RangeOrBitVector range_or_bv =
storage_->IndexSearch(op, sql_val, storage_iv.data(),
static_cast<uint32_t>(storage_iv.size()), sorted);
- return ReconcileStorageResult(op, std::move(storage_non_null).Build(),
- std::move(range_or_bv), Range(0, indices_size));
+ BitVector res =
+ ReconcileStorageResult(op, std::move(storage_non_null).Build(),
+ std::move(range_or_bv), Range(0, indices_size));
+
+ PERFETTO_DCHECK(res.size() == indices_size);
+ return RangeOrBitVector(std::move(res));
}
void NullStorage::StableSort(uint32_t*, uint32_t) const {
diff --git a/src/trace_processor/db/storage/numeric_storage.cc b/src/trace_processor/db/storage/numeric_storage.cc
index b090cb8..8bd2fa8 100644
--- a/src/trace_processor/db/storage/numeric_storage.cc
+++ b/src/trace_processor/db/storage/numeric_storage.cc
@@ -19,6 +19,8 @@
#include <cmath>
#include <cstddef>
+#include <cstdint>
+#include <functional>
#include <string>
#include "perfetto/base/compiler.h"
@@ -193,6 +195,80 @@
}
}
+SearchValidationResult IntColumnToDouble(SqlValue* sql_val, FilterOp op) {
+ double double_val = sql_val->AsDouble();
+
+ // Case when |sql_val| can be interpreted as a SqlValue::Double.
+ if (std::equal_to<double>()(
+ static_cast<double>(static_cast<int64_t>(double_val)), double_val)) {
+ *sql_val = SqlValue::Long(static_cast<int64_t>(double_val));
+ return SearchValidationResult::kOk;
+ }
+
+ // Logic for when the value is a real double.
+ switch (op) {
+ case FilterOp::kEq:
+ return SearchValidationResult::kNoData;
+ case FilterOp::kNe:
+ return SearchValidationResult::kAllData;
+
+ case FilterOp::kLe:
+ case FilterOp::kGt:
+ *sql_val = SqlValue::Long(static_cast<int64_t>(std::floor(double_val)));
+ return SearchValidationResult::kOk;
+
+ case FilterOp::kLt:
+ case FilterOp::kGe:
+ *sql_val = SqlValue::Long(static_cast<int64_t>(std::ceil(double_val)));
+ return SearchValidationResult::kOk;
+
+ case FilterOp::kIsNotNull:
+ case FilterOp::kIsNull:
+ case FilterOp::kGlob:
+ case FilterOp::kRegex:
+ PERFETTO_FATAL("Invalid filter operation");
+ }
+ PERFETTO_FATAL("For GCC");
+}
+
+SearchValidationResult DoubleColumnWithInt(SqlValue* sql_val, FilterOp op) {
+ int64_t i = sql_val->AsLong();
+ double i_as_d = static_cast<double>(i);
+
+ // Case when |sql_val| can be interpreted as a SqlValue::Long.
+ if (std::equal_to<int64_t>()(i, static_cast<int64_t>(i_as_d))) {
+ *sql_val = SqlValue::Double(i_as_d);
+ return SearchValidationResult::kOk;
+ }
+
+ // Logic for when the value can't be represented as double.
+ switch (op) {
+ case FilterOp::kEq:
+ return SearchValidationResult::kNoData;
+ case FilterOp::kNe:
+ return SearchValidationResult::kAllData;
+
+ case FilterOp::kLe:
+ case FilterOp::kGt:
+ // The first double value smaller than |i|.
+ *sql_val = SqlValue::Double(std::nextafter(i_as_d, i - 1));
+ return SearchValidationResult::kOk;
+
+ case FilterOp::kLt:
+ case FilterOp::kGe:
+ // The first double value bigger than |i|.
+ *sql_val = SqlValue::Double(std::nextafter(i_as_d, i + 1));
+ return SearchValidationResult::kOk;
+
+ case FilterOp::kIsNotNull:
+ case FilterOp::kIsNull:
+ case FilterOp::kGlob:
+ case FilterOp::kRegex:
+ PERFETTO_FATAL("Invalid filter operation");
+ }
+ PERFETTO_FATAL("For GCC");
+}
+
} // namespace
SearchValidationResult NumericStorageBase::ValidateSearchConstraints(
@@ -245,17 +321,15 @@
return SearchValidationResult::kNoData;
}
- // TODO(b/307482437): There is currently no support for comparison with double
- // and it is prevented on QueryExecutor level.
- if (type_ != ColumnType::kDouble) {
- PERFETTO_CHECK(val.type != SqlValue::kDouble);
- }
-
// Bounds of the value.
enum ExtremeVal { kTooBig, kTooSmall, kOk };
ExtremeVal extreme_validator = kOk;
- switch (type_) {
+ double_t num_val = val.type == SqlValue::kLong
+ ? static_cast<double_t>(val.AsLong())
+ : val.AsDouble();
+
+ switch (storage_type_) {
case ColumnType::kDouble:
// Any value would make a sensible comparison with a double.
case ColumnType::kInt64:
@@ -263,21 +337,21 @@
// to verify here, as all values are going to be in the int64_t limits.
break;
case ColumnType::kInt32:
- if (val.AsLong() > std::numeric_limits<int32_t>::max()) {
+ if (num_val > std::numeric_limits<int32_t>::max()) {
extreme_validator = kTooBig;
break;
}
- if (val.AsLong() < std::numeric_limits<int32_t>::min()) {
+ if (num_val < std::numeric_limits<int32_t>::min()) {
extreme_validator = kTooSmall;
break;
}
break;
case ColumnType::kUint32:
- if (val.AsLong() > std::numeric_limits<uint32_t>::max()) {
+ if (num_val > std::numeric_limits<uint32_t>::max()) {
extreme_validator = kTooBig;
break;
}
- if (val.AsLong() < std::numeric_limits<uint32_t>::min()) {
+ if (num_val < std::numeric_limits<uint32_t>::min()) {
extreme_validator = kTooSmall;
break;
}
@@ -317,7 +391,33 @@
std::to_string(static_cast<uint32_t>(op)));
});
- NumericValue val = GetNumericTypeVariant(type_, sql_val);
+ if (sql_val.type == SqlValue::kDouble &&
+ storage_type_ != ColumnType::kDouble) {
+ auto comp = IntColumnToDouble(&sql_val, op);
+ switch (comp) {
+ case SearchValidationResult::kOk:
+ break;
+ case SearchValidationResult::kAllData:
+ return RangeOrBitVector(search_range);
+ case SearchValidationResult::kNoData:
+ return RangeOrBitVector(Range());
+ }
+ }
+
+ if (sql_val.type != SqlValue::kDouble &&
+ storage_type_ == ColumnType::kDouble) {
+ auto comp = DoubleColumnWithInt(&sql_val, op);
+ switch (comp) {
+ case SearchValidationResult::kOk:
+ break;
+ case SearchValidationResult::kAllData:
+ return RangeOrBitVector(search_range);
+ case SearchValidationResult::kNoData:
+ return RangeOrBitVector(Range());
+ }
+ }
+
+ NumericValue val = GetNumericTypeVariant(storage_type_, sql_val);
if (is_sorted_) {
if (op != FilterOp::kNe) {
@@ -347,7 +447,34 @@
std::to_string(static_cast<uint32_t>(op)));
});
- NumericValue val = GetNumericTypeVariant(type_, sql_val);
+ if (sql_val.type == SqlValue::kDouble &&
+ storage_type_ != ColumnType::kDouble) {
+ auto comp = IntColumnToDouble(&sql_val, op);
+ switch (comp) {
+ case SearchValidationResult::kOk:
+ break;
+ case SearchValidationResult::kAllData:
+ return RangeOrBitVector(Range(0, indices_size));
+ case SearchValidationResult::kNoData:
+ return RangeOrBitVector(Range());
+ }
+ }
+
+ if (sql_val.type != SqlValue::kDouble &&
+ storage_type_ == ColumnType::kDouble) {
+ auto comp = DoubleColumnWithInt(&sql_val, op);
+ switch (comp) {
+ case SearchValidationResult::kOk:
+ break;
+ case SearchValidationResult::kAllData:
+ return RangeOrBitVector(Range(0, indices_size));
+ case SearchValidationResult::kNoData:
+ return RangeOrBitVector(Range());
+ }
+ }
+
+ NumericValue val = GetNumericTypeVariant(storage_type_, sql_val);
+
if (sorted) {
return RangeOrBitVector(
BinarySearchExtrinsic(op, val, indices, indices_size));
@@ -473,7 +600,7 @@
return first_val < second_val;
});
},
- GetNumericTypeVariant(type_, SqlValue::Long(0)));
+ GetNumericTypeVariant(storage_type_, SqlValue::Long(0)));
}
void NumericStorageBase::Sort(uint32_t*, uint32_t) const {
@@ -484,10 +611,10 @@
void NumericStorageBase::Serialize(StorageProto* msg) const {
auto* numeric_storage_msg = msg->set_numeric_storage();
numeric_storage_msg->set_is_sorted(is_sorted_);
- numeric_storage_msg->set_column_type(static_cast<uint32_t>(type_));
+ numeric_storage_msg->set_column_type(static_cast<uint32_t>(storage_type_));
uint32_t type_size;
- switch (type_) {
+ switch (storage_type_) {
case ColumnType::kInt64:
type_size = sizeof(int64_t);
break;
diff --git a/src/trace_processor/db/storage/numeric_storage.h b/src/trace_processor/db/storage/numeric_storage.h
index 741a8e0..6af150a 100644
--- a/src/trace_processor/db/storage/numeric_storage.h
+++ b/src/trace_processor/db/storage/numeric_storage.h
@@ -60,7 +60,7 @@
uint32_t size,
ColumnType type,
bool is_sorted = false)
- : size_(size), data_(data), type_(type), is_sorted_(is_sorted) {}
+ : size_(size), data_(data), storage_type_(type), is_sorted_(is_sorted) {}
private:
// All viable numeric values for ColumnTypes.
@@ -86,7 +86,7 @@
const uint32_t size_ = 0;
const void* data_ = nullptr;
- const ColumnType type_ = ColumnType::kDummy;
+ const ColumnType storage_type_ = ColumnType::kDummy;
const bool is_sorted_ = false;
};
diff --git a/src/trace_processor/db/storage/numeric_storage_unittest.cc b/src/trace_processor/db/storage/numeric_storage_unittest.cc
index 5ba32ad..5806f83 100644
--- a/src/trace_processor/db/storage/numeric_storage_unittest.cc
+++ b/src/trace_processor/db/storage/numeric_storage_unittest.cc
@@ -16,6 +16,8 @@
#include "src/trace_processor/db/storage/numeric_storage.h"
#include <cstdint>
+#include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/db/compare.h"
#include "src/trace_processor/db/storage/types.h"
#include "test/gtest_and_gmock.h"
@@ -29,8 +31,21 @@
namespace storage {
namespace {
+using testing::ElementsAre;
+using testing::IsEmpty;
using Range = RowMap::Range;
+std::vector<uint32_t> ToIndexVector(RangeOrBitVector& r_or_bv) {
+ RowMap rm;
+ if (r_or_bv.IsBitVector()) {
+ rm = RowMap(std::move(r_or_bv).TakeIfBitVector());
+ } else {
+ Range range = std::move(r_or_bv).TakeIfRange();
+ rm = RowMap(range.start, range.end);
+ }
+ return rm.GetAllIndices();
+}
+
TEST(NumericStorageUnittest, InvalidSearchConstraintsGeneralChecks) {
std::vector<uint32_t> data_vec(128);
std::iota(data_vec.begin(), data_vec.end(), 0);
@@ -160,7 +175,111 @@
ASSERT_EQ(out, stable_out);
}
-TEST(NumericStorageUnittest, CompareFast) {
+TEST(NumericStorageUnittest, Search) {
+ std::vector<int32_t> data_vec{-5, 5, -4, 4, -3, 3, 0};
+ NumericStorage<int32_t> storage(&data_vec, ColumnType::kInt32);
+ Range test_range(1, 5);
+ SqlValue val = SqlValue::Long(4);
+
+ auto res = storage.Search(FilterOp::kEq, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(3));
+
+ res = storage.Search(FilterOp::kNe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 2, 4));
+
+ res = storage.Search(FilterOp::kLt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(2, 4));
+
+ res = storage.Search(FilterOp::kLe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(2, 3, 4));
+
+ res = storage.Search(FilterOp::kGt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1));
+
+ res = storage.Search(FilterOp::kGe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 3));
+}
+
+TEST(NumericStorageUnittest, SearchCompareWithNegative) {
+ std::vector<int32_t> data_vec{-5, 5, -4, 4, -3, 3, 0};
+ NumericStorage<int32_t> storage(&data_vec, ColumnType::kInt32);
+ Range test_range(1, 5);
+ SqlValue val = SqlValue::Long(-3);
+
+ auto res = storage.Search(FilterOp::kEq, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(4));
+
+ res = storage.Search(FilterOp::kNe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 2, 3));
+
+ res = storage.Search(FilterOp::kLt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(2));
+
+ res = storage.Search(FilterOp::kLe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(2, 4));
+
+ res = storage.Search(FilterOp::kGt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 3));
+
+ res = storage.Search(FilterOp::kGe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 3, 4));
+}
+
+TEST(NumericStorageUnittest, IndexSearch) {
+ std::vector<int32_t> data_vec{-5, 5, -4, 4, -3, 3, 0};
+ NumericStorage<int32_t> storage(&data_vec, ColumnType::kInt32);
+
+ // -5, -3, -3, 3, 5, 0
+ std::vector<uint32_t> indices{0, 4, 4, 5, 1, 6};
+ SqlValue val = SqlValue::Long(3);
+
+ auto res = storage.IndexSearch(FilterOp::kEq, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(3));
+
+ res = storage.IndexSearch(FilterOp::kNe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2, 4, 5));
+
+ res = storage.IndexSearch(FilterOp::kLt, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2, 5));
+
+ res = storage.IndexSearch(FilterOp::kLe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2, 3, 5));
+
+ res = storage.IndexSearch(FilterOp::kGt, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(4));
+
+ res = storage.IndexSearch(FilterOp::kGe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(3, 4));
+}
+
+TEST(NumericStorageUnittest, IndexSearchCompareWithNegative) {
+ std::vector<int32_t> data_vec{-5, 5, -4, 4, -3, 3, 0};
+ NumericStorage<int32_t> storage(&data_vec, ColumnType::kInt32);
+
+ // -5, -3, -3, 3, 5, 0
+ std::vector<uint32_t> indices{0, 4, 4, 5, 1, 6};
+ SqlValue val = SqlValue::Long(-3);
+
+ auto res = storage.IndexSearch(FilterOp::kEq, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 2));
+
+ res = storage.IndexSearch(FilterOp::kNe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 3, 4, 5));
+
+ res = storage.IndexSearch(FilterOp::kLt, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0));
+
+ res = storage.IndexSearch(FilterOp::kLe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2));
+
+ res = storage.IndexSearch(FilterOp::kGt, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(3, 4, 5));
+
+ res = storage.IndexSearch(FilterOp::kGe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 2, 3, 4, 5));
+}
+
+TEST(NumericStorageUnittest, SearchFast) {
std::vector<uint32_t> data_vec(128);
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage<uint32_t> storage(&data_vec, ColumnType::kUint32);
@@ -172,7 +291,7 @@
ASSERT_EQ(bv.IndexOfNthSet(0), 100u);
}
-TEST(NumericStorageUnittest, CompareSorted) {
+TEST(NumericStorageUnittest, SearchSorted) {
std::vector<uint32_t> data_vec(128);
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage<uint32_t> storage(&data_vec, ColumnType::kUint32, true);
@@ -184,7 +303,7 @@
ASSERT_EQ(range.end, 128u);
}
-TEST(NumericStorageUnittest, CompareSortedNe) {
+TEST(NumericStorageUnittest, SearchSortedNe) {
std::vector<uint32_t> data_vec(128);
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage<uint32_t> storage(&data_vec, ColumnType::kUint32, true);
@@ -194,7 +313,7 @@
ASSERT_EQ(bv.CountSetBits(), 127u);
}
-TEST(NumericStorageUnittest, CompareSortedSubset) {
+TEST(NumericStorageUnittest, SearchSortedSubset) {
std::vector<uint32_t> data_vec(128);
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage<uint32_t> storage(&data_vec, ColumnType::kUint32, true);
@@ -206,7 +325,7 @@
ASSERT_EQ(range.end, 104u);
}
-TEST(NumericStorageUnittest, CompareSortedIndexesGreaterEqual) {
+TEST(NumericStorageUnittest, IndexSearcgExtrinsicGe) {
std::vector<uint32_t> data_vec{30, 40, 50, 60, 90, 80, 70, 0, 10, 20};
std::vector<uint32_t> sorted_order{7, 8, 9, 0, 1, 2, 3, 6, 5, 4};
@@ -222,7 +341,7 @@
ASSERT_EQ(range.end, 10u);
}
-TEST(NumericStorageUnittest, CompareSortedIndexesLess) {
+TEST(NumericStorageUnittest, IndexSearchExtrinsicLt) {
std::vector<uint32_t> data_vec{30, 40, 50, 60, 90, 80, 70, 0, 10, 20};
std::vector<uint32_t> sorted_order{7, 8, 9, 0, 1, 2, 3, 6, 5, 4};
@@ -238,7 +357,7 @@
ASSERT_EQ(range.end, 6u);
}
-TEST(NumericStorageUnittest, CompareSortedIndexesEqual) {
+TEST(NumericStorageUnittest, IndexSearchExtrinsicEq) {
std::vector<uint32_t> data_vec{30, 40, 50, 60, 90, 80, 70, 0, 10, 20};
std::vector<uint32_t> sorted_order{7, 8, 9, 0, 1, 2, 3, 6, 5, 4};
@@ -254,6 +373,284 @@
ASSERT_EQ(range.end, 7u);
}
+TEST(NumericStorageUnittest, SearchWithIntAsDouble) {
+ std::vector<int32_t> data_vec{-5, 5, -4, 4, -3, 3, 0};
+ NumericStorage<int32_t> storage(&data_vec, ColumnType::kInt32);
+ Range test_range(1, 5);
+ SqlValue val = SqlValue::Double(4);
+
+ auto res = storage.Search(FilterOp::kEq, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(3));
+
+ res = storage.Search(FilterOp::kNe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 2, 4));
+
+ res = storage.Search(FilterOp::kLt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(2, 4));
+
+ res = storage.Search(FilterOp::kLe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(2, 3, 4));
+
+ res = storage.Search(FilterOp::kGt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1));
+
+ res = storage.Search(FilterOp::kGe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 3));
+}
+
+TEST(NumericStorageUnittest, IndexSearchWithIntAsDouble) {
+ std::vector<int32_t> data_vec{-5, 5, -4, 4, -3, 3, 0};
+ NumericStorage<int32_t> storage(&data_vec, ColumnType::kInt32);
+
+ // -5, -3, -3, 3, 5, 0
+ std::vector<uint32_t> indices{0, 4, 4, 5, 1, 6};
+ SqlValue val = SqlValue::Double(3);
+
+ auto res = storage.IndexSearch(FilterOp::kEq, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(3));
+
+ res = storage.IndexSearch(FilterOp::kNe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2, 4, 5));
+
+ res = storage.IndexSearch(FilterOp::kLt, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2, 5));
+
+ res = storage.IndexSearch(FilterOp::kLe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2, 3, 5));
+
+ res = storage.IndexSearch(FilterOp::kGt, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(4));
+
+ res = storage.IndexSearch(FilterOp::kGe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(3, 4));
+}
+
+TEST(NumericStorageUnittest, SearchInt32WithDouble) {
+ std::vector<int32_t> data_vec{-5, 5, -4, 4, -3, 3, 0};
+ NumericStorage<int32_t> storage(&data_vec, ColumnType::kInt32);
+ Range test_range(1, 5);
+ SqlValue val = SqlValue::Double(3.5);
+
+ auto res = storage.Search(FilterOp::kEq, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), IsEmpty());
+
+ res = storage.Search(FilterOp::kNe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 2, 3, 4));
+
+ res = storage.Search(FilterOp::kLt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(2, 4));
+
+ res = storage.Search(FilterOp::kLe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(2, 4));
+
+ res = storage.Search(FilterOp::kGt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 3));
+
+ res = storage.Search(FilterOp::kGe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 3));
+}
+
+TEST(NumericStorageUnittest, SearchInt32WithNegDouble) {
+ std::vector<int32_t> data_vec{-5, 5, -4, 4, -3, 3, 0};
+ NumericStorage<int32_t> storage(&data_vec, ColumnType::kInt32);
+ Range test_range(1, 5);
+ SqlValue val = SqlValue::Double(-3.5);
+
+ auto res = storage.Search(FilterOp::kEq, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), IsEmpty());
+
+ res = storage.Search(FilterOp::kNe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 2, 3, 4));
+
+ res = storage.Search(FilterOp::kLt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(2));
+
+ res = storage.Search(FilterOp::kLe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(2));
+
+ res = storage.Search(FilterOp::kGt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 3, 4));
+
+ res = storage.Search(FilterOp::kGe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 3, 4));
+}
+
+TEST(NumericStorageUnittest, IndexSearchInt32WithDouble) {
+ std::vector<int32_t> data_vec{-5, 5, -4, 4, -3, 3, 0};
+ NumericStorage<int32_t> storage(&data_vec, ColumnType::kInt32);
+
+ // -5, -3, -3, 3, 5, 0
+ std::vector<uint32_t> indices{0, 4, 4, 5, 1, 6};
+ SqlValue val = SqlValue::Double(1.5);
+
+ auto res = storage.IndexSearch(FilterOp::kEq, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), IsEmpty());
+
+ res = storage.IndexSearch(FilterOp::kNe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2, 3, 4, 5));
+
+ res = storage.IndexSearch(FilterOp::kLt, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2, 5));
+
+ res = storage.IndexSearch(FilterOp::kLe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2, 5));
+
+ res = storage.IndexSearch(FilterOp::kGt, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(3, 4));
+
+ res = storage.IndexSearch(FilterOp::kGe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(3, 4));
+}
+
+TEST(NumericStorageUnittest, IndexSearchInt32WithNegDouble) {
+ std::vector<int32_t> data_vec{-5, 5, -4, 4, -3, 3, 0};
+ NumericStorage<int32_t> storage(&data_vec, ColumnType::kInt32);
+
+ // -5, -3, -3, 3, 5, 0
+ std::vector<uint32_t> indices{0, 4, 4, 5, 1, 6};
+ SqlValue val = SqlValue::Double(-2.5);
+
+ auto res = storage.IndexSearch(FilterOp::kEq, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), IsEmpty());
+
+ res = storage.IndexSearch(FilterOp::kNe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2, 3, 4, 5));
+
+ res = storage.IndexSearch(FilterOp::kLt, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2));
+
+ res = storage.IndexSearch(FilterOp::kLe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2));
+
+ res = storage.IndexSearch(FilterOp::kGt, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(3, 4, 5));
+
+ res = storage.IndexSearch(FilterOp::kGe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(3, 4, 5));
+}
+
+TEST(NumericStorageUnittest, SearchUint32WithNegDouble) {
+ std::vector<uint32_t> data_vec{0, 1, 2, 3, 4, 5};
+ NumericStorage<uint32_t> storage(&data_vec, ColumnType::kInt32);
+ Range test_range(1, 5);
+ SqlValue val = SqlValue::Double(-3.5);
+
+ auto res = storage.Search(FilterOp::kEq, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), IsEmpty());
+
+ res = storage.Search(FilterOp::kNe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 2, 3, 4));
+
+ res = storage.Search(FilterOp::kLt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), IsEmpty());
+
+ res = storage.Search(FilterOp::kLe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), IsEmpty());
+
+ res = storage.Search(FilterOp::kGt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 2, 3, 4));
+
+ res = storage.Search(FilterOp::kGe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 2, 3, 4));
+}
+
+TEST(NumericStorageUnittest, IndexSearchUint32WithNegDouble) {
+ std::vector<uint32_t> data_vec{0, 1, 2, 3, 4, 5, 6};
+ NumericStorage<uint32_t> storage(&data_vec, ColumnType::kInt32);
+
+ std::vector<uint32_t> indices{0, 4, 4, 5, 1, 6};
+ SqlValue val = SqlValue::Double(-2.5);
+
+ auto res = storage.IndexSearch(FilterOp::kEq, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), IsEmpty());
+
+ res = storage.IndexSearch(FilterOp::kNe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2, 3, 4, 5));
+
+ res = storage.IndexSearch(FilterOp::kLt, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), IsEmpty());
+
+ res = storage.IndexSearch(FilterOp::kLe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), IsEmpty());
+
+ res = storage.IndexSearch(FilterOp::kGt, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2, 3, 4, 5));
+
+ res = storage.IndexSearch(FilterOp::kGe, val, indices.data(), 6, false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2, 3, 4, 5));
+}
+
+TEST(NumericStorageUnittest, DoubleColumnWithIntThatCantBeRepresentedAsDouble) {
+ // Sanity check that this value can't be represented as double.
+ int64_t not_rep_i = 9007199254740993;
+ EXPECT_FALSE(std::nextafter(static_cast<double>(not_rep_i), 1.0) ==
+ static_cast<double>(not_rep_i));
+ SqlValue val = SqlValue::Long(not_rep_i);
+
+ std::vector<double> data_vec{9007199254740992.0, 9007199254740994.0};
+
+ // Whether LongToDouble has the expected results.
+ ASSERT_TRUE(compare::LongToDouble(not_rep_i, data_vec[0]) > 0);
+ ASSERT_TRUE(compare::LongToDouble(not_rep_i, data_vec[1]) < 0);
+
+ NumericStorage<double> storage(&data_vec, ColumnType::kDouble);
+ Range test_range(0, 2);
+
+ auto res = storage.Search(FilterOp::kEq, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), IsEmpty());
+
+ res = storage.Search(FilterOp::kNe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1));
+
+ res = storage.Search(FilterOp::kLt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0));
+
+ res = storage.Search(FilterOp::kLe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0));
+
+ res = storage.Search(FilterOp::kGt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1));
+
+ res = storage.Search(FilterOp::kGe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1));
+}
+
+TEST(NumericStorageUnittest,
+ DoubleColumnWithNegIntThatCantBeRepresentedAsDouble) {
+ // Sanity check that this value can't be represented as double.
+ int64_t not_rep_i = -9007199254740993;
+ EXPECT_FALSE(std::nextafter(static_cast<double>(not_rep_i), 1.0) ==
+ static_cast<double>(not_rep_i));
+ SqlValue val = SqlValue::Long(not_rep_i);
+
+ std::vector<double> data_vec{-9007199254740992.0, -9007199254740994.0};
+
+ // Whether LongToDouble has the expected results.
+ ASSERT_TRUE(compare::LongToDouble(not_rep_i, data_vec[0]) < 0);
+ ASSERT_TRUE(compare::LongToDouble(not_rep_i, data_vec[1]) > 0);
+
+ NumericStorage<double> storage(&data_vec, ColumnType::kDouble);
+ Range test_range(0, 2);
+
+ auto res = storage.Search(FilterOp::kEq, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), IsEmpty());
+
+ res = storage.Search(FilterOp::kNe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1));
+
+ res = storage.Search(FilterOp::kLt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1));
+
+ res = storage.Search(FilterOp::kLe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1));
+
+ res = storage.Search(FilterOp::kGt, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0));
+
+ res = storage.Search(FilterOp::kGe, val, test_range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0));
+}
+
} // namespace
} // namespace storage
} // namespace trace_processor
diff --git a/tools/cpu_profile b/tools/cpu_profile
index 9654a2a..c33235f 100755
--- a/tools/cpu_profile
+++ b/tools/cpu_profile
@@ -37,18 +37,18 @@
# ----- Amalgamator: begin of python/perfetto/prebuilts/manifests/traceconv.py
-# This file has been generated by: tools/roll-prebuilts v40.0
+# This file has been generated by: tools/roll-prebuilts 3e53e144bee271ec558363df2e561a77d7e0b789
TRACECONV_MANIFEST = [{
'arch':
'mac-amd64',
'file_name':
'traceconv',
'file_size':
- 9184800,
+ 9348712,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-amd64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-amd64/traceconv',
'sha256':
- 'b651d0a5b5606c1c3e24723e94d8ecb233a01f0dfccc95a2c6a4e773cb8f52d7',
+ '466110b5d92cfc7951ae3223147156dc3ddfad055f8c7a93fea91b2f1844d013',
'platform':
'darwin',
'machine': ['x86_64']
@@ -58,11 +58,11 @@
'file_name':
'traceconv',
'file_size':
- 7761896,
+ 7927048,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-arm64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-arm64/traceconv',
'sha256':
- '3b019f5ddd5293d3181f7c30f91dc7b08f3a2e83ebb3b52b8f3905dc5161747d',
+ '46663d0eaa88bc821ad71872fd9789c340f9100e22a78494006b94225e2cfe9b',
'platform':
'darwin',
'machine': ['arm64']
@@ -72,11 +72,11 @@
'file_name':
'traceconv',
'file_size':
- 8928296,
+ 9091432,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-amd64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-amd64/traceconv',
'sha256':
- '830d20ffec266218d49f6b6c8efed4538bc59b51d8d2f735cbbb6a1435131b50',
+ 'bb0eabefb6cb22623368d1b51cd95a6d9485781f102a9293443659fdd826fc8f',
'platform':
'linux',
'machine': ['x86_64']
@@ -86,11 +86,11 @@
'file_name':
'traceconv',
'file_size':
- 6770204,
+ 6934532,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm/traceconv',
'sha256':
- '93a9e5ccb94559b871af8f6da45f858aee01801b31776703892dcf3d7ea769b7',
+ 'ce90e026c71a006b01e4d3c247772cfeeeb7581cd2ce1b003de35ddd87e9d349',
'platform':
'linux',
'machine': ['armv6l', 'armv7l', 'armv8l']
@@ -100,11 +100,11 @@
'file_name':
'traceconv',
'file_size':
- 8393944,
+ 8558824,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm64/traceconv',
'sha256':
- '88a92ccbcd8e851673e018b7f599514daf05dde9b7e4de9641fa5629124abf12',
+ 'f26446b306b0025c54d39dac5b62ae015e0d1771ff5ec461ccbbcc93f1dcb335',
'platform':
'linux',
'machine': ['aarch64']
@@ -114,55 +114,55 @@
'file_name':
'traceconv',
'file_size':
- 6378744,
+ 6542848,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm/traceconv',
'sha256':
- '6cb7d30d656aa4f172e6724f105a56e249e7043ecf637c65e1e3868885535cff'
+ '901512a8243b4015aeba59f547d40736fcf032edeedcd1ecb59c259bba0122cf'
}, {
'arch':
'android-arm64',
'file_name':
'traceconv',
'file_size':
- 7692488,
+ 7856856,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm64/traceconv',
'sha256':
- '1668808efbdf8d5b116d4716d61d2bd002f71ce465206d3b83af4fcc7a4c19cd'
+ '0eda603b5bc4925b98e0d9656dc18e3e7c4db4685c49f902fd3e1fad1be75efd'
}, {
'arch':
'android-x86',
'file_name':
'traceconv',
'file_size':
- 8557756,
+ 8721860,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x86/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x86/traceconv',
'sha256':
- '653733582cae0021eae0e1b5d8db387c1bae772d77b307f1e2111b78ec4ea67c'
+ 'd9bc2acf1b280198402a81019d6d5c9f75849d0254fd929b62671af6095d6f57'
}, {
'arch':
'android-x64',
'file_name':
'traceconv',
'file_size':
- 8708352,
+ 8872720,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x64/traceconv',
'sha256':
- '7fc564ac581b81d79573f57dae027c47bd7a857ff0f89df984380c3c657d5876'
+ '3c33c2f79a4fb9760cdf2348a09d6fb6fbb8b5098e014e83cd14d3f3dfb8661d'
}, {
'arch':
'windows-amd64',
'file_name':
'traceconv.exe',
'file_size':
- 8204288,
+ 8369664,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/windows-amd64/traceconv.exe',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/windows-amd64/traceconv.exe',
'sha256':
- 'e33bad8061f08f9c3cfe6e91ef6f1696b6ac90d0799edcb57052f24888b436e2',
+ '900f931d89af74b84229e1c396898a9c492d49acd15977692040c95a50499936',
'platform':
'win32',
'machine': ['amd64']
diff --git a/tools/heap_profile b/tools/heap_profile
index 77885fc..e002051 100755
--- a/tools/heap_profile
+++ b/tools/heap_profile
@@ -34,18 +34,18 @@
# ----- Amalgamator: begin of python/perfetto/prebuilts/manifests/traceconv.py
-# This file has been generated by: tools/roll-prebuilts v40.0
+# This file has been generated by: tools/roll-prebuilts 3e53e144bee271ec558363df2e561a77d7e0b789
TRACECONV_MANIFEST = [{
'arch':
'mac-amd64',
'file_name':
'traceconv',
'file_size':
- 9184800,
+ 9348712,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-amd64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-amd64/traceconv',
'sha256':
- 'b651d0a5b5606c1c3e24723e94d8ecb233a01f0dfccc95a2c6a4e773cb8f52d7',
+ '466110b5d92cfc7951ae3223147156dc3ddfad055f8c7a93fea91b2f1844d013',
'platform':
'darwin',
'machine': ['x86_64']
@@ -55,11 +55,11 @@
'file_name':
'traceconv',
'file_size':
- 7761896,
+ 7927048,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-arm64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-arm64/traceconv',
'sha256':
- '3b019f5ddd5293d3181f7c30f91dc7b08f3a2e83ebb3b52b8f3905dc5161747d',
+ '46663d0eaa88bc821ad71872fd9789c340f9100e22a78494006b94225e2cfe9b',
'platform':
'darwin',
'machine': ['arm64']
@@ -69,11 +69,11 @@
'file_name':
'traceconv',
'file_size':
- 8928296,
+ 9091432,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-amd64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-amd64/traceconv',
'sha256':
- '830d20ffec266218d49f6b6c8efed4538bc59b51d8d2f735cbbb6a1435131b50',
+ 'bb0eabefb6cb22623368d1b51cd95a6d9485781f102a9293443659fdd826fc8f',
'platform':
'linux',
'machine': ['x86_64']
@@ -83,11 +83,11 @@
'file_name':
'traceconv',
'file_size':
- 6770204,
+ 6934532,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm/traceconv',
'sha256':
- '93a9e5ccb94559b871af8f6da45f858aee01801b31776703892dcf3d7ea769b7',
+ 'ce90e026c71a006b01e4d3c247772cfeeeb7581cd2ce1b003de35ddd87e9d349',
'platform':
'linux',
'machine': ['armv6l', 'armv7l', 'armv8l']
@@ -97,11 +97,11 @@
'file_name':
'traceconv',
'file_size':
- 8393944,
+ 8558824,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm64/traceconv',
'sha256':
- '88a92ccbcd8e851673e018b7f599514daf05dde9b7e4de9641fa5629124abf12',
+ 'f26446b306b0025c54d39dac5b62ae015e0d1771ff5ec461ccbbcc93f1dcb335',
'platform':
'linux',
'machine': ['aarch64']
@@ -111,55 +111,55 @@
'file_name':
'traceconv',
'file_size':
- 6378744,
+ 6542848,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm/traceconv',
'sha256':
- '6cb7d30d656aa4f172e6724f105a56e249e7043ecf637c65e1e3868885535cff'
+ '901512a8243b4015aeba59f547d40736fcf032edeedcd1ecb59c259bba0122cf'
}, {
'arch':
'android-arm64',
'file_name':
'traceconv',
'file_size':
- 7692488,
+ 7856856,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm64/traceconv',
'sha256':
- '1668808efbdf8d5b116d4716d61d2bd002f71ce465206d3b83af4fcc7a4c19cd'
+ '0eda603b5bc4925b98e0d9656dc18e3e7c4db4685c49f902fd3e1fad1be75efd'
}, {
'arch':
'android-x86',
'file_name':
'traceconv',
'file_size':
- 8557756,
+ 8721860,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x86/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x86/traceconv',
'sha256':
- '653733582cae0021eae0e1b5d8db387c1bae772d77b307f1e2111b78ec4ea67c'
+ 'd9bc2acf1b280198402a81019d6d5c9f75849d0254fd929b62671af6095d6f57'
}, {
'arch':
'android-x64',
'file_name':
'traceconv',
'file_size':
- 8708352,
+ 8872720,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x64/traceconv',
'sha256':
- '7fc564ac581b81d79573f57dae027c47bd7a857ff0f89df984380c3c657d5876'
+ '3c33c2f79a4fb9760cdf2348a09d6fb6fbb8b5098e014e83cd14d3f3dfb8661d'
}, {
'arch':
'windows-amd64',
'file_name':
'traceconv.exe',
'file_size':
- 8204288,
+ 8369664,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/windows-amd64/traceconv.exe',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/windows-amd64/traceconv.exe',
'sha256':
- 'e33bad8061f08f9c3cfe6e91ef6f1696b6ac90d0799edcb57052f24888b436e2',
+ '900f931d89af74b84229e1c396898a9c492d49acd15977692040c95a50499936',
'platform':
'win32',
'machine': ['amd64']
diff --git a/tools/record_android_trace b/tools/record_android_trace
index d4a740a..59bde1c 100755
--- a/tools/record_android_trace
+++ b/tools/record_android_trace
@@ -33,18 +33,18 @@
# ----- Amalgamator: begin of python/perfetto/prebuilts/manifests/tracebox.py
-# This file has been generated by: tools/roll-prebuilts v40.0
+# This file has been generated by: tools/roll-prebuilts 3e53e144bee271ec558363df2e561a77d7e0b789
TRACEBOX_MANIFEST = [{
'arch':
'mac-amd64',
'file_name':
'tracebox',
'file_size':
- 1498816,
+ 1515200,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-amd64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-amd64/tracebox',
'sha256':
- '185014447d35357edbd20e7ce9924842a0d5c6576bd2257abae2ed48b65fd3b8',
+ 'b451e873b1f6c8bd2fc3f1e12adc381c77a5b6dce9ec28ad8788e6f7f5efd348',
'platform':
'darwin',
'machine': ['x86_64']
@@ -56,9 +56,9 @@
'file_size':
1392776,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-arm64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-arm64/tracebox',
'sha256':
- '082bb50e64df5e232673eebb1cd8b0dd752a394105f600cb0262730833f6b7f3',
+ '8247045bd78e467aa010674277048658cdf04a95bd15b25dabc973fce011d6db',
'platform':
'darwin',
'machine': ['arm64']
@@ -68,11 +68,11 @@
'file_name':
'tracebox',
'file_size':
- 2229096,
+ 2236584,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-amd64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-amd64/tracebox',
'sha256':
- 'c99120caedb845e1c3fad4428263a683b44c357c76d65848dd8e437250066e38',
+ 'adf6f9ebb5686a7d2e056c8f059adf4d95e867ffa39d27b041bef16d3cb7e1c7',
'platform':
'linux',
'machine': ['x86_64']
@@ -82,11 +82,11 @@
'file_name':
'tracebox',
'file_size':
- 1339796,
+ 1344188,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm/tracebox',
'sha256':
- '6732165916b74f0b820991d1aaed2086a6b56e91f6c604291efe6636f0bdda71',
+ 'e2feeeaf38c3cd9efbf992dbe09f40fca81651d9fd9159e0f9a95868e2c4e07e',
'platform':
'linux',
'machine': ['armv6l', 'armv7l', 'armv8l']
@@ -96,11 +96,11 @@
'file_name':
'tracebox',
'file_size':
- 2157312,
+ 2164560,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm64/tracebox',
'sha256':
- '7d09865a6d7118e67d2acd0c56b2a94ce8bd5f614869d29a72fe633515ab1fbd',
+ '5d89a6c16819a74be44bf731f2d07bfb83924a2e560554a373feeb2bb9940ef1',
'platform':
'linux',
'machine': ['aarch64']
@@ -112,31 +112,31 @@
'file_size':
1247188,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm/tracebox',
'sha256':
- '4ecc192172ac2bca49557cbdbb1f7d660718d4fb4a7314fd19b2b2e52be8bc0c'
+ '5837e88a92b8bc00d5575f9dc02dd314f16b2e0a1bb174efb6c092a8f639e7c4'
}, {
'arch':
'android-arm64',
'file_name':
'tracebox',
'file_size':
- 1854120,
+ 1870504,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm64/tracebox',
'sha256':
- '1ca89113279d5c6a9ae273bde03b4d84373efe6923dc637cb840908f13b9639e'
+ '75431d11aec11f59b87a76fa31cf92a1f8e534ad4118357b3654a458cf547081'
}, {
'arch':
'android-x86',
'file_name':
'tracebox',
'file_size':
- 1853356,
+ 1869740,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x86/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x86/tracebox',
'sha256':
- 'cf689a191c1252734ebbfda3106600da324610f761515cfbffbeac2ebdfee715'
+ '388da3a4248f105bc56685db4835ce487633035334efa543b7190ac4a9e26bde'
}, {
'arch':
'android-x64',
@@ -145,9 +145,9 @@
'file_size':
2149032,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x64/tracebox',
'sha256':
- '99e9ebdb5b5308d95551a4ad060d615d7defb6877c4061d21c783c45a71d372f'
+ '1c3d50a4066f9b3478ad65431532c3503a2ad73ee89d346e6ee12f7fb0c93aaa'
}]
# ----- Amalgamator: end of python/perfetto/prebuilts/manifests/tracebox.py
diff --git a/tools/trace_processor b/tools/trace_processor
index 60de377..4a839a3 100755
--- a/tools/trace_processor
+++ b/tools/trace_processor
@@ -30,18 +30,18 @@
# ----- Amalgamator: begin of python/perfetto/prebuilts/manifests/trace_processor_shell.py
-# This file has been generated by: tools/roll-prebuilts v40.0
+# This file has been generated by: tools/roll-prebuilts 3e53e144bee271ec558363df2e561a77d7e0b789
TRACE_PROCESSOR_SHELL_MANIFEST = [{
'arch':
'mac-amd64',
'file_name':
'trace_processor_shell',
'file_size':
- 9978200,
+ 10142120,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-amd64/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-amd64/trace_processor_shell',
'sha256':
- 'f3e21eb29fb51cb2ea9b81b69132c5ae93ce3276c57ccd27fcf7c675306b4e41',
+ '44585789d420d0bc38edc3dd6fbade4c4a718dc535fb68ac7a2449bf1a251f30',
'platform':
'darwin',
'machine': ['x86_64']
@@ -51,11 +51,11 @@
'file_name':
'trace_processor_shell',
'file_size':
- 8493976,
+ 8659128,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-arm64/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-arm64/trace_processor_shell',
'sha256':
- '84f35765141374b8d883813ac533e0c004cf72d1c6f05aef0c973364ff541eb9',
+ 'bccca60b99fb2c587503a6430e0b15204ebeddb97607006d54f203e64ac923af',
'platform':
'darwin',
'machine': ['arm64']
@@ -65,11 +65,11 @@
'file_name':
'trace_processor_shell',
'file_size':
- 9830856,
+ 9987880,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-amd64/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-amd64/trace_processor_shell',
'sha256':
- 'b3dc0a9c641b84a57fa5d59637921ae2237e4f05b1778341a691df220faf0cd7',
+ '3510cfc89e627a95ede2d06e77d1ddd70d31ef99d0d213d1fbaba4f438030e4c',
'platform':
'linux',
'machine': ['x86_64']
@@ -79,11 +79,11 @@
'file_name':
'trace_processor_shell',
'file_size':
- 7231096,
+ 7389416,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm/trace_processor_shell',
'sha256':
- 'a21252830fb1bbb7b3fd9665ce6e70920cffa6b1e72c16589c90896c002c3348',
+ '2a87d3587e9a756ea486746ba08e7535dacf8872b1d2081e9381a612668d154d',
'platform':
'linux',
'machine': ['armv6l', 'armv7l', 'armv8l']
@@ -93,11 +93,11 @@
'file_name':
'trace_processor_shell',
'file_size':
- 9238056,
+ 9396856,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm64/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm64/trace_processor_shell',
'sha256':
- 'f77519ec19743ec2c22ed78fe3a20106a482a28d77c4154378af108c5f7bdd4a',
+ '42738a5aa187fe7644d87361fcf9854459f3d46a301026c9ac76ac4bf0ec9d3e',
'platform':
'linux',
'machine': ['aarch64']
@@ -107,55 +107,55 @@
'file_name':
'trace_processor_shell',
'file_size':
- 6870968,
+ 7018688,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm/trace_processor_shell',
'sha256':
- '2c7055fb44085ec60ad8bb970d495c9c88070fce08902f11fcd44e0ae3369876'
+ '9d8247c09b82835dc5019fed2f41e8844162a8cbf520e4243111852d6398911b'
}, {
'arch':
'android-arm64',
'file_name':
'trace_processor_shell',
'file_size':
- 8414568,
+ 8578936,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm64/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm64/trace_processor_shell',
'sha256':
- 'd8ca0dc2bab7ea604a6721f0ac0e2b433b43261f247c6c98c510dc17aafe5a72'
+ '91405004e1a47b1170eb32315f3d0a5b287bc71cb856e7403fad0f02e8b4dfd1'
}, {
'arch':
'android-x86',
'file_name':
'trace_processor_shell',
'file_size':
- 9328508,
+ 9492612,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x86/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x86/trace_processor_shell',
'sha256':
- 'de6a6ea45769888e59a1678d37b6e355b27b834d34a0b9e4980a942d333b88cc'
+ '01364fc6fb485b20d838326462239d14c8f2daf1e7dde524b2cba4fd5acb8a73'
}, {
'arch':
'android-x64',
'file_name':
'trace_processor_shell',
'file_size':
- 9577896,
+ 9742264,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x64/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x64/trace_processor_shell',
'sha256':
- 'cd4b16c5f78a060934204737ba8b312e824ff7cc28f3732daf7d64e733a727f9'
+ '43b456dcd0238f52f5730c6f5b9f8249f096df718d3fefa443c3246d66df4bd6'
}, {
'arch':
'windows-amd64',
'file_name':
'trace_processor_shell.exe',
'file_size':
- 9248256,
+ 9408000,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/windows-amd64/trace_processor_shell.exe',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/windows-amd64/trace_processor_shell.exe',
'sha256':
- '26584b4bbab40f8b0ad991a869e7483f92d7223e1473b879a6ceafa49b76390a',
+ 'b4dc6a7968673373265344e8e5249ccc31f7d12bb9df527370065dff71b1e74a',
'platform':
'win32',
'machine': ['amd64']
diff --git a/tools/tracebox b/tools/tracebox
index a4c278b..402a52d 100755
--- a/tools/tracebox
+++ b/tools/tracebox
@@ -30,18 +30,18 @@
# ----- Amalgamator: begin of python/perfetto/prebuilts/manifests/tracebox.py
-# This file has been generated by: tools/roll-prebuilts v40.0
+# This file has been generated by: tools/roll-prebuilts 3e53e144bee271ec558363df2e561a77d7e0b789
TRACEBOX_MANIFEST = [{
'arch':
'mac-amd64',
'file_name':
'tracebox',
'file_size':
- 1498816,
+ 1515200,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-amd64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-amd64/tracebox',
'sha256':
- '185014447d35357edbd20e7ce9924842a0d5c6576bd2257abae2ed48b65fd3b8',
+ 'b451e873b1f6c8bd2fc3f1e12adc381c77a5b6dce9ec28ad8788e6f7f5efd348',
'platform':
'darwin',
'machine': ['x86_64']
@@ -53,9 +53,9 @@
'file_size':
1392776,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-arm64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-arm64/tracebox',
'sha256':
- '082bb50e64df5e232673eebb1cd8b0dd752a394105f600cb0262730833f6b7f3',
+ '8247045bd78e467aa010674277048658cdf04a95bd15b25dabc973fce011d6db',
'platform':
'darwin',
'machine': ['arm64']
@@ -65,11 +65,11 @@
'file_name':
'tracebox',
'file_size':
- 2229096,
+ 2236584,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-amd64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-amd64/tracebox',
'sha256':
- 'c99120caedb845e1c3fad4428263a683b44c357c76d65848dd8e437250066e38',
+ 'adf6f9ebb5686a7d2e056c8f059adf4d95e867ffa39d27b041bef16d3cb7e1c7',
'platform':
'linux',
'machine': ['x86_64']
@@ -79,11 +79,11 @@
'file_name':
'tracebox',
'file_size':
- 1339796,
+ 1344188,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm/tracebox',
'sha256':
- '6732165916b74f0b820991d1aaed2086a6b56e91f6c604291efe6636f0bdda71',
+ 'e2feeeaf38c3cd9efbf992dbe09f40fca81651d9fd9159e0f9a95868e2c4e07e',
'platform':
'linux',
'machine': ['armv6l', 'armv7l', 'armv8l']
@@ -93,11 +93,11 @@
'file_name':
'tracebox',
'file_size':
- 2157312,
+ 2164560,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm64/tracebox',
'sha256':
- '7d09865a6d7118e67d2acd0c56b2a94ce8bd5f614869d29a72fe633515ab1fbd',
+ '5d89a6c16819a74be44bf731f2d07bfb83924a2e560554a373feeb2bb9940ef1',
'platform':
'linux',
'machine': ['aarch64']
@@ -109,31 +109,31 @@
'file_size':
1247188,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm/tracebox',
'sha256':
- '4ecc192172ac2bca49557cbdbb1f7d660718d4fb4a7314fd19b2b2e52be8bc0c'
+ '5837e88a92b8bc00d5575f9dc02dd314f16b2e0a1bb174efb6c092a8f639e7c4'
}, {
'arch':
'android-arm64',
'file_name':
'tracebox',
'file_size':
- 1854120,
+ 1870504,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm64/tracebox',
'sha256':
- '1ca89113279d5c6a9ae273bde03b4d84373efe6923dc637cb840908f13b9639e'
+ '75431d11aec11f59b87a76fa31cf92a1f8e534ad4118357b3654a458cf547081'
}, {
'arch':
'android-x86',
'file_name':
'tracebox',
'file_size':
- 1853356,
+ 1869740,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x86/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x86/tracebox',
'sha256':
- 'cf689a191c1252734ebbfda3106600da324610f761515cfbffbeac2ebdfee715'
+ '388da3a4248f105bc56685db4835ce487633035334efa543b7190ac4a9e26bde'
}, {
'arch':
'android-x64',
@@ -142,9 +142,9 @@
'file_size':
2149032,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x64/tracebox',
'sha256':
- '99e9ebdb5b5308d95551a4ad060d615d7defb6877c4061d21c783c45a71d372f'
+ '1c3d50a4066f9b3478ad65431532c3503a2ad73ee89d346e6ee12f7fb0c93aaa'
}]
# ----- Amalgamator: end of python/perfetto/prebuilts/manifests/tracebox.py
diff --git a/tools/traceconv b/tools/traceconv
index 0136e37..63997fb 100755
--- a/tools/traceconv
+++ b/tools/traceconv
@@ -30,18 +30,18 @@
# ----- Amalgamator: begin of python/perfetto/prebuilts/manifests/traceconv.py
-# This file has been generated by: tools/roll-prebuilts v40.0
+# This file has been generated by: tools/roll-prebuilts 3e53e144bee271ec558363df2e561a77d7e0b789
TRACECONV_MANIFEST = [{
'arch':
'mac-amd64',
'file_name':
'traceconv',
'file_size':
- 9184800,
+ 9348712,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-amd64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-amd64/traceconv',
'sha256':
- 'b651d0a5b5606c1c3e24723e94d8ecb233a01f0dfccc95a2c6a4e773cb8f52d7',
+ '466110b5d92cfc7951ae3223147156dc3ddfad055f8c7a93fea91b2f1844d013',
'platform':
'darwin',
'machine': ['x86_64']
@@ -51,11 +51,11 @@
'file_name':
'traceconv',
'file_size':
- 7761896,
+ 7927048,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/mac-arm64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/mac-arm64/traceconv',
'sha256':
- '3b019f5ddd5293d3181f7c30f91dc7b08f3a2e83ebb3b52b8f3905dc5161747d',
+ '46663d0eaa88bc821ad71872fd9789c340f9100e22a78494006b94225e2cfe9b',
'platform':
'darwin',
'machine': ['arm64']
@@ -65,11 +65,11 @@
'file_name':
'traceconv',
'file_size':
- 8928296,
+ 9091432,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-amd64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-amd64/traceconv',
'sha256':
- '830d20ffec266218d49f6b6c8efed4538bc59b51d8d2f735cbbb6a1435131b50',
+ 'bb0eabefb6cb22623368d1b51cd95a6d9485781f102a9293443659fdd826fc8f',
'platform':
'linux',
'machine': ['x86_64']
@@ -79,11 +79,11 @@
'file_name':
'traceconv',
'file_size':
- 6770204,
+ 6934532,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm/traceconv',
'sha256':
- '93a9e5ccb94559b871af8f6da45f858aee01801b31776703892dcf3d7ea769b7',
+ 'ce90e026c71a006b01e4d3c247772cfeeeb7581cd2ce1b003de35ddd87e9d349',
'platform':
'linux',
'machine': ['armv6l', 'armv7l', 'armv8l']
@@ -93,11 +93,11 @@
'file_name':
'traceconv',
'file_size':
- 8393944,
+ 8558824,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/linux-arm64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/linux-arm64/traceconv',
'sha256':
- '88a92ccbcd8e851673e018b7f599514daf05dde9b7e4de9641fa5629124abf12',
+ 'f26446b306b0025c54d39dac5b62ae015e0d1771ff5ec461ccbbcc93f1dcb335',
'platform':
'linux',
'machine': ['aarch64']
@@ -107,55 +107,55 @@
'file_name':
'traceconv',
'file_size':
- 6378744,
+ 6542848,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm/traceconv',
'sha256':
- '6cb7d30d656aa4f172e6724f105a56e249e7043ecf637c65e1e3868885535cff'
+ '901512a8243b4015aeba59f547d40736fcf032edeedcd1ecb59c259bba0122cf'
}, {
'arch':
'android-arm64',
'file_name':
'traceconv',
'file_size':
- 7692488,
+ 7856856,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-arm64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-arm64/traceconv',
'sha256':
- '1668808efbdf8d5b116d4716d61d2bd002f71ce465206d3b83af4fcc7a4c19cd'
+ '0eda603b5bc4925b98e0d9656dc18e3e7c4db4685c49f902fd3e1fad1be75efd'
}, {
'arch':
'android-x86',
'file_name':
'traceconv',
'file_size':
- 8557756,
+ 8721860,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x86/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x86/traceconv',
'sha256':
- '653733582cae0021eae0e1b5d8db387c1bae772d77b307f1e2111b78ec4ea67c'
+ 'd9bc2acf1b280198402a81019d6d5c9f75849d0254fd929b62671af6095d6f57'
}, {
'arch':
'android-x64',
'file_name':
'traceconv',
'file_size':
- 8708352,
+ 8872720,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/android-x64/traceconv',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/android-x64/traceconv',
'sha256':
- '7fc564ac581b81d79573f57dae027c47bd7a857ff0f89df984380c3c657d5876'
+ '3c33c2f79a4fb9760cdf2348a09d6fb6fbb8b5098e014e83cd14d3f3dfb8661d'
}, {
'arch':
'windows-amd64',
'file_name':
'traceconv.exe',
'file_size':
- 8204288,
+ 8369664,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v40.0/windows-amd64/traceconv.exe',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/3e53e144bee271ec558363df2e561a77d7e0b789/windows-amd64/traceconv.exe',
'sha256':
- 'e33bad8061f08f9c3cfe6e91ef6f1696b6ac90d0799edcb57052f24888b436e2',
+ '900f931d89af74b84229e1c396898a9c492d49acd15977692040c95a50499936',
'platform':
'win32',
'machine': ['amd64']
diff --git a/ui/release/channels.json b/ui/release/channels.json
index cce73f1..a8c38ae 100644
--- a/ui/release/channels.json
+++ b/ui/release/channels.json
@@ -2,11 +2,11 @@
"channels": [
{
"name": "stable",
- "rev": "fa6ee75b6f4a9374ade506697c65a8a73edc54be"
+ "rev": "ce5cae18bd9a71f9948a6c33315a4cbd2df4c44b"
},
{
"name": "canary",
- "rev": "46dae5655847f65acd49cad6a24ef37c6a85383d"
+ "rev": "4a28823dd05cf2642e17419a4bbbdf5c39dc52bc"
},
{
"name": "autopush",
diff --git a/ui/src/base/logging.ts b/ui/src/base/logging.ts
index 945d96a..8387783 100644
--- a/ui/src/base/logging.ts
+++ b/ui/src/base/logging.ts
@@ -12,11 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {SCM_REVISION, VERSION} from '../gen/perfetto_version';
+import {VERSION} from '../gen/perfetto_version';
-export type ErrorHandler = (err: string) => void;
+export type ErrorType = 'ERROR'|'PROMISE_REJ'|'OTHER';
+export interface ErrorStackEntry {
+ name: string; // e.g. renderCanvas
+ location: string; // e.g. frontend_bundle.js:12:3
+}
+export interface ErrorDetails {
+ errType: ErrorType;
+ message: string; // Uncaught StoreError: No such subtree: tracks,1374,state
+ stack: ErrorStackEntry[];
+}
-let errorHandler: ErrorHandler = (_: string) => {};
+export type ErrorHandler = (err: ErrorDetails) => void;
+const errorHandlers: ErrorHandler[] = [];
export function assertExists<A>(value: A | null | undefined): A {
if (value === null || value === undefined) {
@@ -35,34 +45,86 @@
assertTrue(!value, optMsg);
}
-export function setErrorHandler(handler: ErrorHandler) {
- errorHandler = handler;
+export function addErrorHandler(handler: ErrorHandler) {
+ if (!errorHandlers.includes(handler)) {
+ errorHandlers.push(handler);
+ }
}
export function reportError(err: ErrorEvent|PromiseRejectionEvent|{}) {
- let errLog = '';
let errorObj = undefined;
+ let errMsg = '';
+ let errType: ErrorType;
+ const stack: ErrorStackEntry[] = [];
+ const baseUrl = `${location.protocol}//${location.host}`;
if (err instanceof ErrorEvent) {
- errLog = err.message;
+ errType = 'ERROR';
+ errMsg = err.message;
errorObj = err.error;
} else if (err instanceof PromiseRejectionEvent) {
- errLog = `${err.reason}`;
+ errType = 'PROMISE_REJ';
+ errMsg = `PromiseRejection: ${err.reason}`;
errorObj = err.reason;
} else {
- errLog = `${err}`;
+ errType = 'OTHER';
+ errMsg = `Err: ${err}`;
}
if (errorObj !== undefined && errorObj !== null) {
- const errStack = (errorObj as {stack?: string}).stack;
- errLog += '\n';
- errLog += errStack !== undefined ? errStack : JSON.stringify(errorObj);
- }
- errLog += '\n\n';
- errLog += `${VERSION} ${SCM_REVISION}\n`;
- errLog += `UA: ${navigator.userAgent}\n`;
+ const maybeStack = (errorObj as {stack?: string}).stack;
+ let errStack = maybeStack !== undefined ? `${maybeStack}` : '';
+ errStack = errStack.replaceAll(/\r/g, ''); // Strip Windows CR.
+ for (let line of errStack.split('\n')) {
+ if (errMsg.includes(line)) continue;
+ // Chrome, Firefox and safari don't agree on the stack format:
+ // Chrome: prefixes entries with a ' at ' and uses the format
+ // function(https://url:line:col), e.g.
+ // ' at FooBar (https://.../frontend_bundle.js:2073:15)'
+ // however, if the function name is not known, it prints just:
+ // ' at https://.../frontend_bundle.js:2073:15'
+ // or also:
+ // ' at <anonymous>:5:11'
+ // Firefox and Safari: don't have any prefix and use @ as a separator:
+ // redrawCanvas@https://.../frontend_bundle.js:468814:26
+ // @debugger eval code:1:32
- console.error(errLog, err);
- errorHandler(errLog);
+ // Here we first normalize Chrome into the Firefox/Safari format by
+ // removing the ' at ' prefix and replacing (xxx)$ into @xxx.
+ line = line.replace(/^\s*at\s*/, '');
+ line = line.replace(/\s*\(([^)]+)\)$/, '@$1');
+
+ // This leaves us still with two possible options here:
+ // 1. FooBar@https://ui.perfetto.dev/v123/frontend_bundle.js:2073:15
+ // 2. https://ui.perfetto.dev/v123/frontend_bundle.js:2073:15
+ const lastAt = line.lastIndexOf('@');
+ let entryName = '';
+ let entryLocation = '';
+ if (lastAt >= 0) {
+ entryLocation = line.substring(lastAt + 1);
+ entryName = line.substring(0, lastAt);
+ } else {
+ entryLocation = line;
+ }
+
+ // Remove redundant https://ui.perfetto.dev/v38.0-d6ed090ee/ as we have
+ // that information already and don't need to repeat it on each line.
+ if (entryLocation.includes(baseUrl)) {
+ entryLocation = entryLocation.replace(baseUrl, '');
+ entryLocation = entryLocation.replace(`/${VERSION}/`, '');
+ }
+ stack.push({name: entryName, location: entryLocation});
+ }
+ }
+ // Invoke all the handlers registered through addErrorHandler.
+ // There are usually two handlers registered, one for the UI (error_dialog.ts)
+ // and one for Analytics (analytics.ts).
+ for (const handler of errorHandlers) {
+ handler({
+ errType,
+ message: errMsg,
+ stack,
+ } as ErrorDetails);
+ }
}
// This function serves two purposes.
diff --git a/ui/src/common/canvas_utils.ts b/ui/src/common/canvas_utils.ts
index ad78f96..2f56b5f 100644
--- a/ui/src/common/canvas_utils.ts
+++ b/ui/src/common/canvas_utils.ts
@@ -151,7 +151,7 @@
y -= 10;
// Ensure the box is on screen:
- const endPx = globals.frontendLocalState.visibleTimeScale.pxSpan.end;
+ const endPx = globals.timeline.visibleTimeScale.pxSpan.end;
if (x + width > endPx) {
x -= x + width - endPx;
}
diff --git a/ui/src/common/recordingV2/recording_config_utils.ts b/ui/src/common/recordingV2/recording_config_utils.ts
index aadb254..94e4993 100644
--- a/ui/src/common/recordingV2/recording_config_utils.ts
+++ b/ui/src/common/recordingV2/recording_config_utils.ts
@@ -154,12 +154,14 @@
protoCfg.dataSources.push(ds);
}
+ let ftrace = false;
+ let symbolizeKsyms = false;
if (uiCfg.cpuSched) {
procThreadAssociationPolling = true;
procThreadAssociationFtrace = true;
- uiCfg.ftrace = true;
+ ftrace = true;
if (enableSchedBlockedReason(androidApiLevel)) {
- uiCfg.symbolizeKsyms = true;
+ symbolizeKsyms = true;
}
ftraceEvents.add('sched/sched_switch');
ftraceEvents.add('power/suspend_resume');
@@ -612,7 +614,7 @@
protoCfg.dataSources.push(ds);
}
- if (uiCfg.ftrace || uiCfg.atrace || ftraceEvents.size > 0 ||
+ if (uiCfg.ftrace || ftrace || uiCfg.atrace || ftraceEvents.size > 0 ||
atraceCats.size > 0 || atraceApps.size > 0) {
const ds = new TraceConfig.DataSource();
ds.config = new DataSourceConfig();
@@ -620,14 +622,14 @@
ds.config.ftraceConfig = new FtraceConfig();
// Override the advanced ftrace parameters only if the user has ticked the
// "Advanced ftrace config" tab.
- if (uiCfg.ftrace) {
+ if (uiCfg.ftrace || ftrace) {
if (uiCfg.ftraceBufferSizeKb) {
ds.config.ftraceConfig.bufferSizeKb = uiCfg.ftraceBufferSizeKb;
}
if (uiCfg.ftraceDrainPeriodMs) {
ds.config.ftraceConfig.drainPeriodMs = uiCfg.ftraceDrainPeriodMs;
}
- if (uiCfg.symbolizeKsyms) {
+ if (uiCfg.symbolizeKsyms || symbolizeKsyms) {
ds.config.ftraceConfig.symbolizeKsyms = true;
ftraceEvents.add('sched/sched_blocked_reason');
}
diff --git a/ui/src/common/recordingV2/recording_config_utils_unittest.ts b/ui/src/common/recordingV2/recording_config_utils_unittest.ts
new file mode 100644
index 0000000..aca575e
--- /dev/null
+++ b/ui/src/common/recordingV2/recording_config_utils_unittest.ts
@@ -0,0 +1,90 @@
+// Copyright (C) 2023 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.
+
+import {createEmptyRecordConfig} from '../../controller/record_config_types';
+
+import {genTraceConfig} from './recording_config_utils';
+import {AndroidTargetInfo} from './recording_interfaces_v2';
+
+test('genTraceConfig() can run without manipulating the input config', () => {
+ const config = createEmptyRecordConfig();
+ config.cpuSched = true; // Exercise ftrace
+
+ const targetInfo: AndroidTargetInfo = {
+ name: 'test',
+ targetType: 'ANDROID',
+ androidApiLevel: 31, // >= 32 to exercise symbolizeKsyms
+ dataSources: [],
+ };
+
+ Object.freeze(config);
+ const actual = genTraceConfig(config, targetInfo);
+
+ const expected = {
+ 'buffers': [
+ {
+ 'sizeKb': 63488,
+ 'fillPolicy': 'DISCARD',
+ },
+ {
+ 'sizeKb': 2048,
+ 'fillPolicy': 'DISCARD',
+ },
+ ],
+ 'dataSources': [
+ {
+ 'config': {
+ 'name': 'android.packages_list',
+ 'targetBuffer': 1,
+ },
+ },
+ {
+ 'config': {
+ 'name': 'linux.process_stats',
+ 'targetBuffer': 1,
+ 'processStatsConfig': {
+ 'scanAllProcessesOnStart': true,
+ },
+ },
+ },
+ {
+ 'config': {
+ 'name': 'linux.ftrace',
+ 'ftraceConfig': {
+ 'ftraceEvents': [
+ 'sched/sched_switch',
+ 'power/suspend_resume',
+ 'sched/sched_wakeup',
+ 'sched/sched_wakeup_new',
+ 'sched/sched_waking',
+ 'sched/sched_process_exit',
+ 'sched/sched_process_free',
+ 'task/task_newtask',
+ 'task/task_rename',
+ 'sched/sched_blocked_reason',
+ ],
+ 'compactSched': {
+ 'enabled': true,
+ },
+ 'symbolizeKsyms': true,
+ },
+ },
+ },
+ ],
+ 'durationMs': 10000,
+ };
+
+ // Compare stringified versions to void issues with JS objects.
+ expect(JSON.stringify(actual)).toEqual(JSON.stringify(expected));
+});
diff --git a/ui/src/common/track_helper.ts b/ui/src/common/track_helper.ts
index 8990a44..3a11596 100644
--- a/ui/src/common/track_helper.ts
+++ b/ui/src/common/track_helper.ts
@@ -14,14 +14,13 @@
import m from 'mithril';
-import {duration, Time, time} from '../base/time';
+import {Disposable} from '../base/disposable';
+import {duration, Time, time, TimeSpan} from '../base/time';
import {raf} from '../core/raf_scheduler';
import {globals} from '../frontend/globals';
import {PanelSize} from '../frontend/panel';
import {SliceRect, Track, TrackContext} from '../public';
-import {TrackData} from './track_data';
-
export {Store} from '../frontend/store';
export {EngineProxy} from '../trace_processor/engine';
export {
@@ -33,6 +32,97 @@
STR_NULL,
} from '../trace_processor/query_result';
+type FetchTimeline<Data> = (start: time, end: time, resolution: duration) =>
+ Promise<Data>;
+
+// This helper provides the logic to call |doFetch()| only when more
+// data is needed as the visible window is panned and zoomed about, and
+// includes an FSM to ensure doFetch is not re-entered.
+class TimelineFetcher<Data> implements Disposable {
+ private requestingData = false;
+ private queuedRequest = false;
+ private doFetch: FetchTimeline<Data>;
+
+ private data_?: Data;
+
+ // Timespan and resolution of the latest *request*. data_ may cover
+ // a different time window.
+ private latestTimespan: TimeSpan;
+ private latestResolution: duration;
+
+ constructor(doFetch: FetchTimeline<Data>) {
+ this.doFetch = doFetch;
+ this.latestTimespan = TimeSpan.ZERO;
+ this.latestResolution = 0n;
+ }
+
+ requestDataForCurrentTime(): void {
+ const currentTimeSpan = globals.timeline.visibleTimeSpan;
+ const currentResolution = globals.getCurResolution();
+ this.requestData(currentTimeSpan, currentResolution);
+ }
+
+ requestData(timespan: TimeSpan, resolution: duration): void {
+ if (this.shouldLoadNewData(timespan, resolution)) {
+ // Over request data, one page worth to the left and right.
+ const start = Time.sub(timespan.start, timespan.duration);
+ const end = Time.add(timespan.end, timespan.duration);
+ this.latestTimespan = new TimeSpan(start, end);
+ this.latestResolution = resolution;
+ this.loadData();
+ }
+ }
+
+ get data(): Data|undefined {
+ return this.data_;
+ }
+
+ dispose() {
+ this.queuedRequest = false;
+ this.data_ = undefined;
+ }
+
+ private shouldLoadNewData(timespan: TimeSpan, resolution: duration): boolean {
+ if (this.data_ === undefined) {
+ return true;
+ }
+
+ if (timespan.start < this.latestTimespan.start) {
+ return true;
+ }
+
+ if (timespan.end > this.latestTimespan.end) {
+ return true;
+ }
+
+ if (resolution !== this.latestResolution) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private loadData(): void {
+ if (this.requestingData) {
+ this.queuedRequest = true;
+ return;
+ }
+ const {start, end} = this.latestTimespan;
+ const resolution = this.latestResolution;
+ this.doFetch(start, end, resolution).then((data) => {
+ this.requestingData = false;
+ this.data_ = data;
+ if (this.queuedRequest) {
+ this.queuedRequest = false;
+ this.loadData();
+ } else {
+ raf.scheduleRedraw();
+ }
+ });
+ this.requestingData = true;
+ }
+}
+
// A helper class which provides a base track implementation for tracks which
// load their content asynchronously from the trace.
//
@@ -49,17 +139,21 @@
// Note: This class is deprecated and should not be used for new tracks. Use
// |BaseSliceTrack| instead.
export abstract class TrackHelperLEGACY<Data> implements Track {
- private requestingData = false;
- private queuedRequest = false;
- private currentState?: TrackData;
- protected data?: Data;
+ private timelineFetcher: TimelineFetcher<Data>;
+
+ constructor() {
+ this.timelineFetcher =
+ new TimelineFetcher<Data>(this.onBoundsChange.bind(this));
+ }
onCreate(_ctx: TrackContext): void {}
onDestroy(): void {
- this.queuedRequest = false;
- this.currentState = undefined;
- this.data = undefined;
+ this.timelineFetcher.dispose();
+ }
+
+ get data(): Data|undefined {
+ return this.timelineFetcher.data;
}
// Returns a place where a given slice should be drawn. Should be implemented
@@ -93,65 +187,7 @@
abstract renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void;
render(ctx: CanvasRenderingContext2D, size: PanelSize): void {
- if (this.shouldLoadNewData()) {
- this.loadData();
- }
-
+ this.timelineFetcher.requestDataForCurrentTime();
this.renderCanvas(ctx, size);
}
-
- private loadData(): void {
- if (this.requestingData) {
- this.queuedRequest = true;
- return;
- }
-
- const ts = globals.frontendLocalState.visibleTimeSpan;
- const resolution = globals.getCurResolution();
-
- const start = Time.sub(ts.start, ts.duration);
- const end = Time.add(ts.end, ts.duration);
-
- this.currentState = {
- start,
- end,
- resolution,
- length: 0,
- };
-
- this.onBoundsChange(start, end, resolution).then((data) => {
- this.requestingData = false;
- this.data = data;
-
- if (this.queuedRequest) {
- this.queuedRequest = false;
- this.loadData();
- } else {
- raf.scheduleRedraw();
- }
- });
-
- this.requestingData = true;
- }
-
- private shouldLoadNewData(): boolean {
- if (!this.currentState) {
- return true;
- }
-
- const ts = globals.frontendLocalState.visibleTimeSpan;
- if (ts.start < this.currentState.start) {
- return true;
- }
-
- if (ts.end > this.currentState.end) {
- return true;
- }
-
- if (globals.getCurResolution() !== this.currentState.resolution) {
- return true;
- }
-
- return false;
- }
}
diff --git a/ui/src/controller/ftrace_controller.ts b/ui/src/controller/ftrace_controller.ts
index e596ff4..e4f13cc 100644
--- a/ui/src/controller/ftrace_controller.ts
+++ b/ui/src/controller/ftrace_controller.ts
@@ -49,7 +49,7 @@
run() {
if (this.shouldUpdate()) {
- this.oldSpan = globals.frontendLocalState.visibleWindowTime;
+ this.oldSpan = globals.timeline.visibleWindowTime;
this.oldFtraceFilter = globals.state.ftraceFilter;
this.oldPagination = globals.state.ftracePagination;
if (globals.state.ftracePagination.count > 0) {
@@ -69,7 +69,7 @@
private shouldUpdate(): boolean {
// Has the visible window moved?
- const visibleWindow = globals.frontendLocalState.visibleWindowTime;
+ const visibleWindow = globals.timeline.visibleWindowTime;
if (!this.oldSpan.equals(visibleWindow)) {
return true;
}
diff --git a/ui/src/controller/track_decider.ts b/ui/src/controller/track_decider.ts
index 1df6bee..afeb64f 100644
--- a/ui/src/controller/track_decider.ts
+++ b/ui/src/controller/track_decider.ts
@@ -1658,7 +1658,7 @@
async decideTracks(): Promise<DeferredAction[]> {
{
- const result = screenshotDecideTracks();
+ const result = screenshotDecideTracks(this.engine);
if (result !== null) {
const {tracksToAdd} = await result;
this.tracksToAdd.push(...tracksToAdd);
diff --git a/ui/src/frontend/analytics.ts b/ui/src/frontend/analytics.ts
index 74c42fc..25f8e96 100644
--- a/ui/src/frontend/analytics.ts
+++ b/ui/src/frontend/analytics.ts
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {ErrorDetails} from '../base/logging';
import {getCurrentChannel} from '../common/channels';
import {VERSION} from '../gen/perfetto_version';
@@ -58,16 +59,16 @@
export interface Analytics {
initialize(): void;
updatePath(_: string): void;
- logEvent(_x: TraceCategories|null, _y: string): void;
- logError(_x: string, _y?: boolean): void;
+ logEvent(category: TraceCategories|null, event: string): void;
+ logError(err: ErrorDetails): void;
isEnabled(): boolean;
}
export class NullAnalytics implements Analytics {
initialize() {}
updatePath(_: string) {}
- logEvent(_x: TraceCategories|null, _y: string) {}
- logError(_x: string) {}
+ logEvent(_category: TraceCategories|null, _event: string) {}
+ logError(_err: ErrorDetails) {}
isEnabled(): boolean {
return false;
}
@@ -135,8 +136,24 @@
gtagGlobals.gtag('event', event, {event_category: category});
}
- logError(description: string, fatal = true) {
- gtagGlobals.gtag('event', 'exception', {description, fatal});
+ logError(err: ErrorDetails) {
+ let stack = '';
+ for (const entry of err.stack) {
+ const shortLocation = entry.location.replace('frontend_bundle.js', '$');
+ stack += `${entry.name}(${shortLocation}),`;
+ }
+ // Strip trailing ',' (works also for empty strings without extra checks).
+ stack = stack.substring(0, stack.length - 1);
+
+ gtagGlobals.gtag('event', 'exception', {
+ description: err.message,
+ error_type: err.errType,
+
+ // As per GA4 all field are restrictred to 100 chars.
+ // page_title is the only one restricted to 1000 chars and we use that for
+ // the full crash report.
+ page_location: `http://crash?/${encodeURI(stack)}`,
+ });
}
isEnabled(): boolean {
diff --git a/ui/src/frontend/base_counter_track.ts b/ui/src/frontend/base_counter_track.ts
index 5081cb7..079fb1a 100644
--- a/ui/src/frontend/base_counter_track.ts
+++ b/ui/src/frontend/base_counter_track.ts
@@ -180,7 +180,7 @@
const {
visibleTimeScale: timeScale,
visibleWindowTime: vizTime,
- } = globals.frontendLocalState;
+ } = globals.timeline;
{
const windowSizePx = Math.max(1, timeScale.pxSpan.delta);
@@ -383,7 +383,7 @@
const data = this.counters;
if (data === undefined) return;
this.mousePos = pos;
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const time = visibleTimeScale.pxToHpTime(pos.x);
let values = data.lastValues;
diff --git a/ui/src/frontend/base_slice_track.ts b/ui/src/frontend/base_slice_track.ts
index 95855cf..30778c2 100644
--- a/ui/src/frontend/base_slice_track.ts
+++ b/ui/src/frontend/base_slice_track.ts
@@ -332,7 +332,7 @@
const {
visibleTimeScale: timeScale,
visibleWindowTime: vizTime,
- } = globals.frontendLocalState;
+ } = globals.timeline;
{
const windowSizePx = Math.max(1, timeScale.pxSpan.delta);
@@ -816,7 +816,7 @@
}
for (const slice of this.incomplete) {
- const visibleTimeScale = globals.frontendLocalState.visibleTimeScale;
+ const visibleTimeScale = globals.timeline.visibleTimeScale;
const startPx = CROP_INCOMPLETE_SLICE_FLAG.get() ?
visibleTimeScale.timeToPx(slice.startNsQ) :
slice.x;
@@ -973,7 +973,7 @@
windowSpan,
visibleTimeScale,
visibleTimeSpan,
- } = globals.frontendLocalState;
+ } = globals.timeline;
const pxEnd = windowSpan.end;
const left = Math.max(visibleTimeScale.timeToPx(tStart), 0);
diff --git a/ui/src/frontend/drag/drag_strategy.ts b/ui/src/frontend/drag/drag_strategy.ts
index 7c6a1ca..869921e 100644
--- a/ui/src/frontend/drag/drag_strategy.ts
+++ b/ui/src/frontend/drag/drag_strategy.ts
@@ -28,7 +28,7 @@
protected updateGlobals(tStart: HighPrecisionTime, tEnd: HighPrecisionTime) {
const vizTime = new HighPrecisionTimeSpan(tStart, tEnd);
- globals.frontendLocalState.updateVisibleTime(vizTime);
+ globals.timeline.updateVisibleTime(vizTime);
raf.scheduleRedraw();
}
}
diff --git a/ui/src/frontend/error_dialog.ts b/ui/src/frontend/error_dialog.ts
index e94bfd7..008f1bc 100644
--- a/ui/src/frontend/error_dialog.ts
+++ b/ui/src/frontend/error_dialog.ts
@@ -14,30 +14,26 @@
import m from 'mithril';
-import {assertExists} from '../base/logging';
+import {assertExists, ErrorDetails} from '../base/logging';
import {EXTENSION_URL} from '../common/recordingV2/recording_utils';
import {TraceUrlSource} from '../common/state';
import {saveTrace} from '../common/upload_utils';
import {RECORDING_V2_FLAG} from '../core/feature_flags';
+import {VERSION} from '../gen/perfetto_version';
import {globals} from './globals';
import {showModal} from './modal';
import {isShareable} from './trace_attrs';
-// Never show more than one dialog per minute.
-const MIN_REPORT_PERIOD_MS = 60000;
+// Never show more than one dialog per 10s.
+const MIN_REPORT_PERIOD_MS = 10000;
let timeLastReport = 0;
-// Keeps the last ERR_QUEUE_MAX_LEN errors while the dialog is throttled.
-const queuedErrors = new Array<string>();
-const ERR_QUEUE_MAX_LEN = 10;
-
-export function maybeShowErrorDialog(errLog: string) {
- globals.logging.logError(errLog);
+export function maybeShowErrorDialog(err: ErrorDetails) {
const now = performance.now();
// Here we rely on the exception message from onCannotGrowMemory function
- if (errLog.includes('Cannot enlarge memory')) {
+ if (err.message.includes('Cannot enlarge memory')) {
showOutOfMemoryDialog();
// Refresh timeLastReport to prevent a different error showing a dialog
timeLastReport = now;
@@ -45,46 +41,37 @@
}
if (!RECORDING_V2_FLAG.get()) {
- if (errLog.includes('Unable to claim interface')) {
+ if (err.message.includes('Unable to claim interface')) {
showWebUSBError();
timeLastReport = now;
return;
}
- if (errLog.includes('A transfer error has occurred') ||
- errLog.includes('The device was disconnected') ||
- errLog.includes('The transfer was cancelled')) {
+ if (err.message.includes('A transfer error has occurred') ||
+ err.message.includes('The device was disconnected') ||
+ err.message.includes('The transfer was cancelled')) {
showConnectionLostError();
timeLastReport = now;
return;
}
}
- if (errLog.includes('(ERR:fmt)')) {
+ if (err.message.includes('(ERR:fmt)')) {
showUnknownFileError();
return;
}
- if (errLog.includes('(ERR:rpc_seq)')) {
+ if (err.message.includes('(ERR:rpc_seq)')) {
showRpcSequencingError();
return;
}
if (timeLastReport > 0 && now - timeLastReport <= MIN_REPORT_PERIOD_MS) {
- queuedErrors.unshift(errLog);
- if (queuedErrors.length > ERR_QUEUE_MAX_LEN) queuedErrors.pop();
console.log('Suppressing crash dialog, last error notified too soon.');
return;
}
timeLastReport = now;
-
- // Append queued errors.
- while (queuedErrors.length > 0) {
- const queuedErr = queuedErrors.shift();
- errLog += `\n\n---------------------------------------\n${queuedErr}`;
- }
-
- const errTitle = errLog.split('\n', 1)[0].substr(0, 80);
+ const errTitle = err.message.split('\n', 1)[0].substring(0, 80);
const userDescription = '';
let checked = false;
const engine = globals.getCurrentEngine();
@@ -98,13 +85,13 @@
checked = (ev.target as HTMLInputElement).checked;
if (checked && engine && engine.source.type === 'FILE') {
saveTrace(engine.source.file).then((url) => {
- const errMessage = createErrorMessage(errLog, checked, url);
+ const errMessage = createErrorMessage(err, checked, url);
renderModal(
errTitle, errMessage, userDescription, shareTraceSection);
return;
});
}
- const errMessage = createErrorMessage(errLog, checked);
+ const errMessage = createErrorMessage(err, checked);
renderModal(
errTitle, errMessage, userDescription, shareTraceSection);
},
@@ -118,7 +105,7 @@
}
renderModal(
errTitle,
- createErrorMessage(errLog, checked),
+ createErrorMessage(err, checked),
userDescription,
shareTraceSection);
}
@@ -171,20 +158,28 @@
engine.source.url !== undefined;
}
-function createErrorMessage(errLog: string, checked: boolean, url?: string) {
- let errMessage = '';
+function createErrorMessage(err: ErrorDetails, checked: boolean, url?: string) {
+ let msg = `UI: ${location.protocol}//${location.host}/${VERSION}\n\n`;
+
+ // Append the trace stack.
+ msg += `${err.message}\n`;
+ for (const entry of err.stack) {
+ msg += ` - ${entry.name} (${entry.location})\n`;
+ }
+ msg += '\n';
+
+ // Append the trace URL.
const engine = globals.getCurrentEngine();
if (checked && url !== undefined) {
- errMessage += `Trace: ${url}`;
+ msg += `Trace: ${url}\n`;
} else if (urlExists()) {
- errMessage +=
- `Trace: ${(assertExists(engine).source as TraceUrlSource).url}`;
+ msg += `Trace: ${(assertExists(engine).source as TraceUrlSource).url}\n`;
} else {
- errMessage += 'To assist with debugging please attach or link to the ' +
- 'trace you were viewing.';
+ msg += 'Trace: not available, please provide repro steps.\n';
}
- return errMessage + '\n\n' +
- 'Viewed on: ' + self.location.origin + '\n\n' + errLog;
+ msg += `UA: ${navigator.userAgent}\n`;
+ msg += `Referrer: ${document.referrer}\n`;
+ return msg;
}
function createLink(
diff --git a/ui/src/frontend/flow_events_renderer.ts b/ui/src/frontend/flow_events_renderer.ts
index 12ce93c..8d2da34 100644
--- a/ui/src/frontend/flow_events_renderer.ts
+++ b/ui/src/frontend/flow_events_renderer.ts
@@ -135,7 +135,7 @@
}
private getXCoordinate(ts: time): number {
- return globals.frontendLocalState.visibleTimeScale.timeToPx(ts);
+ return globals.timeline.visibleTimeScale.timeToPx(ts);
}
private getSliceRect(args: FlowEventsRendererArgs, point: FlowPoint):
diff --git a/ui/src/frontend/frontend_local_state.ts b/ui/src/frontend/frontend_local_state.ts
index a649966..6394672 100644
--- a/ui/src/frontend/frontend_local_state.ts
+++ b/ui/src/frontend/frontend_local_state.ts
@@ -136,7 +136,7 @@
* State that is shared between several frontend components, but not the
* controller. This state is updated at 60fps.
*/
-export class FrontendLocalState {
+export class Timeline {
private visibleWindow = new TimeWindow();
private _timeScale = this.visibleWindow.createTimeScale(0, 0);
private _windowSpan = PxSpan.ZERO;
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index 435bf99..845c0d5 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -51,7 +51,7 @@
import {Analytics, initAnalytics} from './analytics';
import {BottomTabList} from './bottom_tab';
-import {FrontendLocalState} from './frontend_local_state';
+import {Timeline} from './frontend_local_state';
import {Router} from './router';
import {horizontalScrollToTs} from './scroll_helper';
import {ServiceWorkerController} from './service_worker_controller';
@@ -248,7 +248,7 @@
private _testing = false;
private _dispatch?: Dispatch = undefined;
private _store?: Store<State>;
- private _frontendLocalState?: FrontendLocalState = undefined;
+ private _timeline?: Timeline = undefined;
private _serviceWorkerController?: ServiceWorkerController = undefined;
private _logging?: Analytics = undefined;
private _isInternalUser: boolean|undefined = undefined;
@@ -315,7 +315,7 @@
this._router = router;
this._store = createStore(initialState);
this._cmdManager = cmdManager;
- this._frontendLocalState = new FrontendLocalState();
+ this._timeline = new Timeline();
setPerfHooks(
() => this.state.perfDebug,
@@ -379,8 +379,8 @@
}
}
- get frontendLocalState() {
- return assertExists(this._frontendLocalState);
+ get timeline() {
+ return assertExists(this._timeline);
}
get logging() {
@@ -599,7 +599,7 @@
// levels. Logic: each zoom level represents a delta of 0.1 * (visible
// window span). Therefore, zooming out by six levels is 1.1^6 ~= 2.
// Similarily, zooming in six levels is 0.9^6 ~= 0.5.
- const timeScale = this.frontendLocalState.visibleTimeScale;
+ const timeScale = this.timeline.visibleTimeScale;
// TODO(b/186265930): Remove once fixed:
if (timeScale.pxSpan.delta === 0) {
console.error(`b/186265930: Bad pxToSec suppressed`);
@@ -656,7 +656,7 @@
resetForTesting() {
this._dispatch = undefined;
this._store = undefined;
- this._frontendLocalState = undefined;
+ this._timeline = undefined;
this._serviceWorkerController = undefined;
// TODO(hjd): Unify trackDataStore, queryResults, overviewStore, threads.
diff --git a/ui/src/frontend/gridline_helper.ts b/ui/src/frontend/gridline_helper.ts
index 04c24b3..60d959f 100644
--- a/ui/src/frontend/gridline_helper.ts
+++ b/ui/src/frontend/gridline_helper.ts
@@ -178,7 +178,7 @@
// Gets the timescale associated with the current visible window.
export function timeScaleForVisibleWindow(
startPx: number, endPx: number): TimeScale {
- return globals.frontendLocalState.getTimeScale(startPx, endPx);
+ return globals.timeline.getTimeScale(startPx, endPx);
}
export function drawGridLines(
@@ -188,7 +188,7 @@
ctx.strokeStyle = TRACK_BORDER_COLOR;
ctx.lineWidth = 1;
- const span = globals.frontendLocalState.visibleTimeSpan;
+ const span = globals.timeline.visibleTimeSpan;
if (width > TRACK_SHELL_WIDTH && span.duration > 0n) {
const maxMajorTicks = getMaxMajorTicks(width - TRACK_SHELL_WIDTH);
const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, width);
diff --git a/ui/src/frontend/index.ts b/ui/src/frontend/index.ts
index 52f0c1a..866e567 100644
--- a/ui/src/frontend/index.ts
+++ b/ui/src/frontend/index.ts
@@ -20,7 +20,7 @@
import m from 'mithril';
import {defer} from '../base/deferred';
-import {reportError, setErrorHandler} from '../base/logging';
+import {addErrorHandler, reportError} from '../base/logging';
import {Actions, DeferredAction, StateActions} from '../common/actions';
import {CommandManager} from '../common/commands';
import {createEmptyState} from '../common/empty_state';
@@ -72,7 +72,7 @@
// recently than the visible time handled by the frontend @ 60fps,
// update it. This typically happens when restoring the state from a
// permalink.
- globals.frontendLocalState.mergeState(state.frontendLocalState);
+ globals.timeline.mergeState(state.frontendLocalState);
// Only redraw if something other than the frontendLocalState changed.
let key: keyof State;
@@ -206,8 +206,11 @@
document.head.append(script, css);
+ // Route errors to both the UI bugreport dialog and Analytics (if enabled).
+ addErrorHandler(maybeShowErrorDialog);
+ addErrorHandler((e) => globals.logging.logError(e));
+
// Add Error handlers for JS error and for uncaught exceptions in promises.
- setErrorHandler((err: string) => maybeShowErrorDialog(err));
window.addEventListener('error', (e) => reportError(e));
window.addEventListener('unhandledrejection', (e) => reportError(e));
diff --git a/ui/src/frontend/keyboard_event_handler.ts b/ui/src/frontend/keyboard_event_handler.ts
index e27f83c..386167f 100644
--- a/ui/src/frontend/keyboard_event_handler.ts
+++ b/ui/src/frontend/keyboard_event_handler.ts
@@ -80,7 +80,7 @@
return true;
}
if (down && 'escape' === key) {
- globals.frontendLocalState.deselectArea();
+ globals.timeline.deselectArea();
globals.makeSelection(Actions.deselect({}));
globals.dispatch(Actions.removeNote({id: '0'}));
return true;
diff --git a/ui/src/frontend/logs_panel.ts b/ui/src/frontend/logs_panel.ts
index c05b881..cd17638 100644
--- a/ui/src/frontend/logs_panel.ts
+++ b/ui/src/frontend/logs_panel.ts
@@ -93,7 +93,7 @@
firstVisibleLogTs,
lastVisibleLogTs,
} = this.bounds;
- const vis = globals.frontendLocalState.visibleWindowTime;
+ const vis = globals.timeline.visibleWindowTime;
const visibleLogSpan =
new HighPrecisionTimeSpan(firstVisibleLogTs, lastVisibleLogTs);
diff --git a/ui/src/frontend/notes_panel.ts b/ui/src/frontend/notes_panel.ts
index 1d7589c..b3a3d13 100644
--- a/ui/src/frontend/notes_panel.ts
+++ b/ui/src/frontend/notes_panel.ts
@@ -124,8 +124,8 @@
ctx.rect(TRACK_SHELL_WIDTH, 0, size.width - TRACK_SHELL_WIDTH, size.height);
ctx.clip();
- const span = globals.frontendLocalState.visibleTimeSpan;
- const {visibleTimeScale} = globals.frontendLocalState;
+ const span = globals.timeline.visibleTimeSpan;
+ const {visibleTimeScale} = globals.timeline;
if (size.width > TRACK_SHELL_WIDTH && span.duration > 0n) {
const maxMajorTicks = getMaxMajorTicks(size.width - TRACK_SHELL_WIDTH);
const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width);
@@ -267,7 +267,7 @@
private onClick(x: number, _: number) {
if (x < 0) return;
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const timestamp = visibleTimeScale.pxToHpTime(x).toTime();
for (const note of Object.values(globals.state.notes)) {
if (this.hoveredX && this.mouseOverNote(this.hoveredX, note)) {
@@ -285,7 +285,7 @@
}
private mouseOverNote(x: number, note: AreaNote|Note): boolean {
- const timeScale = globals.frontendLocalState.visibleTimeScale;
+ const timeScale = globals.timeline.visibleTimeScale;
const noteX = timeScale.timeToPx(getStartTimestamp(note));
if (note.noteType === 'AREA') {
const noteArea = globals.state.areas[note.areaId];
diff --git a/ui/src/frontend/overview_timeline_panel.ts b/ui/src/frontend/overview_timeline_panel.ts
index edda1d3..12ffc28 100644
--- a/ui/src/frontend/overview_timeline_panel.ts
+++ b/ui/src/frontend/overview_timeline_panel.ts
@@ -226,7 +226,7 @@
}
private static extractBounds(timeScale: TimeScale): [number, number] {
- const vizTime = globals.frontendLocalState.visibleWindowTime;
+ const vizTime = globals.timeline.visibleWindowTime;
return [
Math.floor(timeScale.hpTimeToPx(vizTime.start)),
Math.ceil(timeScale.hpTimeToPx(vizTime.end)),
diff --git a/ui/src/frontend/panel_container.ts b/ui/src/frontend/panel_container.ts
index 5497d8e..4365896 100644
--- a/ui/src/frontend/panel_container.ts
+++ b/ui/src/frontend/panel_container.ts
@@ -121,10 +121,9 @@
// This finds the tracks covered by the in-progress area selection. When
// editing areaY is not set, so this will not be used.
handleAreaSelection() {
- const area = globals.frontendLocalState.selectedArea;
- if (area === undefined ||
- globals.frontendLocalState.areaY.start === undefined ||
- globals.frontendLocalState.areaY.end === undefined ||
+ const area = globals.timeline.selectedArea;
+ if (area === undefined || globals.timeline.areaY.start === undefined ||
+ globals.timeline.areaY.end === undefined ||
this.panelInfos.length === 0) {
return;
}
@@ -133,22 +132,20 @@
const panelContainerTop = this.panelInfos[0].y;
const panelContainerBottom = this.panelInfos[this.panelInfos.length - 1].y +
this.panelInfos[this.panelInfos.length - 1].height;
- if (globals.frontendLocalState.areaY.start + TOPBAR_HEIGHT <
- panelContainerTop ||
- globals.frontendLocalState.areaY.start + TOPBAR_HEIGHT >
- panelContainerBottom) {
+ if (globals.timeline.areaY.start + TOPBAR_HEIGHT < panelContainerTop ||
+ globals.timeline.areaY.start + TOPBAR_HEIGHT > panelContainerBottom) {
return;
}
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
// The Y value is given from the top of the pan and zoom region, we want it
// from the top of the panel container. The parent offset corrects that.
const panels = this.getPanelsInRegion(
visibleTimeScale.timeToPx(area.start),
visibleTimeScale.timeToPx(area.end),
- globals.frontendLocalState.areaY.start + TOPBAR_HEIGHT,
- globals.frontendLocalState.areaY.end + TOPBAR_HEIGHT);
+ globals.timeline.areaY.start + TOPBAR_HEIGHT,
+ globals.timeline.areaY.end + TOPBAR_HEIGHT);
// Get the track ids from the panels.
const tracks = [];
for (const panel of panels) {
@@ -167,7 +164,7 @@
}
}
}
- globals.frontendLocalState.selectArea(area.start, area.end, tracks);
+ globals.timeline.selectArea(area.start, area.end, tracks);
}
constructor(vnode: m.CVnode<Attrs>) {
@@ -288,7 +285,7 @@
this.updateCanvasDimensions();
this.repositionCanvas();
if (this.attrs.kind === 'TRACKS') {
- globals.frontendLocalState.updateLocalLimits(
+ globals.timeline.updateLocalLimits(
0, this.parentWidth - TRACK_SHELL_WIDTH);
}
this.redrawCanvas();
@@ -430,10 +427,9 @@
// the whole canvas rather than per panel.
private drawTopLayerOnCanvas() {
if (!this.ctx) return;
- const area = globals.frontendLocalState.selectedArea;
- if (area === undefined ||
- globals.frontendLocalState.areaY.start === undefined ||
- globals.frontendLocalState.areaY.end === undefined) {
+ const area = globals.timeline.selectedArea;
+ if (area === undefined || globals.timeline.areaY.start === undefined ||
+ globals.timeline.areaY.end === undefined) {
return;
}
if (this.panelInfos.length === 0 || area.tracks.length === 0) return;
@@ -458,7 +454,7 @@
return;
}
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const startX = visibleTimeScale.timeToPx(area.start);
const endX = visibleTimeScale.timeToPx(area.end);
// To align with where to draw on the canvas subtract the first panel Y.
diff --git a/ui/src/frontend/publish.ts b/ui/src/frontend/publish.ts
index d23be62..052cdea 100644
--- a/ui/src/frontend/publish.ts
+++ b/ui/src/frontend/publish.ts
@@ -153,7 +153,6 @@
export function publishMetricError(error: string) {
globals.setMetricError(error);
- globals.logging.logError(error, false);
globals.publishRedraw();
}
diff --git a/ui/src/frontend/scroll_helper.ts b/ui/src/frontend/scroll_helper.ts
index b514b61..4df9b14 100644
--- a/ui/src/frontend/scroll_helper.ts
+++ b/ui/src/frontend/scroll_helper.ts
@@ -27,14 +27,14 @@
// center |ts|, keeping the same zoom level.
export function horizontalScrollToTs(ts: time) {
const time = HighPrecisionTime.fromTime(ts);
- const visibleWindow = globals.frontendLocalState.visibleWindowTime;
+ const visibleWindow = globals.timeline.visibleWindowTime;
if (!visibleWindow.contains(time)) {
// TODO(hjd): This is an ugly jump, we should do a smooth pan instead.
const halfDuration = visibleWindow.duration.divide(2);
const newStart = time.sub(halfDuration);
const newWindow = new HighPrecisionTimeSpan(
newStart, newStart.add(visibleWindow.duration));
- globals.frontendLocalState.updateVisibleTime(newWindow);
+ globals.timeline.updateVisibleTime(newWindow);
}
}
@@ -52,7 +52,7 @@
// - Otherwise, preserve the zoom range.
export function focusHorizontalRange(
start: time, end: time, viewPercentage?: number) {
- const visible = globals.frontendLocalState.visibleWindowTime;
+ const visible = globals.timeline.visibleWindowTime;
const trace = globals.stateTraceTime();
const select = HighPrecisionTimeSpan.fromTime(start, end);
@@ -68,13 +68,13 @@
const paddingPercentage = 1.0 - viewPercentage;
const paddingTime = select.duration.multiply(paddingPercentage);
const halfPaddingTime = paddingTime.divide(2);
- globals.frontendLocalState.updateVisibleTime(select.pad(halfPaddingTime));
+ globals.timeline.updateVisibleTime(select.pad(halfPaddingTime));
return;
}
// If the range is too large to fit on the current zoom level, resize.
if (select.duration.gt(visible.duration.multiply(0.5))) {
const paddedRange = select.pad(select.duration.multiply(2));
- globals.frontendLocalState.updateVisibleTime(paddedRange);
+ globals.timeline.updateVisibleTime(paddedRange);
return;
}
// Calculate the new visible window preserving the zoom level.
@@ -99,9 +99,9 @@
// level.
if (view.start.eq(visible.start) && view.end.eq(visible.end)) {
const padded = select.pad(select.duration.multiply(2));
- globals.frontendLocalState.updateVisibleTime(padded);
+ globals.timeline.updateVisibleTime(padded);
} else {
- globals.frontendLocalState.updateVisibleTime(view);
+ globals.timeline.updateVisibleTime(view);
}
}
diff --git a/ui/src/frontend/slice_layout.ts b/ui/src/frontend/slice_layout.ts
index ca655bd..9a2fa15 100644
--- a/ui/src/frontend/slice_layout.ts
+++ b/ui/src/frontend/slice_layout.ts
@@ -13,15 +13,15 @@
// limitations under the License.
export interface SliceLayoutBase {
- padding: number; // top/bottom pixel padding between slices and track.
- rowSpacing: number; // Spacing between rows.
- minDepth: number; // Minimum depth a slice can be (normally zero)
+ readonly padding: number; // vertical pixel padding between slices and track.
+ readonly rowSpacing: number; // Spacing between rows.
+ readonly minDepth: number; // Minimum depth a slice can be (normally zero)
// Maximum depth a slice can be plus 1 (a half open range with minDepth).
// We have a optimization for when maxDepth - minDepth == 1 so it is useful
// to set this correctly:
- maxDepth: number;
- titleSizePx?: number;
- subtitleSizePx?: number;
+ readonly maxDepth: number;
+ readonly titleSizePx?: number;
+ readonly subtitleSizePx?: number;
}
export const SLICE_LAYOUT_BASE_DEFAULTS: SliceLayoutBase = Object.freeze({
@@ -34,8 +34,8 @@
});
export interface SliceLayoutFixed extends SliceLayoutBase {
- heightMode: 'FIXED';
- fixedHeight: number; // Outer height of the track.
+ readonly heightMode: 'FIXED';
+ readonly fixedHeight: number; // Outer height of the track.
}
export const SLICE_LAYOUT_FIXED_DEFAULTS: SliceLayoutFixed = Object.freeze({
@@ -45,8 +45,8 @@
});
export interface SliceLayoutFitContent extends SliceLayoutBase {
- heightMode: 'FIT_CONTENT';
- sliceHeight: number; // Only when heightMode = 'FIT_CONTENT'.
+ readonly heightMode: 'FIT_CONTENT';
+ readonly sliceHeight: number; // Only when heightMode = 'FIT_CONTENT'.
}
export const SLICE_LAYOUT_FIT_CONTENT_DEFAULTS: SliceLayoutFitContent =
@@ -57,10 +57,10 @@
});
export interface SliceLayoutFlat extends SliceLayoutBase {
- heightMode: 'FIXED';
- fixedHeight: number; // Outer height of the track.
- minDepth: 0;
- maxDepth: 1;
+ readonly heightMode: 'FIXED';
+ readonly fixedHeight: number; // Outer height of the track.
+ readonly minDepth: 0;
+ readonly maxDepth: 1;
}
export const SLICE_LAYOUT_FLAT_DEFAULTS: SliceLayoutFlat = Object.freeze({
diff --git a/ui/src/frontend/slice_track.ts b/ui/src/frontend/slice_track.ts
index 685ff8c..21885d0 100644
--- a/ui/src/frontend/slice_track.ts
+++ b/ui/src/frontend/slice_track.ts
@@ -82,7 +82,7 @@
const data = this.data;
if (data === undefined) return; // Can't possibly draw anything.
- const {visibleTimeSpan, visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeSpan, visibleTimeScale} = globals.timeline;
// If the cached trace slices don't fully cover the visible time range,
// show a gray rectangle with a "Loading..." label.
@@ -262,7 +262,7 @@
if (data === undefined) return;
const {
visibleTimeScale: timeScale,
- } = globals.frontendLocalState;
+ } = globals.timeline;
if (y < TRACK_PADDING) return;
const instantWidthTime = timeScale.pxDeltaToDuration(HALF_CHEVRON_WIDTH_PX);
const t = timeScale.pxToHpTime(x);
@@ -293,7 +293,7 @@
}
getEndTimeIfInComplete(start: time): time {
- const {visibleTimeScale, visibleWindowTime} = globals.frontendLocalState;
+ const {visibleTimeScale, visibleWindowTime} = globals.timeline;
let end = visibleWindowTime.end.toTime('ceil');
if (CROP_INCOMPLETE_SLICE_FLAG.get()) {
@@ -349,7 +349,7 @@
windowSpan,
visibleTimeScale,
visibleTimeSpan,
- } = globals.frontendLocalState;
+ } = globals.timeline;
const pxEnd = windowSpan.end;
const left = Math.max(visibleTimeScale.timeToPx(tStart), 0);
diff --git a/ui/src/frontend/tickmark_panel.ts b/ui/src/frontend/tickmark_panel.ts
index 9390c7f..5a363cc 100644
--- a/ui/src/frontend/tickmark_panel.ts
+++ b/ui/src/frontend/tickmark_panel.ts
@@ -33,7 +33,7 @@
}
renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
ctx.fillStyle = '#999';
ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
@@ -43,7 +43,7 @@
ctx.rect(TRACK_SHELL_WIDTH, 0, size.width - TRACK_SHELL_WIDTH, size.height);
ctx.clip();
- const visibleSpan = globals.frontendLocalState.visibleTimeSpan;
+ const visibleSpan = globals.timeline.visibleTimeSpan;
if (size.width > TRACK_SHELL_WIDTH && visibleSpan.duration > 0n) {
const maxMajorTicks = getMaxMajorTicks(size.width - TRACK_SHELL_WIDTH);
const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width);
diff --git a/ui/src/frontend/time_axis_panel.ts b/ui/src/frontend/time_axis_panel.ts
index f4372af..6238c8d 100644
--- a/ui/src/frontend/time_axis_panel.ts
+++ b/ui/src/frontend/time_axis_panel.ts
@@ -66,7 +66,7 @@
ctx.clip();
// Draw time axis.
- const span = globals.frontendLocalState.visibleTimeSpan;
+ const span = globals.timeline.visibleTimeSpan;
if (size.width > TRACK_SHELL_WIDTH && span.duration > 0n) {
const maxMajorTicks = getMaxMajorTicks(size.width - TRACK_SHELL_WIDTH);
const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width);
diff --git a/ui/src/frontend/time_selection_panel.ts b/ui/src/frontend/time_selection_panel.ts
index 8137c6f..0b61594 100644
--- a/ui/src/frontend/time_selection_panel.ts
+++ b/ui/src/frontend/time_selection_panel.ts
@@ -144,7 +144,7 @@
ctx.rect(TRACK_SHELL_WIDTH, 0, size.width - TRACK_SHELL_WIDTH, size.height);
ctx.clip();
- const span = globals.frontendLocalState.visibleTimeSpan;
+ const span = globals.timeline.visibleTimeSpan;
if (size.width > TRACK_SHELL_WIDTH && span.duration > 0n) {
const maxMajorTicks = getMaxMajorTicks(size.width - TRACK_SHELL_WIDTH);
const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width);
@@ -159,7 +159,7 @@
}
}
- const localArea = globals.frontendLocalState.selectedArea;
+ const localArea = globals.timeline.selectedArea;
const selection = globals.state.currentSelection;
if (localArea !== undefined) {
const start = Time.min(localArea.start, localArea.end);
@@ -190,7 +190,7 @@
}
renderHover(ctx: CanvasRenderingContext2D, size: PanelSize, ts: time) {
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const xPos = TRACK_SHELL_WIDTH + Math.floor(visibleTimeScale.timeToPx(ts));
const domainTime = globals.toDomainTime(ts);
const label = stringifyTimestamp(domainTime);
@@ -200,7 +200,7 @@
renderSpan(
ctx: CanvasRenderingContext2D, size: PanelSize,
span: Span<time, duration>) {
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const xLeft = visibleTimeScale.timeToPx(span.start);
const xRight = visibleTimeScale.timeToPx(span.end);
const label = renderDuration(span.duration);
diff --git a/ui/src/frontend/trace_converter.ts b/ui/src/frontend/trace_converter.ts
index a08f622..fb0bc12 100644
--- a/ui/src/frontend/trace_converter.ts
+++ b/ui/src/frontend/trace_converter.ts
@@ -13,6 +13,7 @@
// limitations under the License.
import {download} from '../base/clipboard';
+import {ErrorDetails} from '../base/logging';
import {time} from '../base/time';
import {Actions} from '../common/actions';
import {
@@ -51,7 +52,7 @@
interface ErrorArgs {
kind: 'error';
- error: string;
+ error: ErrorDetails;
}
diff --git a/ui/src/frontend/track_group_panel.ts b/ui/src/frontend/track_group_panel.ts
index 6b69607..04ae41e 100644
--- a/ui/src/frontend/track_group_panel.ts
+++ b/ui/src/frontend/track_group_panel.ts
@@ -204,7 +204,7 @@
}
highlightIfTrackSelected(ctx: CanvasRenderingContext2D, size: PanelSize) {
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const selection = globals.state.currentSelection;
if (!selection || selection.kind !== 'AREA') return;
const selectedArea = globals.state.areas[selection.areaId];
@@ -244,7 +244,7 @@
this.highlightIfTrackSelected(ctx, size);
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
// Draw vertical line when hovering on the notes panel.
if (globals.state.hoveredNoteTimestamp !== -1n) {
drawVerticalLineAtTime(
diff --git a/ui/src/frontend/track_panel.ts b/ui/src/frontend/track_panel.ts
index afd58c6..b4fcda4 100644
--- a/ui/src/frontend/track_panel.ts
+++ b/ui/src/frontend/track_panel.ts
@@ -416,7 +416,7 @@
}
highlightIfTrackSelected(ctx: CanvasRenderingContext2D, size: PanelSize) {
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const selection = globals.state.currentSelection;
const trackState = this.trackState;
if (!selection || selection.kind !== 'AREA' || trackState === undefined) {
@@ -453,7 +453,7 @@
this.highlightIfTrackSelected(ctx, size);
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
// Draw vertical line when hovering on the notes panel.
if (globals.state.hoveredNoteTimestamp !== -1n) {
drawVerticalLineAtTime(
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index 57aa0a3..071c968 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -51,10 +51,10 @@
if (selection !== null && selection.kind === 'AREA') {
// If frontend selectedArea exists then we are in the process of editing the
// time range and need to use that value instead.
- const area = globals.frontendLocalState.selectedArea ?
- globals.frontendLocalState.selectedArea :
+ const area = globals.timeline.selectedArea ?
+ globals.timeline.selectedArea :
globals.state.areas[selection.areaId];
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const start = visibleTimeScale.timeToPx(area.start);
const end = visibleTimeScale.timeToPx(area.end);
const startDrag = mousePos - TRACK_SHELL_WIDTH;
@@ -94,10 +94,10 @@
private keepCurrentSelection = false;
oncreate(vnode: m.CVnodeDOM) {
- const frontendLocalState = globals.frontendLocalState;
+ const timeline = globals.timeline;
const updateDimensions = () => {
const rect = vnode.dom.getBoundingClientRect();
- frontendLocalState.updateLocalLimits(
+ timeline.updateLocalLimits(
0, rect.width - TRACK_SHELL_WIDTH - getScrollbarWidth());
};
@@ -120,11 +120,11 @@
onPanned: (pannedPx: number) => {
const {
visibleTimeScale,
- } = globals.frontendLocalState;
+ } = globals.timeline;
this.keepCurrentSelection = true;
const tDelta = visibleTimeScale.pxDeltaToDuration(pannedPx);
- frontendLocalState.panVisibleWindow(tDelta);
+ timeline.panVisibleWindow(tDelta);
// If the user has panned they no longer need the hint.
localStorage.setItem(DISMISSED_PANNING_HINT_KEY, 'true');
@@ -136,7 +136,7 @@
const zoomPx = zoomedPositionPx - TRACK_SHELL_WIDTH;
const rect = vnode.dom.getBoundingClientRect();
const centerPoint = zoomPx / (rect.width - TRACK_SHELL_WIDTH);
- frontendLocalState.zoomVisibleWindow(1 - zoomRatio, centerPoint);
+ timeline.zoomVisibleWindow(1 - zoomRatio, centerPoint);
raf.scheduleRedraw();
},
editSelection: (currentPx: number) => {
@@ -150,13 +150,13 @@
currentY: number,
editing: boolean) => {
const traceTime = globals.state.traceTime;
- const {visibleTimeScale} = frontendLocalState;
+ const {visibleTimeScale} = timeline;
this.keepCurrentSelection = true;
if (editing) {
const selection = globals.state.currentSelection;
if (selection !== null && selection.kind === 'AREA') {
- const area = globals.frontendLocalState.selectedArea ?
- globals.frontendLocalState.selectedArea :
+ const area = globals.timeline.selectedArea ?
+ globals.timeline.selectedArea :
globals.state.areas[selection.areaId];
let newTime =
visibleTimeScale.pxToHpTime(currentX - TRACK_SHELL_WIDTH)
@@ -175,7 +175,7 @@
}
// When editing the time range we always use the saved tracks,
// since these will not change.
- frontendLocalState.selectArea(
+ timeline.selectArea(
Time.max(Time.min(keepTime, newTime), traceTime.start),
Time.min(Time.max(keepTime, newTime), traceTime.end),
globals.state.areas[selection.areaId].tracks);
@@ -187,20 +187,20 @@
const {pxSpan} = visibleTimeScale;
startPx = clamp(startPx, pxSpan.start, pxSpan.end);
endPx = clamp(endPx, pxSpan.start, pxSpan.end);
- frontendLocalState.selectArea(
+ timeline.selectArea(
visibleTimeScale.pxToHpTime(startPx).toTime('floor'),
visibleTimeScale.pxToHpTime(endPx).toTime('ceil'),
);
- frontendLocalState.areaY.start = dragStartY;
- frontendLocalState.areaY.end = currentY;
+ timeline.areaY.start = dragStartY;
+ timeline.areaY.end = currentY;
publishShowPanningHint();
}
raf.scheduleRedraw();
},
endSelection: (edit: boolean) => {
- globals.frontendLocalState.areaY.start = undefined;
- globals.frontendLocalState.areaY.end = undefined;
- const area = globals.frontendLocalState.selectedArea;
+ globals.timeline.areaY.start = undefined;
+ globals.timeline.areaY.end = undefined;
+ const area = globals.timeline.selectedArea;
// If we are editing we need to pass the current id through to ensure
// the marked area with that id is also updated.
if (edit) {
@@ -214,8 +214,8 @@
}
// Now the selection has ended we stored the final selected area in the
// global state and can remove the in progress selection from the
- // frontendLocalState.
- globals.frontendLocalState.deselectArea();
+ // timeline.
+ globals.timeline.deselectArea();
// Full redraw to color track shell.
raf.scheduleFullRedraw();
},
diff --git a/ui/src/plugins/dev.perfetto.AndroidPerfTraceCounters/index.ts b/ui/src/plugins/dev.perfetto.AndroidPerfTraceCounters/index.ts
index 46fbb46..3f7d272 100644
--- a/ui/src/plugins/dev.perfetto.AndroidPerfTraceCounters/index.ts
+++ b/ui/src/plugins/dev.perfetto.AndroidPerfTraceCounters/index.ts
@@ -21,7 +21,6 @@
import {addDebugSliceTrack} from '../../tracks/debug/slice_track';
class AndroidPerfTraceCounters implements Plugin {
-
onActivate(_: PluginContext): void {}
async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
@@ -33,7 +32,7 @@
tid = prompt('Enter a thread tid', '');
if (tid === null) return;
}
- const sql_prefix = `
+ const sqlPrefix = `
WITH
sched_switch_ipc AS (
SELECT
@@ -49,7 +48,8 @@
WHERE name = 'sched_switch_with_ctrs' AND tid = ${tid}
),
target_thread_sched_slice AS (
- SELECT s.*, t.tid, t.name FROM sched s LEFT JOIN thread t USING (utid) WHERE t.tid = ${tid}
+ SELECT s.*, t.tid, t.name FROM sched s LEFT JOIN thread t USING (utid) WHERE t.tid = ${
+ tid}
),
target_thread_ipc_slice AS (
SELECT
@@ -76,19 +76,20 @@
ssi.l3_cache_miss
FROM sched_switch_ipc ssi
)
-`
+`;
await addDebugSliceTrack(
- ctx.engine,
- {
- sqlSource: sql_prefix + `
+ ctx.engine,
+ {
+ sqlSource: sqlPrefix + `
SELECT * FROM target_thread_ipc_slice WHERE ts IS NOT NULL`,
- },
- 'Rutime IPC:' + tid,
- {ts: 'ts', dur: 'dur', name: 'ipc'},
- ['instruction', 'cycle', 'stall_backend_mem', 'l3_cache_miss' ],
+ },
+ 'Rutime IPC:' + tid,
+ {ts: 'ts', dur: 'dur', name: 'ipc'},
+ ['instruction', 'cycle', 'stall_backend_mem', 'l3_cache_miss'],
);
- ctx.tabs.openQuery(sql_prefix + `
+ ctx.tabs.openQuery(
+ sqlPrefix + `
SELECT
(sum(instruction) * 1.0 / sum(cycle)*1.0) AS avg_ipc,
sum(dur)/1e6 as total_runtime_ms,
@@ -97,7 +98,7 @@
sum(stall_backend_mem) as total_stall_backend_mem,
sum(l3_cache_miss) as total_l3_cache_miss
FROM target_thread_ipc_slice WHERE ts IS NOT NULL`,
- 'target thread ipc statistic');
+ 'target thread ipc statistic');
},
});
}
diff --git a/ui/src/trace_processor/engine.ts b/ui/src/trace_processor/engine.ts
index f59f33f..c6f9ea2 100644
--- a/ui/src/trace_processor/engine.ts
+++ b/ui/src/trace_processor/engine.ts
@@ -469,12 +469,16 @@
export class EngineProxy implements Disposable {
private engine: Engine;
private tag: string;
- private isAlive: boolean;
+ private _isAlive: boolean;
+
+ get isAlive(): boolean {
+ return this._isAlive;
+ }
constructor(engine: Engine, tag: string) {
this.engine = engine;
this.tag = tag;
- this.isAlive = true;
+ this._isAlive = true;
}
query(query: string, tag?: string): Promise<QueryResult>&QueryResult {
@@ -511,6 +515,6 @@
}
dispose() {
- this.isAlive = false;
+ this._isAlive = false;
}
}
diff --git a/ui/src/traceconv/index.ts b/ui/src/traceconv/index.ts
index 627df91..d9c6aed 100644
--- a/ui/src/traceconv/index.ts
+++ b/ui/src/traceconv/index.ts
@@ -13,7 +13,12 @@
// limitations under the License.
import {defer} from '../base/deferred';
-import {assertExists, reportError, setErrorHandler} from '../base/logging';
+import {
+ addErrorHandler,
+ assertExists,
+ ErrorDetails,
+ reportError,
+} from '../base/logging';
import {time} from '../base/time';
import {
ConversionJobName,
@@ -60,7 +65,7 @@
});
}
-function forwardError(error: string) {
+function forwardError(error: ErrorDetails) {
selfWorker.postMessage({
kind: 'error',
error,
@@ -221,7 +226,7 @@
selfWorker.onmessage = (msg: MessageEvent) => {
self.addEventListener('error', (e) => reportError(e));
self.addEventListener('unhandledrejection', (e) => reportError(e));
- setErrorHandler((err: string) => forwardError(err));
+ addErrorHandler((error: ErrorDetails) => forwardError(error));
const args = msg.data as Args;
if (isConvertTraceAndDownload(args)) {
ConvertTraceAndDownload(args.trace, args.format, args.truncate);
diff --git a/ui/src/tracks/android_log/index.ts b/ui/src/tracks/android_log/index.ts
index 04237b6..b1a31e2 100644
--- a/ui/src/tracks/android_log/index.ts
+++ b/ui/src/tracks/android_log/index.ts
@@ -109,7 +109,7 @@
}
renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const data = this.data();
diff --git a/ui/src/tracks/async_slices/async_slice_track_v2.ts b/ui/src/tracks/async_slices/async_slice_track_v2.ts
index 4e87c9b..cd24132 100644
--- a/ui/src/tracks/async_slices/async_slice_track_v2.ts
+++ b/ui/src/tracks/async_slices/async_slice_track_v2.ts
@@ -13,6 +13,7 @@
// limitations under the License.
import {NamedSliceTrack} from '../../frontend/named_slice_track';
+import {SLICE_LAYOUT_FIT_CONTENT_DEFAULTS} from '../../frontend/slice_layout';
import {NewTrackArgs} from '../../frontend/track';
import {Slice} from '../../public';
@@ -20,7 +21,10 @@
constructor(
args: NewTrackArgs, maxDepth: number, private trackIds: number[]) {
super(args);
- this.sliceLayout.maxDepth = maxDepth + 1;
+ this.sliceLayout = {
+ ...SLICE_LAYOUT_FIT_CONTENT_DEFAULTS,
+ minDepth: maxDepth + 1,
+ };
}
getSqlSource(): string {
diff --git a/ui/src/tracks/chrome_scroll_jank/scroll_jank_cause_link_utils.ts b/ui/src/tracks/chrome_scroll_jank/scroll_jank_cause_link_utils.ts
index 7209356..df919ce 100644
--- a/ui/src/tracks/chrome_scroll_jank/scroll_jank_cause_link_utils.ts
+++ b/ui/src/tracks/chrome_scroll_jank/scroll_jank_cause_link_utils.ts
@@ -201,7 +201,7 @@
verticalScrollToTrack(trackKeys[0], true);
if (exists(ts) && exists(dur)) {
focusHorizontalRange(ts, Time.fromRaw(ts + dur), 0.3);
- globals.frontendLocalState.selectArea(
+ globals.timeline.selectArea(
ts, Time.fromRaw(ts + dur), trackKeys);
globals.dispatch(Actions.selectArea({
diff --git a/ui/src/tracks/chrome_slices/index.ts b/ui/src/tracks/chrome_slices/index.ts
index 8d36341..3d9e638 100644
--- a/ui/src/tracks/chrome_slices/index.ts
+++ b/ui/src/tracks/chrome_slices/index.ts
@@ -20,6 +20,7 @@
NamedSliceTrack,
NamedSliceTrackTypes,
} from '../../frontend/named_slice_track';
+import {SLICE_LAYOUT_FIT_CONTENT_DEFAULTS} from '../../frontend/slice_layout';
import {
SliceData,
SliceTrackLEGACY,
@@ -165,8 +166,12 @@
}
export class ChromeSliceTrackV2 extends NamedSliceTrack<ChromeSliceTrackTypes> {
- constructor(args: NewTrackArgs, private trackId: number) {
+ constructor(args: NewTrackArgs, private trackId: number, maxDepth: number) {
super(args);
+ this.sliceLayout = {
+ ...SLICE_LAYOUT_FIT_CONTENT_DEFAULTS,
+ minDepth: maxDepth + 1,
+ };
}
// This is used by the base class to call iter().
@@ -283,7 +288,7 @@
engine: ctx.engine,
trackKey,
};
- return new ChromeSliceTrackV2(newTrackArgs, trackId);
+ return new ChromeSliceTrackV2(newTrackArgs, trackId, maxDepth);
},
});
}
diff --git a/ui/src/tracks/counter/index.ts b/ui/src/tracks/counter/index.ts
index f9b61a5..5178321 100644
--- a/ui/src/tracks/counter/index.ts
+++ b/ui/src/tracks/counter/index.ts
@@ -353,7 +353,7 @@
// TODO: fonts and colors should come from the CSS and not hardcoded here.
const {
visibleTimeScale: timeScale,
- } = globals.frontendLocalState;
+ } = globals.timeline;
const data = this.data;
// Can't possibly draw anything.
@@ -560,7 +560,7 @@
const data = this.data;
if (data === undefined) return;
this.mousePos = pos;
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const time = visibleTimeScale.pxToHpTime(pos.x);
let values = data.lastValues;
@@ -587,7 +587,7 @@
onMouseClick({x}: {x: number}): boolean {
const data = this.data;
if (data === undefined) return false;
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const time = visibleTimeScale.pxToHpTime(x);
const [left, right] = searchSegment(data.timestamps, time.toTime());
if (left === -1) {
@@ -606,8 +606,10 @@
}
async onDestroy(): Promise<void> {
- await this.engine.query(
- `DROP VIEW IF EXISTS ${this.tableName('counter_view')}`);
+ if (this.engine.isAlive) {
+ await this.engine.query(
+ `DROP VIEW IF EXISTS ${this.tableName('counter_view')}`);
+ }
}
}
diff --git a/ui/src/tracks/cpu_freq/index.ts b/ui/src/tracks/cpu_freq/index.ts
index 06f3087..7d1377b 100644
--- a/ui/src/tracks/cpu_freq/index.ts
+++ b/ui/src/tracks/cpu_freq/index.ts
@@ -294,7 +294,7 @@
const {
visibleTimeScale,
visibleWindowTime,
- } = globals.frontendLocalState;
+ } = globals.timeline;
const data = this.data();
if (data === undefined || data.timestamps.length === 0) {
@@ -466,7 +466,7 @@
const data = this.data();
if (data === undefined) return;
this.mousePos = pos;
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const time = visibleTimeScale.pxToHpTime(pos.x);
const [left, right] = searchSegment(data.timestamps, time.toTime());
diff --git a/ui/src/tracks/cpu_profile/index.ts b/ui/src/tracks/cpu_profile/index.ts
index df0916b..bc4c6bd 100644
--- a/ui/src/tracks/cpu_profile/index.ts
+++ b/ui/src/tracks/cpu_profile/index.ts
@@ -106,7 +106,7 @@
renderCanvas(ctx: CanvasRenderingContext2D, _size: PanelSize): void {
const {
visibleTimeScale: timeScale,
- } = globals.frontendLocalState;
+ } = globals.timeline;
const data = this.data();
if (data === undefined) return;
@@ -181,7 +181,7 @@
if (data === undefined) return;
const {
visibleTimeScale: timeScale,
- } = globals.frontendLocalState;
+ } = globals.timeline;
const time = timeScale.pxToHpTime(x);
const [left, right] = searchSegment(data.tsStarts, time.toTime());
const index = this.findTimestampIndex(left, timeScale, data, x, y, right);
@@ -198,7 +198,7 @@
if (data === undefined) return false;
const {
visibleTimeScale: timeScale,
- } = globals.frontendLocalState;
+ } = globals.timeline;
const time = timeScale.pxToHpTime(x);
const [left, right] = searchSegment(data.tsStarts, time.toTime());
diff --git a/ui/src/tracks/cpu_slices/index.ts b/ui/src/tracks/cpu_slices/index.ts
index f4b2830..90926b7 100644
--- a/ui/src/tracks/cpu_slices/index.ts
+++ b/ui/src/tracks/cpu_slices/index.ts
@@ -198,7 +198,10 @@
}
async onDestroy() {
- await this.query(`drop table if exists ${this.tableName('sched_cached')}`);
+ if (this.engine.isAlive) {
+ await this.engine.query(
+ `drop table if exists ${this.tableName('sched_cached')}`);
+ }
}
}
@@ -220,7 +223,7 @@
renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
// TODO: fonts and colors should come from the CSS and not hardcoded here.
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const data = this.data();
if (data === undefined) return; // Can't possibly draw anything.
@@ -243,7 +246,7 @@
visibleTimeScale,
visibleTimeSpan,
visibleWindowTime,
- } = globals.frontendLocalState;
+ } = globals.timeline;
assertTrue(data.starts.length === data.ends.length);
assertTrue(data.starts.length === data.utids.length);
@@ -422,7 +425,7 @@
const data = this.data();
this.mousePos = pos;
if (data === undefined) return;
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
if (pos.y < MARGIN_TOP || pos.y > MARGIN_TOP + RECT_HEIGHT) {
this.utidHoveredInThisTrack = -1;
globals.dispatch(Actions.setHoveredUtidAndPid({utid: -1, pid: -1}));
@@ -456,7 +459,7 @@
onMouseClick({x}: {x: number}) {
const data = this.data();
if (data === undefined) return false;
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const time = visibleTimeScale.pxToHpTime(x);
const index = search(data.starts, time.toTime());
const id = index === -1 ? undefined : data.ids[index];
diff --git a/ui/src/tracks/custom_sql_table_slices/index.ts b/ui/src/tracks/custom_sql_table_slices/index.ts
index 40c980a..ec7c3ea 100644
--- a/ui/src/tracks/custom_sql_table_slices/index.ts
+++ b/ui/src/tracks/custom_sql_table_slices/index.ts
@@ -92,7 +92,9 @@
});
await this.engine.query(sql);
return DisposableCallback.from(() => {
- this.engine.query(`DROP VIEW ${this.tableName}`);
+ if (this.engine.isAlive) {
+ this.engine.query(`DROP VIEW ${this.tableName}`);
+ }
});
}
diff --git a/ui/src/tracks/frames/actual_frames_track_v2.ts b/ui/src/tracks/frames/actual_frames_track_v2.ts
index c30e673..766041f 100644
--- a/ui/src/tracks/frames/actual_frames_track_v2.ts
+++ b/ui/src/tracks/frames/actual_frames_track_v2.ts
@@ -19,6 +19,7 @@
NamedSliceTrack,
NamedSliceTrackTypes,
} from '../../frontend/named_slice_track';
+import {SLICE_LAYOUT_FIT_CONTENT_DEFAULTS} from '../../frontend/slice_layout';
import {EngineProxy, Slice, STR_NULL} from '../../public';
const BLUE = makeColorScheme(new HSLColor('#03A9F4')); // Blue 500
@@ -47,7 +48,10 @@
engine: EngineProxy, maxDepth: number, trackKey: string,
private trackIds: number[]) {
super({engine, trackKey});
- this.sliceLayout.maxDepth = maxDepth + 1;
+ this.sliceLayout = {
+ ...SLICE_LAYOUT_FIT_CONTENT_DEFAULTS,
+ minDepth: maxDepth + 1,
+ };
}
// This is used by the base class to call iter().
diff --git a/ui/src/tracks/frames/expected_frames_track_v2.ts b/ui/src/tracks/frames/expected_frames_track_v2.ts
index 268b4b6..a3caf5a 100644
--- a/ui/src/tracks/frames/expected_frames_track_v2.ts
+++ b/ui/src/tracks/frames/expected_frames_track_v2.ts
@@ -15,6 +15,7 @@
import {HSLColor} from '../../common/color';
import {makeColorScheme} from '../../common/colorizer';
import {NamedRow, NamedSliceTrack} from '../../frontend/named_slice_track';
+import {SLICE_LAYOUT_FIT_CONTENT_DEFAULTS} from '../../frontend/slice_layout';
import {EngineProxy, Slice} from '../../public';
const GREEN = makeColorScheme(new HSLColor('#4CAF50')); // Green 500
@@ -24,7 +25,10 @@
engine: EngineProxy, maxDepth: number, trackKey: string,
private trackIds: number[]) {
super({engine, trackKey});
- this.sliceLayout.maxDepth = maxDepth + 1;
+ this.sliceLayout = {
+ ...SLICE_LAYOUT_FIT_CONTENT_DEFAULTS,
+ minDepth: maxDepth + 1,
+ };
}
getSqlSource(): string {
diff --git a/ui/src/tracks/ftrace/index.ts b/ui/src/tracks/ftrace/index.ts
index 6ae8474..531bad8 100644
--- a/ui/src/tracks/ftrace/index.ts
+++ b/ui/src/tracks/ftrace/index.ts
@@ -93,7 +93,7 @@
renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
const {
visibleTimeScale,
- } = globals.frontendLocalState;
+ } = globals.timeline;
const data = this.data;
diff --git a/ui/src/tracks/perf_samples_profile/index.ts b/ui/src/tracks/perf_samples_profile/index.ts
index a78e36d..17734f1 100644
--- a/ui/src/tracks/perf_samples_profile/index.ts
+++ b/ui/src/tracks/perf_samples_profile/index.ts
@@ -103,7 +103,7 @@
renderCanvas(ctx: CanvasRenderingContext2D, _size: PanelSize): void {
const {
visibleTimeScale,
- } = globals.frontendLocalState;
+ } = globals.timeline;
const data = this.data();
if (data === undefined) return;
@@ -147,7 +147,7 @@
onMouseMove({x, y}: {x: number, y: number}) {
const data = this.data();
if (data === undefined) return;
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const time = visibleTimeScale.pxToHpTime(x);
const [left, right] = searchSegment(data.tsStarts, time.toTime());
const index =
@@ -163,7 +163,7 @@
onMouseClick({x, y}: {x: number, y: number}) {
const data = this.data();
if (data === undefined) return false;
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const time = visibleTimeScale.pxToHpTime(x);
const [left, right] = searchSegment(data.tsStarts, time.toTime());
diff --git a/ui/src/tracks/process_summary/process_scheduling_track.ts b/ui/src/tracks/process_summary/process_scheduling_track.ts
index 455cac5..b818d31 100644
--- a/ui/src/tracks/process_summary/process_scheduling_track.ts
+++ b/ui/src/tracks/process_summary/process_scheduling_track.ts
@@ -206,7 +206,7 @@
const {
visibleTimeScale,
visibleTimeSpan,
- } = globals.frontendLocalState;
+ } = globals.timeline;
const data = this.data();
if (data === undefined) return; // Can't possibly draw anything.
@@ -288,7 +288,7 @@
const cpuTrackHeight = Math.floor(RECT_HEIGHT / data.maxCpu);
const cpu = Math.floor((pos.y - MARGIN_TOP) / (cpuTrackHeight + 1));
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const t = visibleTimeScale.pxToHpTime(pos.x).toTime('floor');
const [i, j] = searchRange(data.starts, t, searchEq(data.cpus, cpu));
diff --git a/ui/src/tracks/process_summary/process_summary_track.ts b/ui/src/tracks/process_summary/process_summary_track.ts
index 383dcb3..f47e6e9 100644
--- a/ui/src/tracks/process_summary/process_summary_track.ts
+++ b/ui/src/tracks/process_summary/process_summary_track.ts
@@ -131,9 +131,11 @@
}
async onDestroy(): Promise<void> {
- await this.query(`drop table if exists ${
- this.tableName(
- 'window')}; drop table if exists ${this.tableName('span')}`);
+ if (this.engine.isAlive) {
+ await this.engine.query(`drop table if exists ${
+ this.tableName(
+ 'window')}; drop table if exists ${this.tableName('span')}`);
+ }
}
}
@@ -154,7 +156,7 @@
renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
const {
visibleTimeScale,
- } = globals.frontendLocalState;
+ } = globals.timeline;
const data = this.data();
if (data === undefined) return; // Can't possibly draw anything.
@@ -171,7 +173,7 @@
// TODO(dproy): Dedup with CPU slices.
renderSummary(ctx: CanvasRenderingContext2D, data: Data): void {
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const startPx = 0;
const bottomY = TRACK_HEIGHT;
diff --git a/ui/src/tracks/screenshots/index.ts b/ui/src/tracks/screenshots/index.ts
index 4af3c94..d5860b8 100644
--- a/ui/src/tracks/screenshots/index.ts
+++ b/ui/src/tracks/screenshots/index.ts
@@ -17,12 +17,14 @@
NamedSliceTrackTypes,
} from '../../frontend/named_slice_track';
import {
+ NUM,
Plugin,
PluginContext,
PluginContextTrace,
PluginDescriptor,
PrimaryTrackSortKey,
} from '../../public';
+import {Engine} from '../../trace_processor/engine';
import {
CustomSqlDetailsPanelConfig,
CustomSqlTableDefConfig,
@@ -59,16 +61,24 @@
};
// TODO(stevegolton): Use suggestTrack().
-export async function decideTracks(): Promise<DecideTracksResult> {
+export async function decideTracks(engine: Engine):
+ Promise<DecideTracksResult> {
const result: DecideTracksResult = {
tracksToAdd: [],
};
- result.tracksToAdd.push({
- uri: 'perfetto.Screenshots',
- name: 'Screenshots',
- trackSortKey: PrimaryTrackSortKey.ASYNC_SLICE_TRACK,
- });
+ const res =
+ await engine.query('select count() as count from android_screenshots');
+ const {count} = res.firstRow({count: NUM});
+
+ if (count > 0) {
+ result.tracksToAdd.push({
+ uri: 'perfetto.Screenshots',
+ name: 'Screenshots',
+ trackSortKey: PrimaryTrackSortKey.ASYNC_SLICE_TRACK,
+ });
+ }
+
return result;
}
@@ -78,17 +88,25 @@
async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
await ctx.engine.query(`INCLUDE PERFETTO MODULE android.screenshots`);
- ctx.registerStaticTrack({
- uri: 'perfetto.Screenshots',
- displayName: 'Screenshots',
- kind: ScreenshotsTrack.kind,
- track: ({trackKey}) => {
- return new ScreenshotsTrack({
- engine: ctx.engine,
- trackKey,
- });
- },
- });
+ const res = await ctx.engine.query(
+ 'select count() as count from android_screenshots');
+ const {count} = res.firstRow({count: NUM});
+
+ if (count > 0) {
+ const displayName = 'Screenshots';
+ const uri = 'perfetto.Screenshots';
+ ctx.registerStaticTrack({
+ uri,
+ displayName,
+ kind: ScreenshotsTrack.kind,
+ track: ({trackKey}) => {
+ return new ScreenshotsTrack({
+ engine: ctx.engine,
+ trackKey,
+ });
+ },
+ });
+ }
}
}
diff --git a/ui/src/tracks/thread_state/index.ts b/ui/src/tracks/thread_state/index.ts
index 074025e..c72d61a 100644
--- a/ui/src/tracks/thread_state/index.ts
+++ b/ui/src/tracks/thread_state/index.ts
@@ -171,7 +171,10 @@
}
async onDestroy() {
- await this.query(`drop view if exists ${this.tableName('thread_state')}`);
+ if (this.engine.isAlive) {
+ await this.engine.query(
+ `drop view if exists ${this.tableName('thread_state')}`);
+ }
}
}
@@ -192,7 +195,7 @@
const {
visibleTimeScale: timeScale,
visibleTimeSpan,
- } = globals.frontendLocalState;
+ } = globals.timeline;
const data = this.data();
const charWidth = ctx.measureText('dbpqaouk').width / 8;
@@ -276,7 +279,7 @@
onMouseClick({x}: {x: number}) {
const data = this.data();
if (data === undefined) return false;
- const {visibleTimeScale} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.timeline;
const time = visibleTimeScale.pxToHpTime(x);
const index = search(data.starts, time.toTime());
if (index === -1) return false;
diff --git a/ui/src/tracks/visualised_args/index.ts b/ui/src/tracks/visualised_args/index.ts
index 0111078..bd0c746 100644
--- a/ui/src/tracks/visualised_args/index.ts
+++ b/ui/src/tracks/visualised_args/index.ts
@@ -80,7 +80,9 @@
}
async onDestroy(): Promise<void> {
- this.engine.query(`drop view ${this.helperViewName}`);
+ if (this.engine.isAlive) {
+ this.engine.query(`drop view ${this.helperViewName}`);
+ }
}
getFont() {