Merge "gn: enable libc++ assertions in debug mode" into main
diff --git a/Android.bp b/Android.bp
index 328fc3d..cebcd7b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -10974,6 +10974,7 @@
name: "perfetto_src_trace_processor_db_storage_storage",
srcs: [
"src/trace_processor/db/storage/arrangement_storage.cc",
+ "src/trace_processor/db/storage/dense_null_storage.cc",
"src/trace_processor/db/storage/dummy_storage.cc",
"src/trace_processor/db/storage/id_storage.cc",
"src/trace_processor/db/storage/null_storage.cc",
@@ -10982,6 +10983,7 @@
"src/trace_processor/db/storage/set_id_storage.cc",
"src/trace_processor/db/storage/storage.cc",
"src/trace_processor/db/storage/string_storage.cc",
+ "src/trace_processor/db/storage/utils.cc",
],
}
@@ -10990,6 +10992,7 @@
name: "perfetto_src_trace_processor_db_storage_unittests",
srcs: [
"src/trace_processor/db/storage/arrangement_storage_unittest.cc",
+ "src/trace_processor/db/storage/dense_null_storage_unittest.cc",
"src/trace_processor/db/storage/id_storage_unittest.cc",
"src/trace_processor/db/storage/null_storage_unittest.cc",
"src/trace_processor/db/storage/numeric_storage_unittest.cc",
@@ -15481,3 +15484,29 @@
"LICENSE",
],
}
+
+// TODO(b/315118713): use list of proto file sources instead of merged proto
+gensrcs {
+ name: "perfetto_trace_javastream_protos",
+ srcs: [
+ "protos/perfetto/trace/perfetto_trace.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protoc-gen-javastream",
+ "soong_zip",
+ ],
+ cmd: "mkdir -p $(genDir)/$(in) " +
+ "&& $(location aprotoc) " +
+ "--plugin=$(location protoc-gen-javastream) " +
+ "--javastream_out=$(genDir)/$(in) " +
+ "-Iexternal/protobuf/src " +
+ "-Iexternal/perfetto " +
+ "-I . $(in) " +
+ "&& $(location soong_zip) " +
+ "-jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)",
+ data: [
+ ":libprotobuf-internal-protos",
+ ],
+ output_extension: "srcjar",
+}
diff --git a/Android.bp.extras b/Android.bp.extras
index 3292ad9..9c7b0b0 100644
--- a/Android.bp.extras
+++ b/Android.bp.extras
@@ -171,3 +171,29 @@
"LICENSE",
],
}
+
+// TODO(b/315118713): use list of proto file sources instead of merged proto
+gensrcs {
+ name: "perfetto_trace_javastream_protos",
+ srcs: [
+ "protos/perfetto/trace/perfetto_trace.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "protoc-gen-javastream",
+ "soong_zip",
+ ],
+ cmd: "mkdir -p $(genDir)/$(in) " +
+ "&& $(location aprotoc) " +
+ "--plugin=$(location protoc-gen-javastream) " +
+ "--javastream_out=$(genDir)/$(in) " +
+ "-Iexternal/protobuf/src " +
+ "-Iexternal/perfetto " +
+ "-I . $(in) " +
+ "&& $(location soong_zip) " +
+ "-jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)",
+ data: [
+ ":libprotobuf-internal-protos",
+ ],
+ output_extension: "srcjar",
+}
diff --git a/BUILD b/BUILD
index cddab6b..f3d4584 100644
--- a/BUILD
+++ b/BUILD
@@ -1302,6 +1302,8 @@
srcs = [
"src/trace_processor/db/storage/arrangement_storage.cc",
"src/trace_processor/db/storage/arrangement_storage.h",
+ "src/trace_processor/db/storage/dense_null_storage.cc",
+ "src/trace_processor/db/storage/dense_null_storage.h",
"src/trace_processor/db/storage/dummy_storage.cc",
"src/trace_processor/db/storage/dummy_storage.h",
"src/trace_processor/db/storage/id_storage.cc",
@@ -1319,6 +1321,7 @@
"src/trace_processor/db/storage/string_storage.cc",
"src/trace_processor/db/storage/string_storage.h",
"src/trace_processor/db/storage/types.h",
+ "src/trace_processor/db/storage/utils.cc",
"src/trace_processor/db/storage/utils.h",
],
)
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/protos/perfetto/trace_processor/serialization.proto b/protos/perfetto/trace_processor/serialization.proto
index e79b7c9..f559bd9 100644
--- a/protos/perfetto/trace_processor/serialization.proto
+++ b/protos/perfetto/trace_processor/serialization.proto
@@ -92,6 +92,12 @@
optional Storage storage = 2;
}
+ // A schema for serialization of |storage::DenseNullStorage|.
+ message DenseNullStorage {
+ optional BitVector bit_vector = 1;
+ optional Storage storage = 2;
+ }
+
oneof data {
DummyStorage dummy_storage = 1;
IdStorage id_storage = 2;
@@ -101,6 +107,7 @@
NullStorage null_storage = 6;
ArrangementStorage arrangement_storage = 7;
SelectorStorage selector_storage = 8;
+ DenseNullStorage dense_null_storage = 9;
}
}
diff --git a/python/generators/sql_processing/docs_parse.py b/python/generators/sql_processing/docs_parse.py
index 981316d..564679a 100644
--- a/python/generators/sql_processing/docs_parse.py
+++ b/python/generators/sql_processing/docs_parse.py
@@ -20,7 +20,7 @@
from typing import Any, Dict, List, Optional, Set, Tuple, NamedTuple
from python.generators.sql_processing.docs_extractor import DocsExtractor
-from python.generators.sql_processing.utils import ANY_PATTERN, ARG_DEFINITION_PATTERN, ObjKind
+from python.generators.sql_processing.utils import ALLOWED_PREFIXES, ANY_PATTERN, ARG_DEFINITION_PATTERN, ObjKind
from python.generators.sql_processing.utils import ARG_ANNOTATION_PATTERN
from python.generators.sql_processing.utils import NAME_AND_TYPE_PATTERN
from python.generators.sql_processing.utils import FUNCTION_RETURN_PATTERN
@@ -49,6 +49,28 @@
description: str
+# Returns: error message if the name is not correct, None otherwise.
+def get_module_prefix_error(name: str, path: str, module: str) -> Optional[str]:
+ prefix = name.lower().split('_')[0]
+ if module == "common" or module == "prelude":
+ if prefix == module:
+ return (f'Names of tables/views/functions in the "{module}" module '
+ f'should not start with {module}')
+ return None
+ if prefix == module:
+ # Module prefix is always allowed.
+ return None
+ allowed_prefixes = [module]
+ for (path_prefix, allowed_name_prefix) in ALLOWED_PREFIXES.items():
+ if path.startswith(path_prefix):
+ if prefix == allowed_name_prefix:
+ return None
+ allowed_prefixes.append(allowed_name_prefix)
+ return (
+ f'Names of tables/views/functions at path "{path}" should be prefixed '
+ f'with one of following names: {", ".join(allowed_prefixes)}')
+
+
class AbstractDocParser(ABC):
@dataclass
@@ -64,19 +86,10 @@
def _parse_name(self, upper: bool = False):
assert self.name
assert isinstance(self.name, str)
- module_pattern = f"^{self.module}_.*"
- if upper:
- module_pattern = module_pattern.upper()
- starts_with_module_name = re.match(module_pattern, self.name, re.IGNORECASE)
- if self.module == "common" or self.module == "prelude":
- if starts_with_module_name:
- self._error(
- 'Names of tables/views/functions in the "{self.module}" module '
- f'should not start with {module_pattern}')
- return self.name
- if not starts_with_module_name:
- self._error('Names of tables/views/functions should be prefixed with the '
- f'module name (i.e. should start with {module_pattern})')
+ module_prefix_error = get_module_prefix_error(self.name, self.path,
+ self.module)
+ if module_prefix_error is not None:
+ self._error(module_prefix_error)
return self.name.strip()
def _parse_desc_not_empty(self, desc: str):
diff --git a/python/generators/sql_processing/utils.py b/python/generators/sql_processing/utils.py
index 0a05a71..c7133b3 100644
--- a/python/generators/sql_processing/utils.py
+++ b/python/generators/sql_processing/utils.py
@@ -105,6 +105,9 @@
ObjKind.table_function: CREATE_TABLE_FUNCTION_PATTERN,
}
+ALLOWED_PREFIXES = {
+ 'chrome/util': 'cr',
+}
# Given a regex pattern and a string to match against, returns all the
# matching positions. Specifically, it returns a dictionary from the line
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/test/stdlib_unittest.py b/python/test/stdlib_unittest.py
index 3fb6713..f7963fb 100644
--- a/python/test/stdlib_unittest.py
+++ b/python/test/stdlib_unittest.py
@@ -112,6 +112,79 @@
# Expecting an error: function prefix (bar) not matching module name (foo).
self.assertEqual(len(res.errors), 1)
+ # Checks that custom prefixes (cr for chrome/util) are allowed.
+ def test_custom_module_prefix(self):
+ res = parse_file(
+ 'chrome/util/test.sql', f'''
+-- Comment
+CREATE PERFETTO TABLE cr_table(
+ -- Column.
+ x INT
+) AS
+SELECT 1;
+ '''.strip())
+ self.assertListEqual(res.errors, [])
+
+ fn = res.table_views[0]
+ self.assertEqual(fn.name, 'cr_table')
+ self.assertEqual(fn.desc, 'Comment')
+ self.assertEqual(fn.cols, {
+ 'x': Arg('INT', 'Column.'),
+ })
+
+ # Checks that when custom prefixes (cr for chrome/util) are present,
+ # the full module name (chrome) is still accepted.
+ def test_custom_module_prefix_full_module_name(self):
+ res = parse_file(
+ 'chrome/util/test.sql', f'''
+-- Comment
+CREATE PERFETTO TABLE chrome_table(
+ -- Column.
+ x INT
+) AS
+SELECT 1;
+ '''.strip())
+ self.assertListEqual(res.errors, [])
+
+ fn = res.table_views[0]
+ self.assertEqual(fn.name, 'chrome_table')
+ self.assertEqual(fn.desc, 'Comment')
+ self.assertEqual(fn.cols, {
+ 'x': Arg('INT', 'Column.'),
+ })
+
+ # Checks that when custom prefixes (cr for chrome/util) are present,
+ # the incorrect prefixes (foo) are not accepted.
+ def test_custom_module_prefix_incorrect(self):
+ res = parse_file(
+ 'chrome/util/test.sql', f'''
+-- Comment
+CREATE PERFETTO TABLE foo_table(
+ -- Column.
+ x INT
+) AS
+SELECT 1;
+ '''.strip())
+ # Expecting an error: table prefix (foo) is not allowed for a given path
+ # (allowed: chrome, cr).
+ self.assertEqual(len(res.errors), 1)
+
+ # Checks that when custom prefixes (cr for chrome/util) are present,
+ # they do not apply outside of the path scope.
+ def test_custom_module_prefix_does_not_apply_outside(self):
+ res = parse_file(
+ 'foo/bar.sql', f'''
+-- Comment
+CREATE PERFETTO TABLE cr_table(
+ -- Column.
+ x INT
+) AS
+SELECT 1;
+ '''.strip())
+ # Expecting an error: table prefix (foo) is not allowed for a given path
+ # (allowed: foo).
+ self.assertEqual(len(res.errors), 1)
+
def test_common_does_not_include_module_name(self):
res = parse_file(
'common/bar.sql', f'''
diff --git a/src/trace_processor/containers/bit_vector.h b/src/trace_processor/containers/bit_vector.h
index 0e5e72b..243651c 100644
--- a/src/trace_processor/containers/bit_vector.h
+++ b/src/trace_processor/containers/bit_vector.h
@@ -351,8 +351,8 @@
return bv;
}
- // Creates a BitVector of size |end| bit the bits between |start| and |end|
- // filled with corresponding bits |this| BitVector.
+ // Creates a BitVector of size `min(range_end, size())` with bits between
+ // |start| and |end| filled with corresponding bits from |this| BitVector.
BitVector IntersectRange(uint32_t range_start, uint32_t range_end) const;
// Requests the removal of unused capacity.
diff --git a/src/trace_processor/db/query_executor.cc b/src/trace_processor/db/query_executor.cc
index c77cb38..cb9a2cf 100644
--- a/src/trace_processor/db/query_executor.cc
+++ b/src/trace_processor/db/query_executor.cc
@@ -28,12 +28,14 @@
#include "src/trace_processor/containers/string_pool.h"
#include "src/trace_processor/db/query_executor.h"
#include "src/trace_processor/db/storage/arrangement_storage.h"
+#include "src/trace_processor/db/storage/dense_null_storage.h"
#include "src/trace_processor/db/storage/dummy_storage.h"
#include "src/trace_processor/db/storage/id_storage.h"
#include "src/trace_processor/db/storage/null_storage.h"
#include "src/trace_processor/db/storage/numeric_storage.h"
#include "src/trace_processor/db/storage/selector_storage.h"
#include "src/trace_processor/db/storage/set_id_storage.h"
+#include "src/trace_processor/db/storage/storage.h"
#include "src/trace_processor/db/storage/string_storage.h"
#include "src/trace_processor/db/storage/types.h"
#include "src/trace_processor/db/table.h"
@@ -63,6 +65,16 @@
return;
}
+ switch (storage.ValidateSearchConstraints(c.value, c.op)) {
+ case SearchValidationResult::kAllData:
+ return;
+ case SearchValidationResult::kNoData:
+ rm->Clear();
+ return;
+ case SearchValidationResult::kOk:
+ break;
+ }
+
uint32_t rm_size = rm->size();
uint32_t rm_first = rm->Get(0);
uint32_t rm_last = rm->Get(rm_size - 1);
@@ -166,12 +178,11 @@
col.type() == SqlValue::kLong && c.value.type == SqlValue::kDouble;
bool double_with_int =
col.type() == SqlValue::kDouble && c.value.type == SqlValue::kLong;
- use_legacy = use_legacy ||
- (c.op != FilterOp::kIsNull && c.op != FilterOp::kIsNotNull &&
- (int_with_double || double_with_int));
-
- // Dense columns.
- use_legacy = use_legacy || col.IsDense();
+ 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 ||
@@ -255,8 +266,13 @@
// String columns are inherently nullable: null values are signified
// with Id::Null().
PERFETTO_CHECK(col.col_type() != ColumnType::kString);
- storage = std::make_unique<storage::NullStorage>(std::move(storage),
- col.storage_base().bv());
+ if (col.IsDense()) {
+ storage = std::make_unique<storage::DenseNullStorage>(
+ std::move(storage), col.storage_base().bv());
+ } else {
+ storage = std::make_unique<storage::NullStorage>(
+ std::move(storage), col.storage_base().bv());
+ }
}
if (col.overlay().row_map().IsIndexVector()) {
storage = std::make_unique<storage::ArrangementStorage>(
@@ -273,5 +289,37 @@
return rm;
}
+void QueryExecutor::BoundedColumnFilterForTesting(const Constraint& c,
+ const storage::Storage& col,
+ RowMap* rm) {
+ switch (col.ValidateSearchConstraints(c.value, c.op)) {
+ case SearchValidationResult::kAllData:
+ return;
+ case SearchValidationResult::kNoData:
+ rm->Clear();
+ return;
+ case SearchValidationResult::kOk:
+ break;
+ }
+
+ LinearSearch(c, col, rm);
+}
+
+void QueryExecutor::IndexedColumnFilterForTesting(const Constraint& c,
+ const storage::Storage& col,
+ RowMap* rm) {
+ switch (col.ValidateSearchConstraints(c.value, c.op)) {
+ case SearchValidationResult::kAllData:
+ return;
+ case SearchValidationResult::kNoData:
+ rm->Clear();
+ return;
+ case SearchValidationResult::kOk:
+ break;
+ }
+
+ IndexSearch(c, col, rm);
+}
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/db/query_executor.h b/src/trace_processor/db/query_executor.h
index 013dbf2..0b171ca 100644
--- a/src/trace_processor/db/query_executor.h
+++ b/src/trace_processor/db/query_executor.h
@@ -63,18 +63,14 @@
}
// Used only in unittests. Exposes private function.
- static void BoundedColumnFilterForTesting(const Constraint& c,
- const storage::Storage& col,
- RowMap* rm) {
- LinearSearch(c, col, rm);
- }
+ static void BoundedColumnFilterForTesting(const Constraint&,
+ const storage::Storage&,
+ RowMap*);
// Used only in unittests. Exposes private function.
- static void IndexedColumnFilterForTesting(const Constraint& c,
- const storage::Storage& col,
- RowMap* rm) {
- IndexSearch(c, col, rm);
- }
+ static void IndexedColumnFilterForTesting(const Constraint&,
+ const storage::Storage&,
+ RowMap*);
private:
// Updates RowMap with result of filtering single column using the Constraint.
diff --git a/src/trace_processor/db/query_executor_benchmark.cc b/src/trace_processor/db/query_executor_benchmark.cc
index eb23903..38feabd 100644
--- a/src/trace_processor/db/query_executor_benchmark.cc
+++ b/src/trace_processor/db/query_executor_benchmark.cc
@@ -403,6 +403,24 @@
}
BENCHMARK(BM_QEDenseNullFilterIsNull)->ArgsProduct({{DB::V1, DB::V2}});
+static void BM_QEIdColumnWithIntAsDouble(benchmark::State& state) {
+ SliceTableForBenchmark table(state);
+ Constraint c{table.table_.track_id().index_in_table(), FilterOp::kEq,
+ SqlValue::Double(100)};
+ BenchmarkSliceTable(state, table, {c});
+}
+
+BENCHMARK(BM_QEIdColumnWithIntAsDouble)->ArgsProduct({{DB::V1, DB::V2}});
+
+static void BM_QEIdColumnWithDouble(benchmark::State& state) {
+ SliceTableForBenchmark table(state);
+ Constraint c{table.table_.track_id().index_in_table(), FilterOp::kEq,
+ SqlValue::Double(100.5)};
+ BenchmarkSliceTable(state, table, {c});
+}
+
+BENCHMARK(BM_QEIdColumnWithDouble)->ArgsProduct({{DB::V1, DB::V2}});
+
} // namespace
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/db/query_executor_unittest.cc b/src/trace_processor/db/query_executor_unittest.cc
index a2c05d8..7f2dfcc 100644
--- a/src/trace_processor/db/query_executor_unittest.cc
+++ b/src/trace_processor/db/query_executor_unittest.cc
@@ -46,7 +46,7 @@
storage::NumericStorage<int64_t> storage(&storage_data, ColumnType::kInt64);
Constraint c{0, FilterOp::kGe, SqlValue::Long(3)};
- RowMap rm(0, 5);
+ RowMap rm(0, storage.size());
QueryExecutor::BoundedColumnFilterForTesting(c, storage, &rm);
ASSERT_EQ(rm.size(), 3u);
@@ -116,11 +116,12 @@
std::iota(storage_data.begin(), storage_data.end(), 0);
auto numeric = std::make_unique<storage::NumericStorage<int64_t>>(
&storage_data, ColumnType::kInt64);
+
BitVector bv{1, 1, 0, 1, 1, 0, 0, 0, 1, 0};
storage::NullStorage storage(std::move(numeric), &bv);
Constraint c{0, FilterOp::kIsNull, SqlValue()};
- RowMap rm(0, 10);
+ RowMap rm(0, storage.size());
QueryExecutor::BoundedColumnFilterForTesting(c, storage, &rm);
ASSERT_EQ(rm.size(), 5u);
@@ -559,6 +560,29 @@
ASSERT_EQ(res.size(), 0u);
}
+TEST(QueryExecutor, MismatchedTypeIdWithDouble) {
+ IdStorage storage(5);
+
+ // Filter.
+ Constraint c{0, FilterOp::kGe, SqlValue::Double(1.5)};
+ QueryExecutor exec({&storage}, 5);
+ RowMap res = exec.Filter({c});
+
+ ASSERT_EQ(res.size(), 3u);
+}
+
+TEST(QueryExecutor, MismatchedTypeSetIdWithDouble) {
+ std::vector<uint32_t> storage_data{0, 0, 0, 3, 3, 3, 6, 6, 6, 9, 9, 9};
+ SetIdStorage storage(&storage_data);
+
+ // Filter.
+ Constraint c{0, FilterOp::kGe, SqlValue::Double(1.5)};
+ QueryExecutor exec({&storage}, storage.size());
+ RowMap res = exec.Filter({c});
+
+ ASSERT_EQ(res.size(), 9u);
+}
+
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
TEST(QueryExecutor, StringBinarySearchRegex) {
StringPool pool;
diff --git a/src/trace_processor/db/storage/BUILD.gn b/src/trace_processor/db/storage/BUILD.gn
index 55b7eb8..d13b530 100644
--- a/src/trace_processor/db/storage/BUILD.gn
+++ b/src/trace_processor/db/storage/BUILD.gn
@@ -18,6 +18,8 @@
sources = [
"arrangement_storage.cc",
"arrangement_storage.h",
+ "dense_null_storage.cc",
+ "dense_null_storage.h",
"dummy_storage.cc",
"dummy_storage.h",
"id_storage.cc",
@@ -35,6 +37,7 @@
"string_storage.cc",
"string_storage.h",
"types.h",
+ "utils.cc",
"utils.h",
]
deps = [
@@ -67,6 +70,7 @@
testonly = true
sources = [
"arrangement_storage_unittest.cc",
+ "dense_null_storage_unittest.cc",
"id_storage_unittest.cc",
"null_storage_unittest.cc",
"numeric_storage_unittest.cc",
@@ -79,6 +83,7 @@
":storage",
"../../../../gn:default_deps",
"../../../../gn:gtest_and_gmock",
+ "../../../../include/perfetto/trace_processor:basic_types",
"../../containers",
]
}
diff --git a/src/trace_processor/db/storage/arrangement_storage.cc b/src/trace_processor/db/storage/arrangement_storage.cc
index fac7f68..703e4b7 100644
--- a/src/trace_processor/db/storage/arrangement_storage.cc
+++ b/src/trace_processor/db/storage/arrangement_storage.cc
@@ -40,7 +40,7 @@
inner_->size());
}
-Storage::SearchValidationResult ArrangementStorage::ValidateSearchConstraints(
+SearchValidationResult ArrangementStorage::ValidateSearchConstraints(
SqlValue sql_val,
FilterOp op) const {
return inner_->ValidateSearchConstraints(sql_val, op);
diff --git a/src/trace_processor/db/storage/arrangement_storage.h b/src/trace_processor/db/storage/arrangement_storage.h
index 97a944e..2f0ac10 100644
--- a/src/trace_processor/db/storage/arrangement_storage.h
+++ b/src/trace_processor/db/storage/arrangement_storage.h
@@ -32,8 +32,8 @@
explicit ArrangementStorage(std::unique_ptr<Storage> inner,
const std::vector<uint32_t>* arrangement);
- Storage::SearchValidationResult ValidateSearchConstraints(SqlValue, FilterOp)
- const override;
+ SearchValidationResult ValidateSearchConstraints(SqlValue,
+ FilterOp) const override;
RangeOrBitVector Search(FilterOp op,
SqlValue value,
diff --git a/src/trace_processor/db/storage/dense_null_storage.cc b/src/trace_processor/db/storage/dense_null_storage.cc
new file mode 100644
index 0000000..7a59d09
--- /dev/null
+++ b/src/trace_processor/db/storage/dense_null_storage.cc
@@ -0,0 +1,156 @@
+/*
+ * 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.
+ */
+
+#include "src/trace_processor/db/storage/dense_null_storage.h"
+
+#include <cstdint>
+#include <variant>
+
+#include "protos/perfetto/trace_processor/serialization.pbzero.h"
+#include "src/trace_processor/containers/bit_vector.h"
+#include "src/trace_processor/db/storage/types.h"
+#include "src/trace_processor/tp_metatrace.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace storage {
+
+DenseNullStorage::DenseNullStorage(std::unique_ptr<Storage> inner,
+ const BitVector* non_null)
+ : inner_(std::move(inner)), non_null_(non_null) {}
+
+SearchValidationResult DenseNullStorage::ValidateSearchConstraints(
+ SqlValue sql_val,
+ FilterOp op) const {
+ if (op == FilterOp::kIsNull) {
+ return SearchValidationResult::kOk;
+ }
+
+ return inner_->ValidateSearchConstraints(sql_val, op);
+}
+
+RangeOrBitVector DenseNullStorage::Search(FilterOp op,
+ SqlValue sql_val,
+ RowMap::Range in) const {
+ PERFETTO_TP_TRACE(metatrace::Category::DB, "DenseNullStorage::Search");
+
+ if (op == FilterOp::kIsNull) {
+ switch (inner_->ValidateSearchConstraints(sql_val, op)) {
+ case SearchValidationResult::kNoData: {
+ // There is no need to search in underlying storage. It's enough to
+ // intersect the |non_null_|.
+ BitVector res = non_null_->IntersectRange(in.start, in.end);
+ res.Not();
+ res.Resize(in.end, false);
+ return RangeOrBitVector(std::move(res));
+ }
+ case SearchValidationResult::kAllData:
+ return RangeOrBitVector(in);
+ case SearchValidationResult::kOk:
+ break;
+ }
+ }
+
+ RangeOrBitVector inner_res = inner_->Search(op, sql_val, in);
+ BitVector res;
+ if (inner_res.IsRange()) {
+ // If the inner storage returns a range, mask out the appropriate values in
+ // |non_null_| which matches the range. Then, resize to |in.end| as this
+ // is mandated by the API contract of |Storage::Search|.
+ RowMap::Range inner_range = std::move(inner_res).TakeIfRange();
+ PERFETTO_DCHECK(inner_range.end <= in.end);
+ PERFETTO_DCHECK(inner_range.start >= in.start);
+ res = non_null_->IntersectRange(inner_range.start, inner_range.end);
+ res.Resize(in.end, false);
+ } else {
+ res = std::move(inner_res).TakeIfBitVector();
+ }
+
+ if (op == FilterOp::kIsNull) {
+ // For IS NULL, we need to add any rows in |non_null_| which are zeros: we
+ // do this by taking the appropriate number of rows, inverting it and then
+ // bitwise or-ing the result with it.
+ BitVector non_null_copy = non_null_->Copy();
+ non_null_copy.Resize(in.end);
+ non_null_copy.Not();
+ res.Or(non_null_copy);
+ } else {
+ // For anything else, we just need to ensure that any rows which are null
+ // are removed as they would not match.
+ res.And(*non_null_);
+ }
+
+ PERFETTO_DCHECK(res.size() == in.end);
+ return RangeOrBitVector(std::move(res));
+}
+
+RangeOrBitVector DenseNullStorage::IndexSearch(FilterOp op,
+ SqlValue sql_val,
+ uint32_t* indices,
+ uint32_t indices_size,
+ bool sorted) const {
+ PERFETTO_TP_TRACE(metatrace::Category::DB, "DenseNullStorage::IndexSearch");
+
+ RangeOrBitVector inner_res =
+ inner_->IndexSearch(op, sql_val, indices, indices_size, sorted);
+ if (inner_res.IsRange()) {
+ RowMap::Range inner_range = std::move(inner_res).TakeIfRange();
+ BitVector::Builder builder(indices_size, inner_range.start);
+ for (uint32_t i = inner_range.start; i < inner_range.end; ++i) {
+ builder.Append(non_null_->IsSet(indices[i]));
+ }
+ return RangeOrBitVector(std::move(builder).Build());
+ }
+
+ BitVector::Builder builder(indices_size);
+ for (uint32_t i = 0; i < indices_size; ++i) {
+ builder.Append(non_null_->IsSet(indices[i]));
+ }
+ BitVector non_null = std::move(builder).Build();
+
+ BitVector res = std::move(inner_res).TakeIfBitVector();
+
+ if (op == FilterOp::kIsNull) {
+ BitVector null = std::move(non_null);
+ null.Not();
+ res.Or(null);
+ } else {
+ res.And(non_null);
+ }
+
+ PERFETTO_DCHECK(res.size() == indices_size);
+ return RangeOrBitVector(std::move(res));
+}
+
+void DenseNullStorage::StableSort(uint32_t*, uint32_t) const {
+ // TODO(b/307482437): Implement.
+ PERFETTO_FATAL("Not implemented");
+}
+
+void DenseNullStorage::Sort(uint32_t*, uint32_t) const {
+ // TODO(b/307482437): Implement.
+ PERFETTO_FATAL("Not implemented");
+}
+
+void DenseNullStorage::Serialize(StorageProto* storage) const {
+ auto* null_storage = storage->set_dense_null_storage();
+ non_null_->Serialize(null_storage->set_bit_vector());
+ inner_->Serialize(null_storage->set_storage());
+}
+
+} // namespace storage
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/db/storage/dense_null_storage.h b/src/trace_processor/db/storage/dense_null_storage.h
new file mode 100644
index 0000000..ec7b6e9
--- /dev/null
+++ b/src/trace_processor/db/storage/dense_null_storage.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_DB_STORAGE_DENSE_NULL_STORAGE_H_
+#define SRC_TRACE_PROCESSOR_DB_STORAGE_DENSE_NULL_STORAGE_H_
+
+#include <memory>
+#include <variant>
+
+#include "src/trace_processor/containers/bit_vector.h"
+#include "src/trace_processor/db/storage/storage.h"
+#include "src/trace_processor/db/storage/types.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace storage {
+
+// Storage which introduces the layer of nullability but without changing the
+// "spacing" of the underlying storage i.e. this storage simply "masks" out
+// rows in the underlying storage with nulls.
+class DenseNullStorage : public Storage {
+ public:
+ DenseNullStorage(std::unique_ptr<Storage> inner, const BitVector* non_null);
+
+ SearchValidationResult ValidateSearchConstraints(SqlValue,
+ FilterOp) const override;
+
+ RangeOrBitVector Search(FilterOp op,
+ SqlValue value,
+ RowMap::Range range) const override;
+
+ RangeOrBitVector IndexSearch(FilterOp op,
+ SqlValue value,
+ uint32_t* indices,
+ uint32_t indices_count,
+ bool sorted) const override;
+
+ void StableSort(uint32_t* rows, uint32_t rows_size) const override;
+
+ void Sort(uint32_t* rows, uint32_t rows_size) const override;
+
+ void Serialize(StorageProto*) const override;
+
+ uint32_t size() const override { return non_null_->size(); }
+
+ private:
+ std::unique_ptr<Storage> inner_;
+ const BitVector* non_null_ = nullptr;
+};
+
+} // namespace storage
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_DB_STORAGE_DENSE_NULL_STORAGE_H_
diff --git a/src/trace_processor/db/storage/dense_null_storage_unittest.cc b/src/trace_processor/db/storage/dense_null_storage_unittest.cc
new file mode 100644
index 0000000..d8ec93c
--- /dev/null
+++ b/src/trace_processor/db/storage/dense_null_storage_unittest.cc
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+#include "src/trace_processor/db/storage/dense_null_storage.h"
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "src/trace_processor/containers/bit_vector.h"
+#include "src/trace_processor/db/storage/fake_storage.h"
+#include "src/trace_processor/db/storage/numeric_storage.h"
+#include "src/trace_processor/db/storage/types.h"
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace trace_processor {
+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(DenseNullStorage, NoFilteringSearch) {
+ std::vector<uint32_t> data{0, 1, 0, 1, 0};
+ auto numeric =
+ std::make_unique<NumericStorage<uint32_t>>(&data, ColumnType::kUint32);
+
+ BitVector bv{0, 1, 0, 1, 0};
+ DenseNullStorage storage(std::move(numeric), &bv);
+
+ auto res = storage.Search(FilterOp::kGe, SqlValue::Long(0), Range(0, 5));
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1, 3));
+}
+
+TEST(DenseNullStorage, RestrictInputSearch) {
+ std::vector<uint32_t> data{0, 1, 0, 1, 0};
+ auto numeric =
+ std::make_unique<NumericStorage<uint32_t>>(&data, ColumnType::kUint32);
+
+ BitVector bv{0, 1, 0, 1, 0};
+ DenseNullStorage storage(std::move(numeric), &bv);
+
+ auto res = storage.Search(FilterOp::kGe, SqlValue::Long(0), Range(1, 3));
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1));
+}
+
+TEST(DenseNullStorage, RangeFilterSearch) {
+ auto fake = FakeStorage::SearchSubset(5, Range(1, 3));
+
+ BitVector bv{0, 1, 0, 1, 0};
+ DenseNullStorage storage(std::move(fake), &bv);
+
+ auto res = storage.Search(FilterOp::kGe, SqlValue::Long(0), Range(0, 5));
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1));
+}
+
+TEST(DenseNullStorage, BitvectorFilterSearch) {
+ auto fake = FakeStorage::SearchSubset(5, BitVector({0, 1, 1, 0, 0}));
+
+ BitVector bv{0, 1, 0, 1, 0};
+ DenseNullStorage storage(std::move(fake), &bv);
+
+ auto res = storage.Search(FilterOp::kGe, SqlValue::Long(0), Range(0, 5));
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(1));
+}
+
+TEST(DenseNullStorage, IsNullSearch) {
+ auto fake = FakeStorage::SearchSubset(5, BitVector({1, 1, 0, 0, 1}));
+
+ BitVector bv{1, 0, 0, 1, 1};
+ DenseNullStorage storage(std::move(fake), &bv);
+
+ auto res = storage.Search(FilterOp::kIsNull, SqlValue(), Range(0, 5));
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2, 4));
+}
+
+TEST(DenseNullStorage, IndexSearch) {
+ std::vector<uint32_t> data{1, 0, 0, 1, 1, 1};
+ auto numeric =
+ std::make_unique<NumericStorage<uint32_t>>(&data, ColumnType::kUint32);
+
+ BitVector bv{1, 0, 0, 1, 1, 1};
+ DenseNullStorage storage(std::move(numeric), &bv);
+
+ std::vector<uint32_t> index({5, 2, 3, 4, 1});
+ auto res = storage.IndexSearch(FilterOp::kGe, SqlValue::Long(0), index.data(),
+ static_cast<uint32_t>(index.size()), false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 2, 3));
+}
+
+TEST(DenseNullStorage, IsNullIndexSearch) {
+ auto fake = FakeStorage::SearchSubset(6, BitVector({0, 0, 0, 1, 1, 1}));
+
+ BitVector bv{0, 1, 0, 1, 1, 1};
+ DenseNullStorage storage(std::move(fake), &bv);
+
+ std::vector<uint32_t> index({5, 2, 3, 4, 1});
+ auto res = storage.IndexSearch(FilterOp::kIsNull, SqlValue(), index.data(),
+ static_cast<uint32_t>(index.size()), false);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(0, 1, 2, 3));
+}
+
+} // namespace
+} // namespace storage
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/db/storage/dummy_storage.cc b/src/trace_processor/db/storage/dummy_storage.cc
index b4f0be5..ed30e8d 100644
--- a/src/trace_processor/db/storage/dummy_storage.cc
+++ b/src/trace_processor/db/storage/dummy_storage.cc
@@ -21,9 +21,8 @@
namespace trace_processor {
namespace storage {
-DummyStorage::SearchValidationResult DummyStorage::ValidateSearchConstraints(
- SqlValue,
- FilterOp) const {
+SearchValidationResult DummyStorage::ValidateSearchConstraints(SqlValue,
+ FilterOp) const {
PERFETTO_FATAL("Shouldn't be called");
}
diff --git a/src/trace_processor/db/storage/fake_storage.cc b/src/trace_processor/db/storage/fake_storage.cc
index fd9ac2c..9d2316a 100644
--- a/src/trace_processor/db/storage/fake_storage.cc
+++ b/src/trace_processor/db/storage/fake_storage.cc
@@ -27,9 +27,8 @@
FakeStorage::FakeStorage(uint32_t size, SearchStrategy strategy)
: size_(size), strategy_(strategy) {}
-FakeStorage::SearchValidationResult FakeStorage::ValidateSearchConstraints(
- SqlValue,
- FilterOp) const {
+SearchValidationResult FakeStorage::ValidateSearchConstraints(SqlValue,
+ FilterOp) const {
return SearchValidationResult::kOk;
}
diff --git a/src/trace_processor/db/storage/id_storage.cc b/src/trace_processor/db/storage/id_storage.cc
index bec9b041..0b9adee 100644
--- a/src/trace_processor/db/storage/id_storage.cc
+++ b/src/trace_processor/db/storage/id_storage.cc
@@ -15,7 +15,6 @@
*/
#include "src/trace_processor/db/storage/id_storage.h"
-
#include <optional>
#include "perfetto/base/logging.h"
@@ -74,9 +73,8 @@
} // namespace
-IdStorage::SearchValidationResult IdStorage::ValidateSearchConstraints(
- SqlValue val,
- FilterOp op) const {
+SearchValidationResult IdStorage::ValidateSearchConstraints(SqlValue val,
+ FilterOp op) const {
// NULL checks.
if (PERFETTO_UNLIKELY(val.is_null())) {
if (op == FilterOp::kIsNotNull) {
@@ -118,24 +116,25 @@
case SqlValue::kString:
// Any string is always more than any numeric.
if (op == FilterOp::kLt || op == FilterOp::kLe) {
- return Storage::SearchValidationResult::kAllData;
+ return SearchValidationResult::kAllData;
}
- return Storage::SearchValidationResult::kNoData;
+ return SearchValidationResult::kNoData;
case SqlValue::kBytes:
- return Storage::SearchValidationResult::kNoData;
+ return SearchValidationResult::kNoData;
}
- // TODO(b/307482437): Remove after adding support for double
- PERFETTO_CHECK(val.type != SqlValue::kDouble);
-
// Bounds of the value.
- if (PERFETTO_UNLIKELY(val.AsLong() > std::numeric_limits<uint32_t>::max())) {
+ double_t num_val = val.type == SqlValue::kLong
+ ? static_cast<double_t>(val.AsLong())
+ : val.AsDouble();
+
+ if (PERFETTO_UNLIKELY(num_val > std::numeric_limits<uint32_t>::max())) {
if (op == FilterOp::kLe || op == FilterOp::kLt || op == FilterOp::kNe) {
return SearchValidationResult::kAllData;
}
return SearchValidationResult::kNoData;
}
- if (PERFETTO_UNLIKELY(val.AsLong() < std::numeric_limits<uint32_t>::min())) {
+ if (PERFETTO_UNLIKELY(num_val < std::numeric_limits<uint32_t>::min())) {
if (op == FilterOp::kGe || op == FilterOp::kGt || op == FilterOp::kNe) {
return SearchValidationResult::kAllData;
}
@@ -158,17 +157,21 @@
PERFETTO_DCHECK(search_range.end <= size_);
- // After this switch we assume the search is valid.
- switch (ValidateSearchConstraints(sql_val, op)) {
- case SearchValidationResult::kOk:
- break;
- case SearchValidationResult::kAllData:
- return RangeOrBitVector(search_range);
- case SearchValidationResult::kNoData:
- return RangeOrBitVector(Range());
+ // It's a valid filter operation if |sql_val| is a double, although it
+ // requires special logic.
+ if (sql_val.type == SqlValue::kDouble) {
+ switch (utils::CompareIntColumnWithDouble(&sql_val, op)) {
+ case SearchValidationResult::kOk:
+ break;
+ case SearchValidationResult::kAllData:
+ return RangeOrBitVector(Range(0, search_range.end));
+ case SearchValidationResult::kNoData:
+ return RangeOrBitVector(Range());
+ }
}
uint32_t val = static_cast<uint32_t>(sql_val.AsLong());
+
if (op == FilterOp::kNe) {
BitVector ret(search_range.start, false);
ret.Resize(search_range.end, true);
@@ -191,14 +194,17 @@
std::to_string(static_cast<uint32_t>(op)));
});
- // After this switch we assume the search is valid.
- switch (ValidateSearchConstraints(sql_val, op)) {
- case SearchValidationResult::kOk:
- break;
- case SearchValidationResult::kAllData:
- return RangeOrBitVector(Range(0, indices_size));
- case SearchValidationResult::kNoData:
- return RangeOrBitVector(Range());
+ // It's a valid filter operation if |sql_val| is a double, although it
+ // requires special logic.
+ if (sql_val.type == SqlValue::kDouble) {
+ switch (utils::CompareIntColumnWithDouble(&sql_val, op)) {
+ case SearchValidationResult::kOk:
+ break;
+ case SearchValidationResult::kAllData:
+ return RangeOrBitVector(Range(0, indices_size));
+ case SearchValidationResult::kNoData:
+ return RangeOrBitVector(Range());
+ }
}
uint32_t val = static_cast<uint32_t>(sql_val.AsLong());
diff --git a/src/trace_processor/db/storage/id_storage_unittest.cc b/src/trace_processor/db/storage/id_storage_unittest.cc
index 0db3159..ab04d86 100644
--- a/src/trace_processor/db/storage/id_storage_unittest.cc
+++ b/src/trace_processor/db/storage/id_storage_unittest.cc
@@ -16,6 +16,8 @@
#include "src/trace_processor/db/storage/id_storage.h"
#include <limits>
+#include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/db/storage/storage.h"
#include "src/trace_processor/db/storage/types.h"
#include "test/gtest_and_gmock.h"
@@ -26,86 +28,88 @@
return std::tie(a.start, a.end) == std::tie(b.start, b.end);
}
+inline bool operator==(const BitVector& a, const BitVector& b) {
+ return a.size() == b.size() && a.CountSetBits() == b.CountSetBits();
+}
+
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();
+}
+
using Range = RowMap::Range;
TEST(IdStorageUnittest, InvalidSearchConstraints) {
IdStorage storage(100);
- Range test_range(10, 20);
- Range empty_range;
// NULL checks
- SqlValue val;
- val.type = SqlValue::kNull;
- Range search_result =
- storage.Search(FilterOp::kIsNull, val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kIsNotNull, val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, test_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(SqlValue(), FilterOp::kIsNull),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(SqlValue(), FilterOp::kIsNotNull),
+ SearchValidationResult::kAllData);
// FilterOp checks
- search_result =
- storage.Search(FilterOp::kGlob, SqlValue::Long(15), test_range)
- .TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kRegex, SqlValue::Long(15), test_range)
- .TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
+ ASSERT_EQ(
+ storage.ValidateSearchConstraints(SqlValue::Long(15), FilterOp::kGlob),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(
+ storage.ValidateSearchConstraints(SqlValue::Long(15), FilterOp::kRegex),
+ SearchValidationResult::kNoData);
// Type checks
- search_result =
- storage.Search(FilterOp::kGe, SqlValue::String("cheese"), test_range)
- .TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(SqlValue::String("cheese"),
+ FilterOp::kGe),
+ SearchValidationResult::kNoData);
+
+ // With double
+ ASSERT_EQ(
+ storage.ValidateSearchConstraints(SqlValue::Double(-1), FilterOp::kGe),
+ SearchValidationResult::kAllData);
// Value bounds
SqlValue max_val = SqlValue::Long(
static_cast<int64_t>(std::numeric_limits<uint32_t>::max()) + 10);
- search_result =
- storage.Search(FilterOp::kGe, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kGt, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kEq, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kGe),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kGt),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kEq),
+ SearchValidationResult::kNoData);
- search_result =
- storage.Search(FilterOp::kLe, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, test_range);
- search_result =
- storage.Search(FilterOp::kLt, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, test_range);
- search_result =
- storage.Search(FilterOp::kNe, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, test_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kLe),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kLt),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kNe),
+ SearchValidationResult::kAllData);
- SqlValue min_val = SqlValue::Long(
- static_cast<int64_t>(std::numeric_limits<uint32_t>::min()) - 1);
- search_result =
- storage.Search(FilterOp::kGe, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, test_range);
- search_result =
- storage.Search(FilterOp::kGt, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, test_range);
- search_result =
- storage.Search(FilterOp::kNe, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, test_range);
+ SqlValue min_val = SqlValue::Long(-1);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kGe),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kGt),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kNe),
+ SearchValidationResult::kAllData);
- search_result =
- storage.Search(FilterOp::kLe, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kLt, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kEq, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kLe),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kLt),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kEq),
+ SearchValidationResult::kNoData);
}
TEST(IdStorageUnittest, SearchEqSimple) {
@@ -179,13 +183,6 @@
ASSERT_EQ(bv.CountSetBits(), 39u);
}
-TEST(IdStorageUnittest, SearchNeInvalidNum) {
- IdStorage storage(100);
- Range r = storage.Search(FilterOp::kNe, SqlValue::Long(-1), Range(30, 70))
- .TakeIfRange();
- ASSERT_EQ(r.size(), 40u);
-}
-
TEST(IdStorageUnittest, IndexSearchEqSimple) {
IdStorage storage(12);
std::vector<uint32_t> indices{1, 3, 5, 7, 9, 11, 2, 4};
@@ -285,6 +282,61 @@
ASSERT_TRUE(bv.IsSet(5));
}
+TEST(IdStorageUnittest, SearchWithIdAsDoubleSimple) {
+ IdStorage storage(100);
+ SqlValue double_val = SqlValue::Double(15.0);
+ SqlValue long_val = SqlValue::Long(15);
+ Range range(10, 20);
+
+ auto res_double = storage.Search(FilterOp::kEq, double_val, range);
+ auto res_long = storage.Search(FilterOp::kEq, long_val, range);
+ ASSERT_EQ(ToIndexVector(res_double), ToIndexVector(res_long));
+
+ res_double = storage.Search(FilterOp::kNe, double_val, range);
+ res_long = storage.Search(FilterOp::kNe, long_val, range);
+ ASSERT_EQ(ToIndexVector(res_double), ToIndexVector(res_long));
+
+ res_double = storage.Search(FilterOp::kLe, double_val, range);
+ res_long = storage.Search(FilterOp::kLe, long_val, range);
+ ASSERT_EQ(ToIndexVector(res_double), ToIndexVector(res_long));
+
+ res_double = storage.Search(FilterOp::kLt, double_val, range);
+ res_long = storage.Search(FilterOp::kLt, long_val, range);
+ ASSERT_EQ(ToIndexVector(res_double), ToIndexVector(res_long));
+
+ res_double = storage.Search(FilterOp::kGe, double_val, range);
+ res_long = storage.Search(FilterOp::kGe, long_val, range);
+ ASSERT_EQ(ToIndexVector(res_double), ToIndexVector(res_long));
+
+ res_double = storage.Search(FilterOp::kGt, double_val, range);
+ res_long = storage.Search(FilterOp::kGt, long_val, range);
+ ASSERT_EQ(ToIndexVector(res_double), ToIndexVector(res_long));
+}
+
+TEST(IdStorageUnittest, SearchWithIdAsDouble) {
+ IdStorage storage(100);
+ Range range(10, 20);
+ SqlValue val = SqlValue::Double(15.5);
+
+ auto res = storage.Search(FilterOp::kEq, val, range);
+ ASSERT_THAT(ToIndexVector(res), IsEmpty());
+
+ res = storage.Search(FilterOp::kNe, val, range);
+ ASSERT_EQ(ToIndexVector(res).size(), 20u);
+
+ res = storage.Search(FilterOp::kLe, val, range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(10, 11, 12, 13, 14, 15));
+
+ res = storage.Search(FilterOp::kLt, val, range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(10, 11, 12, 13, 14, 15));
+
+ res = storage.Search(FilterOp::kGe, val, range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(16, 17, 18, 19));
+
+ res = storage.Search(FilterOp::kGt, val, range);
+ ASSERT_THAT(ToIndexVector(res), ElementsAre(16, 17, 18, 19));
+}
+
TEST(IdStorageUnittest, Sort) {
std::vector<uint32_t> order{4, 3, 6, 1, 5};
IdStorage storage(10);
diff --git a/src/trace_processor/db/storage/null_storage.cc b/src/trace_processor/db/storage/null_storage.cc
index 6de2759..0ded1af 100644
--- a/src/trace_processor/db/storage/null_storage.cc
+++ b/src/trace_processor/db/storage/null_storage.cc
@@ -17,11 +17,11 @@
#include "src/trace_processor/db/storage/null_storage.h"
#include <cstdint>
-#include <variant>
#include "protos/perfetto/trace_processor/serialization.pbzero.h"
#include "src/trace_processor/containers/bit_vector.h"
#include "src/trace_processor/containers/row_map.h"
+#include "src/trace_processor/db/storage/storage.h"
#include "src/trace_processor/db/storage/types.h"
#include "src/trace_processor/tp_metatrace.h"
@@ -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,14 +68,18 @@
null.Not();
res.Or(null);
}
- return RangeOrBitVector(std::move(res));
+ return res;
}
} // namespace
-Storage::SearchValidationResult NullStorage::ValidateSearchConstraints(
+SearchValidationResult NullStorage::ValidateSearchConstraints(
SqlValue sql_val,
FilterOp op) const {
+ if (op == FilterOp::kIsNull) {
+ return SearchValidationResult::kOk;
+ }
+
return storage_->ValidateSearchConstraints(sql_val, op);
}
@@ -90,13 +94,33 @@
RowMap::Range in) const {
PERFETTO_TP_TRACE(metatrace::Category::DB, "NullStorage::Search");
+ if (op == FilterOp::kIsNull) {
+ switch (storage_->ValidateSearchConstraints(sql_val, op)) {
+ case SearchValidationResult::kNoData: {
+ // There is no need to search in underlying storage. It's enough to
+ // intersect the |non_null_|.
+ BitVector res = non_null_->IntersectRange(in.start, in.end);
+ res.Not();
+ res.Resize(in.end, false);
+ return RangeOrBitVector(std::move(res));
+ }
+ case SearchValidationResult::kAllData:
+ return RangeOrBitVector(in);
+ case SearchValidationResult::kOk:
+ break;
+ }
+ }
+
// Figure out the bounds of the indices in the underlying storage and search
// 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,
@@ -106,6 +130,24 @@
bool sorted) const {
PERFETTO_TP_TRACE(metatrace::Category::DB, "NullStorage::IndexSearch");
+ if (op == FilterOp::kIsNull) {
+ switch (storage_->ValidateSearchConstraints(sql_val, op)) {
+ case SearchValidationResult::kNoData: {
+ BitVector::Builder null_indices(indices_size);
+ for (uint32_t* it = indices; it != indices + indices_size; it++) {
+ null_indices.Append(!non_null_->IsSet(*it));
+ }
+ // There is no need to search in underlying storage. We should just
+ // check if the index is set in |non_null_|.
+ return RangeOrBitVector(std::move(null_indices).Build());
+ }
+ case SearchValidationResult::kAllData:
+ return RangeOrBitVector(Range(0, indices_size));
+ case SearchValidationResult::kOk:
+ break;
+ }
+ }
+
BitVector::Builder storage_non_null(indices_size);
std::vector<uint32_t> storage_iv;
storage_iv.reserve(indices_size);
@@ -119,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 0b792de..b090cb8 100644
--- a/src/trace_processor/db/storage/numeric_storage.cc
+++ b/src/trace_processor/db/storage/numeric_storage.cc
@@ -195,8 +195,9 @@
} // namespace
-NumericStorageBase::SearchValidationResult
-NumericStorageBase::ValidateSearchConstraints(SqlValue val, FilterOp op) const {
+SearchValidationResult NumericStorageBase::ValidateSearchConstraints(
+ SqlValue val,
+ FilterOp op) const {
// NULL checks.
if (PERFETTO_UNLIKELY(val.is_null())) {
if (op == FilterOp::kIsNotNull) {
@@ -237,11 +238,11 @@
case SqlValue::kString:
// Any string is always more than any numeric.
if (op == FilterOp::kLt || op == FilterOp::kLe) {
- return Storage::SearchValidationResult::kAllData;
+ return SearchValidationResult::kAllData;
}
- return Storage::SearchValidationResult::kNoData;
+ return SearchValidationResult::kNoData;
case SqlValue::kBytes:
- return Storage::SearchValidationResult::kNoData;
+ return SearchValidationResult::kNoData;
}
// TODO(b/307482437): There is currently no support for comparison with double
@@ -289,7 +290,7 @@
switch (extreme_validator) {
case kOk:
- return Storage::SearchValidationResult::kOk;
+ return SearchValidationResult::kOk;
case kTooBig:
if (op == FilterOp::kLt || op == FilterOp::kLe || op == FilterOp::kNe) {
return SearchValidationResult::kAllData;
@@ -316,16 +317,6 @@
std::to_string(static_cast<uint32_t>(op)));
});
- // After this switch we assume the search is valid.
- switch (ValidateSearchConstraints(sql_val, op)) {
- case SearchValidationResult::kOk:
- break;
- case SearchValidationResult::kAllData:
- return RangeOrBitVector(Range(0, search_range.end));
- case SearchValidationResult::kNoData:
- return RangeOrBitVector(Range());
- }
-
NumericValue val = GetNumericTypeVariant(type_, sql_val);
if (is_sorted_) {
@@ -356,15 +347,6 @@
std::to_string(static_cast<uint32_t>(op)));
});
- // After this switch we assume the search is valid.
- switch (ValidateSearchConstraints(sql_val, op)) {
- case SearchValidationResult::kOk:
- break;
- case SearchValidationResult::kAllData:
- return RangeOrBitVector(Range(0, indices_size));
- case SearchValidationResult::kNoData:
- return RangeOrBitVector(Range());
- }
NumericValue val = GetNumericTypeVariant(type_, sql_val);
if (sorted) {
return RangeOrBitVector(
diff --git a/src/trace_processor/db/storage/numeric_storage_unittest.cc b/src/trace_processor/db/storage/numeric_storage_unittest.cc
index 36fa51a..ffcc389 100644
--- a/src/trace_processor/db/storage/numeric_storage_unittest.cc
+++ b/src/trace_processor/db/storage/numeric_storage_unittest.cc
@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include "src/trace_processor/db/storage/numeric_storage.h"
+#include <cstdint>
#include "src/trace_processor/db/storage/types.h"
#include "test/gtest_and_gmock.h"
@@ -28,8 +29,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);
@@ -40,30 +54,23 @@
Range empty_range;
// NULL checks
- SqlValue val;
- val.type = SqlValue::kNull;
- Range search_result =
- storage.Search(FilterOp::kIsNull, val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kIsNotNull, val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(SqlValue(), FilterOp::kIsNull),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(SqlValue(), FilterOp::kIsNotNull),
+ SearchValidationResult::kAllData);
// FilterOp checks
- search_result =
- storage.Search(FilterOp::kGlob, SqlValue::Long(15), test_range)
- .TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kRegex, SqlValue::Long(15), test_range)
- .TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
+ ASSERT_EQ(
+ storage.ValidateSearchConstraints(SqlValue::Long(15), FilterOp::kGlob),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(
+ storage.ValidateSearchConstraints(SqlValue::Long(15), FilterOp::kRegex),
+ SearchValidationResult::kNoData);
// Type checks
- search_result =
- storage.Search(FilterOp::kGe, SqlValue::String("cheese"), test_range)
- .TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(SqlValue::String("cheese"),
+ FilterOp::kGe),
+ SearchValidationResult::kNoData);
}
TEST(NumericStorageUnittest, InvalidValueBoundsUint32) {
@@ -71,53 +78,37 @@
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage<uint32_t> storage(&data_vec, ColumnType::kUint32);
- Range test_range(20, 100);
- Range full_range(0, 100);
- Range empty_range;
-
SqlValue max_val = SqlValue::Long(
static_cast<int64_t>(std::numeric_limits<uint32_t>::max()) + 10);
- Range search_result =
- storage.Search(FilterOp::kGe, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kGt, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kEq, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kGe),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kGt),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kEq),
+ SearchValidationResult::kNoData);
- search_result =
- storage.Search(FilterOp::kLe, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
- search_result =
- storage.Search(FilterOp::kLt, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
- search_result =
- storage.Search(FilterOp::kNe, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kLe),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kLt),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kNe),
+ SearchValidationResult::kAllData);
SqlValue min_val = SqlValue::Long(
static_cast<int64_t>(std::numeric_limits<uint32_t>::min()) - 1);
- search_result =
- storage.Search(FilterOp::kGe, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
- search_result =
- storage.Search(FilterOp::kGt, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
- search_result =
- storage.Search(FilterOp::kNe, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kGe),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kGt),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kNe),
+ SearchValidationResult::kAllData);
- search_result =
- storage.Search(FilterOp::kLe, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kLt, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kEq, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kLe),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kLt),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kEq),
+ SearchValidationResult::kNoData);
}
TEST(NumericStorageUnittest, InvalidValueBoundsInt32) {
@@ -125,53 +116,37 @@
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage<int32_t> storage(&data_vec, ColumnType::kInt32);
- Range test_range(20, 100);
- Range full_range(0, 100);
- Range empty_range;
-
SqlValue max_val = SqlValue::Long(
static_cast<int64_t>(std::numeric_limits<int32_t>::max()) + 10);
- Range search_result =
- storage.Search(FilterOp::kGe, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kGt, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kEq, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kGe),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kGt),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kEq),
+ SearchValidationResult::kNoData);
- search_result =
- storage.Search(FilterOp::kLe, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
- search_result =
- storage.Search(FilterOp::kLt, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
- search_result =
- storage.Search(FilterOp::kNe, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kLe),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kLt),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kNe),
+ SearchValidationResult::kAllData);
SqlValue min_val = SqlValue::Long(
static_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1);
- search_result =
- storage.Search(FilterOp::kGe, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
- search_result =
- storage.Search(FilterOp::kGt, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
- search_result =
- storage.Search(FilterOp::kNe, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kGe),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kGt),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kNe),
+ SearchValidationResult::kAllData);
- search_result =
- storage.Search(FilterOp::kLe, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kLt, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kEq, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kLe),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kLt),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kEq),
+ SearchValidationResult::kNoData);
}
TEST(NumericStorageUnittest, StableSortTrivial) {
@@ -198,7 +173,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);
@@ -210,7 +289,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);
@@ -222,7 +301,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);
@@ -232,7 +311,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);
@@ -244,7 +323,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};
@@ -260,7 +339,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};
@@ -276,7 +355,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};
diff --git a/src/trace_processor/db/storage/selector_storage.cc b/src/trace_processor/db/storage/selector_storage.cc
index 934b900..d4865e7 100644
--- a/src/trace_processor/db/storage/selector_storage.cc
+++ b/src/trace_processor/db/storage/selector_storage.cc
@@ -31,7 +31,7 @@
const BitVector* selector)
: inner_(std::move(inner)), selector_(selector) {}
-Storage::SearchValidationResult SelectorStorage::ValidateSearchConstraints(
+SearchValidationResult SelectorStorage::ValidateSearchConstraints(
SqlValue sql_val,
FilterOp op) const {
return inner_->ValidateSearchConstraints(sql_val, op);
diff --git a/src/trace_processor/db/storage/selector_storage.h b/src/trace_processor/db/storage/selector_storage.h
index 9d368e2..518e22b 100644
--- a/src/trace_processor/db/storage/selector_storage.h
+++ b/src/trace_processor/db/storage/selector_storage.h
@@ -31,8 +31,8 @@
public:
SelectorStorage(std::unique_ptr<Storage> storage, const BitVector* non_null);
- Storage::SearchValidationResult ValidateSearchConstraints(SqlValue, FilterOp)
- const override;
+ SearchValidationResult ValidateSearchConstraints(SqlValue,
+ FilterOp) const override;
RangeOrBitVector Search(FilterOp op,
SqlValue value,
diff --git a/src/trace_processor/db/storage/set_id_storage.cc b/src/trace_processor/db/storage/set_id_storage.cc
index 94b94dc..dd0af25 100644
--- a/src/trace_processor/db/storage/set_id_storage.cc
+++ b/src/trace_processor/db/storage/set_id_storage.cc
@@ -58,7 +58,7 @@
} // namespace
-SetIdStorage::SearchValidationResult SetIdStorage::ValidateSearchConstraints(
+SearchValidationResult SetIdStorage::ValidateSearchConstraints(
SqlValue val,
FilterOp op) const {
// NULL checks.
@@ -101,24 +101,25 @@
case SqlValue::kString:
// Any string is always more than any numeric.
if (op == FilterOp::kLt || op == FilterOp::kLe) {
- return Storage::SearchValidationResult::kAllData;
+ return SearchValidationResult::kAllData;
}
- return Storage::SearchValidationResult::kNoData;
+ return SearchValidationResult::kNoData;
case SqlValue::kBytes:
- return Storage::SearchValidationResult::kNoData;
+ return SearchValidationResult::kNoData;
}
- // TODO(b/307482437): Remove after adding support for double
- PERFETTO_CHECK(val.type != SqlValue::kDouble);
-
// Bounds of the value.
- if (PERFETTO_UNLIKELY(val.AsLong() > std::numeric_limits<uint32_t>::max())) {
+ double_t num_val = val.type == SqlValue::kLong
+ ? static_cast<double_t>(val.AsLong())
+ : val.AsDouble();
+
+ if (PERFETTO_UNLIKELY(num_val > std::numeric_limits<uint32_t>::max())) {
if (op == FilterOp::kLe || op == FilterOp::kLt || op == FilterOp::kNe) {
return SearchValidationResult::kAllData;
}
return SearchValidationResult::kNoData;
}
- if (PERFETTO_UNLIKELY(val.AsLong() < std::numeric_limits<uint32_t>::min())) {
+ if (PERFETTO_UNLIKELY(num_val < std::numeric_limits<uint32_t>::min())) {
if (op == FilterOp::kGe || op == FilterOp::kGt || op == FilterOp::kNe) {
return SearchValidationResult::kAllData;
}
@@ -131,6 +132,8 @@
RangeOrBitVector SetIdStorage::Search(FilterOp op,
SqlValue sql_val,
RowMap::Range search_range) const {
+ PERFETTO_DCHECK(search_range.end <= size());
+
PERFETTO_TP_TRACE(metatrace::Category::DB, "SetIdStorage::Search",
[&search_range, op](metatrace::Record* r) {
r->AddArg("Start", std::to_string(search_range.start));
@@ -139,16 +142,17 @@
std::to_string(static_cast<uint32_t>(op)));
});
- PERFETTO_DCHECK(search_range.end <= size());
-
- // After this switch we assume the search is valid.
- switch (ValidateSearchConstraints(sql_val, op)) {
- case SearchValidationResult::kOk:
- break;
- case SearchValidationResult::kAllData:
- return RangeOrBitVector(Range(0, search_range.end));
- case SearchValidationResult::kNoData:
- return RangeOrBitVector(Range());
+ // It's a valid filter operation if |sql_val| is a double, although it
+ // requires special logic.
+ if (sql_val.type == SqlValue::kDouble) {
+ switch (utils::CompareIntColumnWithDouble(&sql_val, op)) {
+ case SearchValidationResult::kOk:
+ break;
+ case SearchValidationResult::kAllData:
+ return RangeOrBitVector(Range(0, search_range.end));
+ case SearchValidationResult::kNoData:
+ return RangeOrBitVector(Range());
+ }
}
uint32_t val = static_cast<uint32_t>(sql_val.AsLong());
@@ -179,14 +183,17 @@
std::to_string(static_cast<uint32_t>(op)));
});
- // After this switch we assume the search is valid.
- switch (ValidateSearchConstraints(sql_val, op)) {
- case SearchValidationResult::kOk:
- break;
- case SearchValidationResult::kAllData:
- return RangeOrBitVector(Range(0, indices_size));
- case SearchValidationResult::kNoData:
- return RangeOrBitVector(Range());
+ // It's a valid filter operation if |sql_val| is a double, although it
+ // requires special logic.
+ if (sql_val.type == SqlValue::kDouble) {
+ switch (utils::CompareIntColumnWithDouble(&sql_val, op)) {
+ case SearchValidationResult::kOk:
+ break;
+ case SearchValidationResult::kAllData:
+ return RangeOrBitVector(Range(0, indices_size));
+ case SearchValidationResult::kNoData:
+ return RangeOrBitVector(Range());
+ }
}
uint32_t val = static_cast<uint32_t>(sql_val.AsLong());
diff --git a/src/trace_processor/db/storage/set_id_storage_unittest.cc b/src/trace_processor/db/storage/set_id_storage_unittest.cc
index 5023345..b7cbfc7 100644
--- a/src/trace_processor/db/storage/set_id_storage_unittest.cc
+++ b/src/trace_processor/db/storage/set_id_storage_unittest.cc
@@ -24,89 +24,80 @@
return std::tie(a.start, a.end) == std::tie(b.start, b.end);
}
+inline bool operator==(const BitVector& a, const BitVector& b) {
+ return a.size() == b.size() && a.CountSetBits() == b.CountSetBits();
+}
+
namespace storage {
namespace {
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(SetIdStorageUnittest, InvalidSearchConstraints) {
std::vector<uint32_t> storage_data{0, 0, 0, 3, 3, 3, 6, 6, 6, 9, 9, 9};
SetIdStorage storage(&storage_data);
-
- Range test_range(3, 9);
- Range full_range(0, 9);
- Range empty_range;
-
// NULL checks
- SqlValue val;
- val.type = SqlValue::kNull;
- Range search_result =
- storage.Search(FilterOp::kIsNull, val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kIsNotNull, val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(SqlValue(), FilterOp::kIsNull),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(SqlValue(), FilterOp::kIsNotNull),
+ SearchValidationResult::kAllData);
// FilterOp checks
- search_result =
- storage.Search(FilterOp::kGlob, SqlValue::Long(15), test_range)
- .TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kRegex, SqlValue::Long(15), test_range)
- .TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
+ ASSERT_EQ(
+ storage.ValidateSearchConstraints(SqlValue::Long(15), FilterOp::kGlob),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(
+ storage.ValidateSearchConstraints(SqlValue::Long(15), FilterOp::kRegex),
+ SearchValidationResult::kNoData);
// Type checks
- search_result =
- storage.Search(FilterOp::kGe, SqlValue::String("cheese"), test_range)
- .TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(SqlValue::String("cheese"),
+ FilterOp::kGe),
+ SearchValidationResult::kNoData);
// Value bounds
SqlValue max_val = SqlValue::Long(
static_cast<int64_t>(std::numeric_limits<uint32_t>::max()) + 10);
- search_result =
- storage.Search(FilterOp::kGe, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kGt, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kEq, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kGe),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kGt),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kEq),
+ SearchValidationResult::kNoData);
- search_result =
- storage.Search(FilterOp::kLe, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
- search_result =
- storage.Search(FilterOp::kLt, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
- search_result =
- storage.Search(FilterOp::kNe, max_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kLe),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kLt),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(max_val, FilterOp::kNe),
+ SearchValidationResult::kAllData);
SqlValue min_val = SqlValue::Long(
static_cast<int64_t>(std::numeric_limits<uint32_t>::min()) - 1);
- search_result =
- storage.Search(FilterOp::kGe, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
- search_result =
- storage.Search(FilterOp::kGt, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
- search_result =
- storage.Search(FilterOp::kNe, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, full_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kGe),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kGt),
+ SearchValidationResult::kAllData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kNe),
+ SearchValidationResult::kAllData);
- search_result =
- storage.Search(FilterOp::kLe, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kLt, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
- search_result =
- storage.Search(FilterOp::kEq, min_val, test_range).TakeIfRange();
- ASSERT_EQ(search_result, empty_range);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kLe),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kLt),
+ SearchValidationResult::kNoData);
+ ASSERT_EQ(storage.ValidateSearchConstraints(min_val, FilterOp::kEq),
+ SearchValidationResult::kNoData);
}
TEST(SetIdStorageUnittest, SearchEqSimple) {
@@ -305,6 +296,52 @@
ASSERT_EQ(bv.CountSetBits(), 2u);
}
+TEST(SetIdStorageUnittest, SearchWithIdAsDoubleSimple) {
+ std::vector<uint32_t> storage_data{0, 0, 0, 3, 3, 3, 6, 6, 6, 9, 9, 9};
+ SetIdStorage storage(&storage_data);
+ SqlValue double_val = SqlValue::Double(7.0);
+ SqlValue long_val = SqlValue::Long(7);
+ Range range(1, 9);
+
+ ASSERT_EQ(ToIndexVector(storage.Search(FilterOp::kEq, double_val, range)),
+ ToIndexVector(storage.Search(FilterOp::kEq, long_val, range)));
+ ASSERT_EQ(ToIndexVector(storage.Search(FilterOp::kNe, double_val, range)),
+ ToIndexVector(storage.Search(FilterOp::kNe, long_val, range)));
+ ASSERT_EQ(ToIndexVector(storage.Search(FilterOp::kLe, double_val, range)),
+ ToIndexVector(storage.Search(FilterOp::kLe, long_val, range)));
+ ASSERT_EQ(ToIndexVector(storage.Search(FilterOp::kLt, double_val, range)),
+ ToIndexVector(storage.Search(FilterOp::kLt, long_val, range)));
+ ASSERT_EQ(ToIndexVector(storage.Search(FilterOp::kGe, double_val, range)),
+ ToIndexVector(storage.Search(FilterOp::kGe, long_val, range)));
+ ASSERT_EQ(ToIndexVector(storage.Search(FilterOp::kGt, double_val, range)),
+ ToIndexVector(storage.Search(FilterOp::kGt, long_val, range)));
+}
+
+TEST(SetIdStorageUnittest, SearchWithIdAsDouble) {
+ std::vector<uint32_t> storage_data{0, 0, 0, 3, 3, 3, 6, 6, 6, 9, 9, 9};
+ SetIdStorage storage(&storage_data);
+ SqlValue val = SqlValue::Double(7.5);
+ Range range(5, 10);
+
+ Range res = storage.Search(FilterOp::kEq, val, range).TakeIfRange();
+ ASSERT_EQ(res, Range());
+
+ res = storage.Search(FilterOp::kNe, val, range).TakeIfRange();
+ ASSERT_EQ(res, Range(0, 10));
+
+ res = storage.Search(FilterOp::kLe, val, range).TakeIfRange();
+ ASSERT_EQ(res, Range(5, 9));
+
+ res = storage.Search(FilterOp::kLt, val, range).TakeIfRange();
+ ASSERT_EQ(res, Range(5, 9));
+
+ res = storage.Search(FilterOp::kGe, val, range).TakeIfRange();
+ ASSERT_EQ(res, Range(9, 10));
+
+ res = storage.Search(FilterOp::kGt, val, range).TakeIfRange();
+ ASSERT_EQ(res, Range(9, 10));
+}
+
} // namespace
} // namespace storage
} // namespace trace_processor
diff --git a/src/trace_processor/db/storage/storage.h b/src/trace_processor/db/storage/storage.h
index 2a9c9fb..eb0c52a 100644
--- a/src/trace_processor/db/storage/storage.h
+++ b/src/trace_processor/db/storage/storage.h
@@ -33,8 +33,6 @@
public:
using StorageProto = protos::pbzero::SerializedColumn_Storage;
- enum class SearchValidationResult { kOk = 0, kAllData = 1, kNoData = 2 };
-
virtual ~Storage();
// Verifies whether any further filtering is needed and if not, whether the
@@ -42,8 +40,6 @@
// the |Search| and |IndexSearch| in special cases.
//
// Notes for callers:
- // * This function is being called by Search and IndexSearch and there is no
- // need to call it before searches.
// * The SqlValue and FilterOp have to be valid in Sqlite: it will crash if
// either: value is NULL and operation is different than "IS NULL" and "IS
// NOT NULL" or the operation is "IS NULL" and "IS NOT NULL" and value is
@@ -58,6 +54,11 @@
// which match the constraint. If a BitVector is returned, it will be
// *precisely* as large as |range.end|.
//
+ // Notes for callers:
+ // * Should only be called if ValidateSearchContraints returned kOk.
+ // * Callers should note that the return value of this function corresponds
+ // to positions in the storage.
+ //
// Notes for implementors:
// * Implementations should ensure that the return value *only* includes
// positions in |range| as callers will expect this to be true and can
@@ -76,6 +77,7 @@
// be *precisely* as large as |indices_count|.
//
// Notes for callers:
+ // * Should only be called if ValidateSearchContraints returned kOk.
// * Callers should note that the return value of this function corresponds
// to positions in |indices| *not* positions in the storage.
//
diff --git a/src/trace_processor/db/storage/string_storage.cc b/src/trace_processor/db/storage/string_storage.cc
index d9c9b98..7d2bc64 100644
--- a/src/trace_processor/db/storage/string_storage.cc
+++ b/src/trace_processor/db/storage/string_storage.cc
@@ -163,7 +163,7 @@
} // namespace
-StringStorage::SearchValidationResult StringStorage::ValidateSearchConstraints(
+SearchValidationResult StringStorage::ValidateSearchConstraints(
SqlValue val,
FilterOp op) const {
// Type checks.
@@ -175,11 +175,11 @@
case SqlValue::kDouble:
// Any string is always more than any numeric.
if (op == FilterOp::kGt || op == FilterOp::kGe) {
- return Storage::SearchValidationResult::kAllData;
+ return SearchValidationResult::kAllData;
}
- return Storage::SearchValidationResult::kNoData;
+ return SearchValidationResult::kNoData;
case SqlValue::kBytes:
- return Storage::SearchValidationResult::kNoData;
+ return SearchValidationResult::kNoData;
}
return SearchValidationResult::kOk;
@@ -196,16 +196,6 @@
std::to_string(static_cast<uint32_t>(op)));
});
- // After this switch we assume the search is valid.
- switch (ValidateSearchConstraints(sql_val, op)) {
- case SearchValidationResult::kOk:
- break;
- case SearchValidationResult::kAllData:
- return RangeOrBitVector(Range(0, search_range.end));
- case SearchValidationResult::kNoData:
- return RangeOrBitVector(Range());
- }
-
if (is_sorted_) {
if (op != FilterOp::kNe) {
return RangeOrBitVector(BinarySearchIntrinsic(op, sql_val, search_range));
@@ -233,16 +223,6 @@
std::to_string(static_cast<uint32_t>(op)));
});
- // After this switch we assume the search is valid.
- switch (ValidateSearchConstraints(sql_val, op)) {
- case SearchValidationResult::kOk:
- break;
- case SearchValidationResult::kAllData:
- return RangeOrBitVector(Range(0, indices_size));
- case SearchValidationResult::kNoData:
- return RangeOrBitVector(Range());
- }
-
if (indices_sorted) {
return RangeOrBitVector(
BinarySearchExtrinsic(op, sql_val, indices, indices_size));
diff --git a/src/trace_processor/db/storage/types.h b/src/trace_processor/db/storage/types.h
index 6884988..83c5d01 100644
--- a/src/trace_processor/db/storage/types.h
+++ b/src/trace_processor/db/storage/types.h
@@ -23,6 +23,13 @@
namespace perfetto {
namespace trace_processor {
+// Result of calling Storage::ValidateSearchResult function.
+enum class SearchValidationResult {
+ kOk = 0, // It makes sense to run search
+ kAllData = 1, // Don't run search, all data passes the constraint.
+ kNoData = 2 // Don't run search, no data passes the constraint.
+};
+
// Used for result of filtering, which is sometimes (for more optimised
// operations) a Range and BitVector otherwise. Stores a variant of Range and
// BitVector.
diff --git a/src/trace_processor/db/storage/utils.cc b/src/trace_processor/db/storage/utils.cc
new file mode 100644
index 0000000..ba12e40
--- /dev/null
+++ b/src/trace_processor/db/storage/utils.cc
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#include "src/trace_processor/db/storage/utils.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace storage {
+namespace utils {
+
+SearchValidationResult CompareIntColumnWithDouble(SqlValue* sql_val,
+ FilterOp op) {
+ double double_val = sql_val->AsDouble();
+ if (std::equal_to<double>()(
+ double_val, static_cast<double>(static_cast<uint32_t>(double_val)))) {
+ // If double is the same as uint32_t, we should just "cast" the |sql_val|
+ // to be treated as long.
+ *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");
+}
+
+} // namespace utils
+
+} // namespace storage
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/db/storage/utils.h b/src/trace_processor/db/storage/utils.h
index 55e18f8..3d38545 100644
--- a/src/trace_processor/db/storage/utils.h
+++ b/src/trace_processor/db/storage/utils.h
@@ -16,7 +16,10 @@
#ifndef SRC_TRACE_PROCESSOR_DB_STORAGE_UTILS_H_
#define SRC_TRACE_PROCESSOR_DB_STORAGE_UTILS_H_
+#include "perfetto/base/logging.h"
+#include "perfetto/trace_processor/basic_types.h"
#include "src/trace_processor/containers/bit_vector.h"
+#include "src/trace_processor/db/storage/types.h"
namespace perfetto {
namespace trace_processor {
@@ -83,6 +86,12 @@
}
}
+// Used for comparing the integer column ({u|}int{32|64}) with a double value.
+// If further search is required it would return kOk and change the SqlValue to
+// a `SqlLong` which would return real results.
+SearchValidationResult CompareIntColumnWithDouble(SqlValue* sql_val,
+ FilterOp op);
+
} // namespace utils
} // namespace storage
diff --git a/src/trace_processor/perfetto_sql/engine/created_function.cc b/src/trace_processor/perfetto_sql/engine/created_function.cc
index 162dbc6..9c32a97 100644
--- a/src/trace_processor/perfetto_sql/engine/created_function.cc
+++ b/src/trace_processor/perfetto_sql/engine/created_function.cc
@@ -587,6 +587,10 @@
SqlValue& out,
Destructors&) {
State* state = static_cast<State*>(ctx);
+
+ // Enter the function and ensure that we have a statement allocated.
+ RETURN_IF_ERROR(state->PushStackEntry());
+
if (argc != state->prototype().arguments.size()) {
return base::ErrStatus(
"%s: invalid number of args; expected %zu, received %zu",
@@ -608,9 +612,6 @@
}
}
- // Enter the function and ensure that we have a statement allocated.
- RETURN_IF_ERROR(state->PushStackEntry());
-
std::optional<Memoizer::MemoizedArgs> memoized_args =
Memoizer::AsMemoizedArgs(argc, argv);
diff --git a/src/websocket_bridge/websocket_bridge.cc b/src/websocket_bridge/websocket_bridge.cc
index eb26506..875e971 100644
--- a/src/websocket_bridge/websocket_bridge.cc
+++ b/src/websocket_bridge/websocket_bridge.cc
@@ -18,10 +18,12 @@
#include <stdint.h>
+#include <cstdlib>
#include <map>
#include <memory>
#include <vector>
+#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/http/http_server.h"
#include "perfetto/ext/base/unix_socket.h"
#include "perfetto/ext/base/unix_task_runner.h"
@@ -71,8 +73,22 @@
#else
const auto kTracedFamily = base::SockFamily::kUnix;
#endif
+ // The ADB_SERVER_SOCKET environment variable is sourced from
+ // the commandline.cpp file in the ADB module of the Android platform.
+ // Examples: tcp:localhost:5037 or tcp:10.52.8.53:5037.
+ std::string adb_socket_endpoint;
+ if (const char* adb_ss = getenv("ADB_SERVER_SOCKET"); adb_ss) {
+ base::StringView adb_ss_sv(adb_ss);
+ adb_socket_endpoint = base::StripPrefix(adb_ss, "tcp:");
+
+ // Ensure that ADB_SERVER_SOCKET actually starts with tcp:
+ PERFETTO_CHECK(adb_socket_endpoint.size() != adb_ss_sv.size());
+ } else {
+ adb_socket_endpoint = "127.0.0.1:5037";
+ }
+ PERFETTO_LOG("[WSBridge] adb server socket is:%s.", adb_socket_endpoint.c_str());
endpoints_.push_back({"/traced", GetConsumerSocket(), kTracedFamily});
- endpoints_.push_back({"/adb", "127.0.0.1:5037", base::SockFamily::kInet});
+ endpoints_.push_back({"/adb", adb_socket_endpoint.c_str(), base::SockFamily::kInet});
base::HttpServer srv(&task_runner_, this);
srv.AddAllowedOrigin("http://localhost:10000");
diff --git a/test/data/ui-screenshots/ui-android_trace_30s_load.png.sha256 b/test/data/ui-screenshots/ui-android_trace_30s_load.png.sha256
index 9ed3863..f99f37b 100644
--- a/test/data/ui-screenshots/ui-android_trace_30s_load.png.sha256
+++ b/test/data/ui-screenshots/ui-android_trace_30s_load.png.sha256
@@ -1 +1 @@
-2d29987562fb3b106e0f1794d2cb341c72a4a51fb5d94bf347048bbe198b7302
\ No newline at end of file
+f358a8b059b98a0445674d5e720230047f85829a6366439559ffc5908508ba11
\ No newline at end of file
diff --git a/test/data/ui-screenshots/ui-chrome_rendering_desktop_select_slice_with_flows.png.sha256 b/test/data/ui-screenshots/ui-chrome_rendering_desktop_select_slice_with_flows.png.sha256
index ea7e6de..518b07a 100644
--- a/test/data/ui-screenshots/ui-chrome_rendering_desktop_select_slice_with_flows.png.sha256
+++ b/test/data/ui-screenshots/ui-chrome_rendering_desktop_select_slice_with_flows.png.sha256
@@ -1 +1 @@
-d9f429e9adad0ce321ab12dbdd062a9a8661c6dc3b6357646bcad5910a215407
\ No newline at end of file
+109a9e36d3659acc0f72275f63a3162718d90d62bfd6251f2d3e3fed2cbac8f0
\ No newline at end of file
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/gen_android_bp b/tools/gen_android_bp
index 6d00144..c1c1ea1 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -536,6 +536,7 @@
self.apex_available = set()
self.min_sdk_version = None
self.proto = dict()
+ self.output_extension: Optional[str] = None
# The genrule_XXX below are properties that must to be propagated back
# on the module(s) that depend on the genrule.
self.genrule_headers = set()
@@ -587,6 +588,7 @@
self._output_field(output, 'stubs')
self._output_field(output, 'proto')
self._output_field(output, 'main')
+ self._output_field(output, 'output_extension')
target_out = []
self._output_field(target_out, 'android')
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/install-build-deps b/tools/install-build-deps
index c3822f6..fd17b81 100755
--- a/tools/install-build-deps
+++ b/tools/install-build-deps
@@ -63,7 +63,7 @@
'buildtools/test_data', # Moved to test/data by r.android.com/1539381 .
'buildtools/d8', # Removed by r.android.com/1424334 .
- # Build toools moved to third_party/ by r.android.com/2327602 .
+ # Build tools moved to third_party/ by r.android.com/2327602 .
'buildtools/mac/clang-format',
'buildtools/mac/gn',
'buildtools/mac/ninja',
@@ -95,6 +95,11 @@
'f706aaa0676e3e22f5fc9ca482295d7caee8535d1869f99efa2358177b64f5cd',
'linux', 'x64'),
Dependency(
+ 'third_party/gn/gn',
+ 'https://storage.googleapis.com/perfetto/gn-linux-arm64-1968-0725d782',
+ 'c2a372cd4f911028d8bc351fbf24835c9b1194fcc92beadf6c5a2b3addae973c',
+ 'linux', 'arm64'),
+ Dependency(
'third_party/gn/gn.exe',
'https://storage.googleapis.com/perfetto/gn-win-1968-0725d782',
'001f777f023c7a6959c778fb3a6b6cfc63f6baef953410ecdeaec350fb12285b',
@@ -150,6 +155,11 @@
'https://storage.googleapis.com/perfetto/ninja-win-182',
'09ced0fcd1a4dec7d1b798a2cf9ce5d20e5d2fbc2337343827f192ce47d0f491',
'windows', 'x64'),
+ Dependency(
+ 'third_party/ninja/ninja',
+ 'https://storage.googleapis.com/perfetto/ninja-linux-arm64-1111',
+ '05031a734ec4310a51b2cfe9f0096b26fce25ab4ff19e5b51abe6371de066cc5',
+ 'linux', 'arm64'),
# Keep the revision in sync with Chrome's PACKAGE_VERSION in
# tools/clang/scripts/update.py.
@@ -463,6 +473,8 @@
arch = machine()
if arch == 'arm64':
return 'arm64'
+ elif arch == 'aarch64':
+ return 'arm64'
else:
# Assume everything else is x64 matching previous behaviour.
return 'x64'
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 9ade987..cce73f1 100644
--- a/ui/release/channels.json
+++ b/ui/release/channels.json
@@ -6,7 +6,7 @@
},
{
"name": "canary",
- "rev": "9ca89e30931314dec4af1131d516e07e39d8657d"
+ "rev": "46dae5655847f65acd49cad6a24ef37c6a85383d"
},
{
"name": "autopush",
diff --git a/ui/src/base/static_initializers.ts b/ui/src/base/static_initializers.ts
index 5abfcd9..f927471 100644
--- a/ui/src/base/static_initializers.ts
+++ b/ui/src/base/static_initializers.ts
@@ -38,7 +38,7 @@
// from the global state (which is frozen) and later try to update the copies.
// By doing so, we accidentally the local copy of global state, which is
// supposed to be immutable.
- setAutoFreeze(false);
+ setAutoFreeze(true);
}
function initializeProtobuf() {
diff --git a/ui/src/common/colorizer.ts b/ui/src/common/colorizer.ts
index 584deb5..14f2140 100644
--- a/ui/src/common/colorizer.ts
+++ b/ui/src/common/colorizer.ts
@@ -19,10 +19,10 @@
import {Color, HSLColor, HSLuvColor} from './color';
-// 128 would provide equal weighting between dark and light text, but we want to
-// slightly prefer light text for stylistic reasons.
-// 140 means we must be brighter on average before switching to dark text.
-const PERCEIVED_BRIGHTNESS_LIMIT = 140;
+// 128 would provide equal weighting between dark and light text.
+// However, we want to prefer light text for stylistic reasons.
+// A higher value means color must be brighter before switching to dark text.
+const PERCEIVED_BRIGHTNESS_LIMIT = 180;
// This file defines some opinionated colors and provides functions to access
// random but predictable colors based on a seed, as well as standardized ways
diff --git a/ui/src/common/track_adapter.ts b/ui/src/common/track_adapter.ts
index acc142d..35fe5db 100644
--- a/ui/src/common/track_adapter.ts
+++ b/ui/src/common/track_adapter.ts
@@ -16,8 +16,8 @@
import {v4 as uuidv4} from 'uuid';
import {assertExists} from '../base/logging';
-import {duration, Span, time} from '../base/time';
-import {PxSpan, TimeScale} from '../frontend/time_scale';
+import {duration, time} from '../base/time';
+import {PanelSize} from '../frontend/panel';
import {NewTrackArgs} from '../frontend/track';
import {SliceRect} from '../public';
import {EngineProxy} from '../trace_processor/engine';
@@ -64,12 +64,8 @@
super.onDestroy();
}
- getSliceRect(
- visibleTimeScale: TimeScale, visibleWindow: Span<time, bigint>,
- windowSpan: PxSpan, tStart: time, tEnd: time, depth: number): SliceRect
- |undefined {
- return this.track.getSliceRect(
- visibleTimeScale, visibleWindow, windowSpan, tStart, tEnd, depth);
+ getSliceRect(tStart: time, tEnd: time, depth: number): SliceRect|undefined {
+ return this.track.getSliceRect(tStart, tEnd, depth);
}
getHeight(): number {
@@ -105,8 +101,8 @@
return await this.controller.onBoundsChange(start, end, resolution);
}
- renderCanvas(ctx: CanvasRenderingContext2D): void {
- this.track.renderCanvas(ctx);
+ renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
+ this.track.renderCanvas(ctx, size);
}
}
@@ -138,12 +134,10 @@
this.trackKey = args.trackKey;
}
- abstract renderCanvas(ctx: CanvasRenderingContext2D): void;
+ abstract renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void;
- getSliceRect(
- _visibleTimeScale: TimeScale, _visibleWindow: Span<time, bigint>,
- _windowSpan: PxSpan, _tStart: time, _tEnd: time,
- _depth: number): SliceRect|undefined {
+ getSliceRect(_tStart: time, _tEnd: time, _depth: number): SliceRect
+ |undefined {
return undefined;
}
diff --git a/ui/src/common/track_helper.ts b/ui/src/common/track_helper.ts
index 114e2c9..8990a44 100644
--- a/ui/src/common/track_helper.ts
+++ b/ui/src/common/track_helper.ts
@@ -14,10 +14,10 @@
import m from 'mithril';
-import {duration, Span, Time, time} from '../base/time';
+import {duration, Time, time} from '../base/time';
import {raf} from '../core/raf_scheduler';
import {globals} from '../frontend/globals';
-import {PxSpan, TimeScale} from '../frontend/time_scale';
+import {PanelSize} from '../frontend/panel';
import {SliceRect, Track, TrackContext} from '../public';
import {TrackData} from './track_data';
@@ -66,10 +66,8 @@
// only for track types that support slices e.g. chrome_slice, async_slices
// tStart - slice start time in seconds, tEnd - slice end time in seconds,
// depth - slice depth
- getSliceRect(
- _visibleTimeScale: TimeScale, _visibleWindow: Span<time, duration>,
- _windowSpan: PxSpan, _tStart: time, _tEnd: time,
- _depth: number): SliceRect|undefined {
+ getSliceRect(_tStart: time, _tEnd: time, _depth: number): SliceRect
+ |undefined {
return undefined;
}
@@ -92,14 +90,14 @@
abstract onBoundsChange(start: time, end: time, resolution: duration):
Promise<Data>;
- abstract renderCanvas(ctx: CanvasRenderingContext2D): void;
+ abstract renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void;
- render(ctx: CanvasRenderingContext2D): void {
+ render(ctx: CanvasRenderingContext2D, size: PanelSize): void {
if (this.shouldLoadNewData()) {
this.loadData();
}
- this.renderCanvas(ctx);
+ this.renderCanvas(ctx, size);
}
private loadData(): void {
diff --git a/ui/src/frontend/base_counter_track.ts b/ui/src/frontend/base_counter_track.ts
index ae7145d..5081cb7 100644
--- a/ui/src/frontend/base_counter_track.ts
+++ b/ui/src/frontend/base_counter_track.ts
@@ -29,6 +29,7 @@
import {checkerboardExcept} from './checkerboard';
import {globals} from './globals';
+import {PanelSize} from './panel';
import {constraintsToQuerySuffix} from './sql_utils';
import {NewTrackArgs, TrackBase} from './track';
import {CacheKey, TrackCache} from './track_cache';
@@ -175,11 +176,10 @@
];
}
- renderCanvas(ctx: CanvasRenderingContext2D) {
+ renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
const {
visibleTimeScale: timeScale,
visibleWindowTime: vizTime,
- windowSpan,
} = globals.frontendLocalState;
{
@@ -237,7 +237,7 @@
}
const effectiveHeight = this.getHeight() - MARGIN_TOP;
- const endPx = windowSpan.end;
+ const endPx = size.width;
const zeroY = MARGIN_TOP + effectiveHeight / (minimumValue < 0 ? 2 : 1);
// Quantize the Y axis to quarters of powers of tens (7.5K, 10K, 12.5K).
@@ -373,8 +373,8 @@
checkerboardExcept(
ctx,
this.getHeight(),
- windowSpan.start,
- windowSpan.end,
+ 0,
+ size.width,
timeScale.timeToPx(this.countersKey.start),
timeScale.timeToPx(this.countersKey.end));
}
diff --git a/ui/src/frontend/base_slice_track.ts b/ui/src/frontend/base_slice_track.ts
index 2dbe0f2..95855cf 100644
--- a/ui/src/frontend/base_slice_track.ts
+++ b/ui/src/frontend/base_slice_track.ts
@@ -17,7 +17,6 @@
import {clamp, floatEqual} from '../base/math_utils';
import {
duration,
- Span,
Time,
time,
} from '../base/time';
@@ -30,18 +29,18 @@
import {colorCompare} from '../common/color';
import {UNEXPECTED_PINK} from '../common/colorizer';
import {Selection, SelectionKind} from '../common/state';
+import {featureFlags} from '../core/feature_flags';
import {raf} from '../core/raf_scheduler';
import {Slice, SliceRect} from '../public';
import {LONG, NUM} from '../trace_processor/query_result';
import {checkerboardExcept} from './checkerboard';
import {globals} from './globals';
+import {PanelSize} from './panel';
import {DEFAULT_SLICE_LAYOUT, SliceLayout} from './slice_layout';
import {constraintsToQuerySuffix} from './sql_utils';
-import {PxSpan, TimeScale} from './time_scale';
import {NewTrackArgs, TrackBase} from './track';
import {BUCKETS_PER_PIXEL, CacheKey, TrackCache} from './track_cache';
-import {featureFlags} from '../core/feature_flags';
// The common class that underpins all tracks drawing slices.
@@ -327,7 +326,7 @@
return `${size}px Roboto Condensed`;
}
- renderCanvas(ctx: CanvasRenderingContext2D): void {
+ renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
// TODO(hjd): fonts and colors should come from the CSS and not hardcoded
// here.
const {
@@ -547,8 +546,8 @@
checkerboardExcept(
ctx,
this.getHeight(),
- timeScale.hpTimeToPx(vizTime.start),
- timeScale.hpTimeToPx(vizTime.end),
+ 0,
+ size.width,
timeScale.timeToPx(this.slicesKey.start),
timeScale.timeToPx(this.slicesKey.end));
@@ -967,17 +966,20 @@
return this.computedTrackHeight;
}
- getSliceRect(
- visibleTimeScale: TimeScale, visibleWindow: Span<time, duration>,
- windowSpan: PxSpan, tStart: time, tEnd: time, depth: number): SliceRect
- |undefined {
+ getSliceRect(tStart: time, tEnd: time, depth: number): SliceRect|undefined {
this.updateSliceAndTrackHeight();
+ const {
+ windowSpan,
+ visibleTimeScale,
+ visibleTimeSpan,
+ } = globals.frontendLocalState;
+
const pxEnd = windowSpan.end;
const left = Math.max(visibleTimeScale.timeToPx(tStart), 0);
const right = Math.min(visibleTimeScale.timeToPx(tEnd), pxEnd);
- const visible = visibleWindow.intersects(tStart, tEnd);
+ const visible = visibleTimeSpan.intersects(tStart, tEnd);
const totalSliceHeight = this.computedRowSpacing + this.computedSliceHeight;
diff --git a/ui/src/frontend/flow_events_renderer.ts b/ui/src/frontend/flow_events_renderer.ts
index fd73ca4..12ce93c 100644
--- a/ui/src/frontend/flow_events_renderer.ts
+++ b/ui/src/frontend/flow_events_renderer.ts
@@ -140,19 +140,12 @@
private getSliceRect(args: FlowEventsRendererArgs, point: FlowPoint):
SliceRect|undefined {
- const {visibleTimeScale, visibleTimeSpan, windowSpan} =
- globals.frontendLocalState;
const trackPanel = args.trackIdToTrackPanel.get(point.trackId) ?.panel;
if (!trackPanel) {
return undefined;
}
return trackPanel.getSliceRect(
- visibleTimeScale,
- visibleTimeSpan,
- windowSpan,
- point.sliceStartTs,
- point.sliceEndTs,
- point.depth);
+ point.sliceStartTs, point.sliceEndTs, point.depth);
}
render(ctx: CanvasRenderingContext2D, args: FlowEventsRendererArgs) {
diff --git a/ui/src/frontend/notes_panel.ts b/ui/src/frontend/notes_panel.ts
index 1904f32..1d7589c 100644
--- a/ui/src/frontend/notes_panel.ts
+++ b/ui/src/frontend/notes_panel.ts
@@ -215,7 +215,7 @@
ctx.strokeStyle = color;
const topOffset = 10;
// Don't draw in the track shell section.
- if (x >= globals.frontendLocalState.windowSpan.start + TRACK_SHELL_WIDTH) {
+ if (x >= TRACK_SHELL_WIDTH) {
// Draw left triangle.
ctx.beginPath();
ctx.moveTo(x, topOffset);
@@ -235,8 +235,7 @@
ctx.stroke();
// Start line after track shell section, join triangles.
- const startDraw = Math.max(
- x, globals.frontendLocalState.windowSpan.start + TRACK_SHELL_WIDTH);
+ const startDraw = Math.max(x, TRACK_SHELL_WIDTH);
ctx.beginPath();
ctx.moveTo(startDraw, topOffset);
ctx.lineTo(xEnd, topOffset);
diff --git a/ui/src/frontend/slice_track.ts b/ui/src/frontend/slice_track.ts
index dd8756d..685ff8c 100644
--- a/ui/src/frontend/slice_track.ts
+++ b/ui/src/frontend/slice_track.ts
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {duration, Span, Time, time} from '../base/time';
+import {Time, time} from '../base/time';
import {Actions} from '../common/actions';
import {cropText, drawIncompleteSlice} from '../common/canvas_utils';
import {getColorForSlice} from '../common/colorizer';
@@ -24,7 +24,7 @@
import {CROP_INCOMPLETE_SLICE_FLAG} from './base_slice_track';
import {checkerboardExcept} from './checkerboard';
import {globals} from './globals';
-import {PxSpan, TimeScale} from './time_scale';
+import {PanelSize} from './panel';
export const SLICE_TRACK_KIND = 'ChromeSliceTrack';
const SLICE_HEIGHT = 18;
@@ -77,21 +77,20 @@
return '12px Roboto Condensed';
}
- renderCanvas(ctx: CanvasRenderingContext2D): void {
+ renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
// TODO: fonts and colors should come from the CSS and not hardcoded here.
const data = this.data;
if (data === undefined) return; // Can't possibly draw anything.
- const {visibleTimeSpan, visibleWindowTime, visibleTimeScale, windowSpan} =
- globals.frontendLocalState;
+ const {visibleTimeSpan, visibleTimeScale} = globals.frontendLocalState;
// If the cached trace slices don't fully cover the visible time range,
// show a gray rectangle with a "Loading..." label.
checkerboardExcept(
ctx,
this.getHeight(),
- visibleTimeScale.hpTimeToPx(visibleWindowTime.start),
- visibleTimeScale.hpTimeToPx(visibleWindowTime.end),
+ 0,
+ size.width,
visibleTimeScale.timeToPx(data.start),
visibleTimeScale.timeToPx(data.end),
);
@@ -126,11 +125,16 @@
continue;
}
- const rect = this.getSliceRect(
- visibleTimeScale, visibleTimeSpan, windowSpan, tStart, tEnd, depth);
- if (!rect || !rect.visible) {
- continue;
- }
+ const pxEnd = size.width;
+ const left = Math.max(visibleTimeScale.timeToPx(tStart), 0);
+ const right = Math.min(visibleTimeScale.timeToPx(tEnd), pxEnd);
+
+ const rect = {
+ left,
+ width: Math.max(right - left, 1),
+ top: TRACK_PADDING + depth * SLICE_HEIGHT,
+ height: SLICE_HEIGHT,
+ };
const currentSelection = globals.state.currentSelection;
const isSelected = currentSelection &&
@@ -340,15 +344,18 @@
return SLICE_HEIGHT * (this.maxDepth + 1) + 2 * TRACK_PADDING;
}
- getSliceRect(
- visibleTimeScale: TimeScale, visibleWindow: Span<time, duration>,
- windowSpan: PxSpan, tStart: time, tEnd: time, depth: number): SliceRect
- |undefined {
+ getSliceRect(tStart: time, tEnd: time, depth: number): SliceRect|undefined {
+ const {
+ windowSpan,
+ visibleTimeScale,
+ visibleTimeSpan,
+ } = globals.frontendLocalState;
+
const pxEnd = windowSpan.end;
const left = Math.max(visibleTimeScale.timeToPx(tStart), 0);
const right = Math.min(visibleTimeScale.timeToPx(tEnd), pxEnd);
- const visible = visibleWindow.intersects(tStart, tEnd);
+ const visible = visibleTimeSpan.intersects(tStart, tEnd);
return {
left,
diff --git a/ui/src/frontend/track.ts b/ui/src/frontend/track.ts
index 88565f2..3cc79f1 100644
--- a/ui/src/frontend/track.ts
+++ b/ui/src/frontend/track.ts
@@ -14,12 +14,11 @@
import m from 'mithril';
-import {duration, Span, time} from '../base/time';
+import {time} from '../base/time';
import {SliceRect, Track, TrackContext} from '../public';
import {EngineProxy} from '../trace_processor/engine';
-import {PxSpan, TimeScale} from './time_scale';
-
+import {PanelSize} from './panel';
// Args passed to the track constructors when creating a new track.
export interface NewTrackArgs {
trackKey: string;
@@ -42,7 +41,8 @@
// this object is removed.
onDestroy() {}
- protected abstract renderCanvas(ctx: CanvasRenderingContext2D): void;
+ protected abstract renderCanvas(
+ ctx: CanvasRenderingContext2D, size: PanelSize): void;
getHeight(): number {
return 40;
@@ -64,18 +64,16 @@
onFullRedraw(): void {}
- render(ctx: CanvasRenderingContext2D) {
- this.renderCanvas(ctx);
+ render(ctx: CanvasRenderingContext2D, size: PanelSize) {
+ this.renderCanvas(ctx, size);
}
// Returns a place where a given slice should be drawn. Should be implemented
// only for track types that support slices e.g. chrome_slice, async_slices
// tStart - slice start time in seconds, tEnd - slice end time in seconds,
// depth - slice depth
- getSliceRect(
- _visibleTimeScale: TimeScale, _visibleWindow: Span<time, duration>,
- _windowSpan: PxSpan, _tStart: time, _tEnd: time,
- _depth: number): SliceRect|undefined {
+ getSliceRect(_tStart: time, _tEnd: time, _depth: number): SliceRect
+ |undefined {
return undefined;
}
}
diff --git a/ui/src/frontend/track_group_panel.ts b/ui/src/frontend/track_group_panel.ts
index a524dfb..6b69607 100644
--- a/ui/src/frontend/track_group_panel.ts
+++ b/ui/src/frontend/track_group_panel.ts
@@ -24,7 +24,7 @@
TrackGroupState,
TrackState,
} from '../common/state';
-import {Migrate, Track, TrackContext} from '../public';
+import {Migrate, Track, TrackContext, TrackTags} from '../public';
import {globals} from './globals';
import {drawGridLines} from './gridline_helper';
@@ -44,6 +44,7 @@
private shellWidth = 0;
private backgroundColor = '#ffffff'; // Updated from CSS later.
private summaryTrack?: Track;
+ private summaryTrackTags?: TrackTags;
constructor({attrs}: m.CVnode<Attrs>) {
super();
@@ -70,6 +71,7 @@
};
this.summaryTrack = pluginManager.createTrack(uri, ctx);
+ this.summaryTrackTags = pluginManager.resolveTrackInfo(uri)?.tags;
}
get trackGroupState(): TrackGroupState {
@@ -148,7 +150,7 @@
'h1.track-title',
{title: name},
name,
- renderChips(this.summaryTrackState),
+ renderChips(this.summaryTrackTags),
),
(this.trackGroupState.collapsed && child !== null) ?
m('h2.track-subtitle', child) :
@@ -235,7 +237,8 @@
ctx.save();
ctx.translate(this.shellWidth, 0);
if (this.summaryTrack) {
- this.summaryTrack.render(ctx);
+ const trackSize = {...size, width: size.width - this.shellWidth};
+ this.summaryTrack.render(ctx, trackSize);
}
ctx.restore();
diff --git a/ui/src/frontend/track_panel.ts b/ui/src/frontend/track_panel.ts
index 56318d1..afd58c6 100644
--- a/ui/src/frontend/track_panel.ts
+++ b/ui/src/frontend/track_panel.ts
@@ -17,19 +17,19 @@
import {currentTargetOffset} from '../base/dom_utils';
import {Icons} from '../base/semantic_icons';
-import {duration, Span, time} from '../base/time';
+import {time} from '../base/time';
import {Actions} from '../common/actions';
import {pluginManager} from '../common/plugins';
import {TrackState} from '../common/state';
import {raf} from '../core/raf_scheduler';
-import {Migrate, SliceRect, Track, TrackContext} from '../public';
+import {Migrate, SliceRect, Track, TrackContext, TrackTags} from '../public';
+import {checkerboard} from './checkerboard';
import {SELECTION_FILL_COLOR, TRACK_SHELL_WIDTH} from './css_constants';
import {globals} from './globals';
import {drawGridLines} from './gridline_helper';
import {Panel, PanelSize} from './panel';
import {verticalScrollToTrack} from './scroll_helper';
-import {PxSpan, TimeScale} from './time_scale';
import {
drawVerticalLineAtTime,
} from './vertical_line_helper';
@@ -75,29 +75,24 @@
}
}
-export function renderChips({uri}: TrackState) {
- const tagElements: m.Children = [];
- const trackInfo = pluginManager.resolveTrackInfo(uri);
- const tags = trackInfo?.tags;
- tags?.metric && tagElements.push(m(TrackChip, {text: 'metric'}));
- tags?.debuggable && tagElements.push(m(TrackChip, {text: 'debuggable'}));
- return tagElements;
+export function renderChips(tags?: TrackTags) {
+ return [
+ tags?.metric && m(TrackChip, {text: 'metric'}),
+ tags?.debuggable && m(TrackChip, {text: 'debuggable'}),
+ ];
}
interface TrackShellAttrs {
- track: Track;
- trackState: TrackState;
+ trackKey: string;
+ title: string;
+ buttons: m.Children;
+ tags?: TrackTags;
}
class TrackShell implements m.ClassComponent<TrackShellAttrs> {
// Set to true when we click down and drag the
private dragging = false;
private dropping: 'before'|'after'|undefined = undefined;
- private attrs?: TrackShellAttrs;
-
- oninit(vnode: m.Vnode<TrackShellAttrs>) {
- this.attrs = vnode.attrs;
- }
view({attrs}: m.CVnode<TrackShellAttrs>) {
// The shell should be highlighted if the current search result is inside
@@ -106,7 +101,7 @@
const searchIndex = globals.state.searchIndex;
if (searchIndex !== -1) {
const trackKey = globals.currentSearchResults.trackKeys[searchIndex];
- if (trackKey === attrs.trackState.key) {
+ if (trackKey === attrs.trackKey) {
highlightClass = 'flash';
}
}
@@ -117,34 +112,34 @@
`.track-shell[draggable=true]`,
{
class: `${highlightClass} ${dragClass} ${dropClass}`,
- ondragstart: this.ondragstart.bind(this),
+ ondragstart: (e: DragEvent) => this.ondragstart(e, attrs.trackKey),
ondragend: this.ondragend.bind(this),
ondragover: this.ondragover.bind(this),
ondragleave: this.ondragleave.bind(this),
- ondrop: this.ondrop.bind(this),
+ ondrop: (e: DragEvent) => this.ondrop(e, attrs.trackKey),
},
m(
'h1',
{
- title: attrs.trackState.name,
+ title: attrs.title,
style: {
- 'font-size': getTitleSize(attrs.trackState.name),
+ 'font-size': getTitleSize(attrs.title),
},
},
- attrs.trackState.name,
- renderChips(attrs.trackState),
+ attrs.title,
+ renderChips(attrs.tags),
),
m('.track-buttons',
- attrs.track.getTrackShellButtons(),
+ attrs.buttons,
m(TrackButton, {
action: () => {
globals.dispatch(
- Actions.toggleTrackPinned({trackKey: attrs.trackState.key}));
+ Actions.toggleTrackPinned({trackKey: attrs.trackKey}));
},
i: Icons.Pin,
- filledIcon: isPinned(attrs.trackState.key),
- tooltip: isPinned(attrs.trackState.key) ? 'Unpin' : 'Pin to top',
- showButton: isPinned(attrs.trackState.key),
+ filledIcon: isPinned(attrs.trackKey),
+ tooltip: isPinned(attrs.trackKey) ? 'Unpin' : 'Pin to top',
+ showButton: isPinned(attrs.trackKey),
fullHeight: true,
}),
globals.state.currentSelection !== null &&
@@ -152,25 +147,24 @@
m(TrackButton, {
action: (e: MouseEvent) => {
globals.dispatch(Actions.toggleTrackSelection(
- {id: attrs.trackState.key, isTrackGroup: false}));
+ {id: attrs.trackKey, isTrackGroup: false}));
e.stopPropagation();
},
- i: isSelected(attrs.trackState.key) ? Icons.Checkbox :
- Icons.BlankCheckbox,
- tooltip: isSelected(attrs.trackState.key) ?
- 'Remove track' :
- 'Add track to selection',
+ i: isSelected(attrs.trackKey) ? Icons.Checkbox :
+ Icons.BlankCheckbox,
+ tooltip: isSelected(attrs.trackKey) ? 'Remove track' :
+ 'Add track to selection',
showButton: true,
}) :
''));
}
- ondragstart(e: DragEvent) {
+ ondragstart(e: DragEvent, trackKey: string) {
const dataTransfer = e.dataTransfer;
if (dataTransfer === null) return;
this.dragging = true;
raf.scheduleFullRedraw();
- dataTransfer.setData('perfetto/track', `${this.attrs!.trackState.key}`);
+ dataTransfer.setData('perfetto/track', `${trackKey}`);
dataTransfer.setDragImage(new Image(), 0, 0);
}
@@ -203,13 +197,13 @@
raf.scheduleFullRedraw();
}
- ondrop(e: DragEvent) {
+ ondrop(e: DragEvent, trackKey: string) {
if (this.dropping === undefined) return;
const dataTransfer = e.dataTransfer;
if (dataTransfer === null) return;
raf.scheduleFullRedraw();
const srcId = dataTransfer.getData('perfetto/track');
- const dstId = this.attrs!.trackState.key;
+ const dstId = trackKey;
globals.dispatch(Actions.moveTrack({srcId, op: this.dropping, dstId}));
this.dropping = undefined;
}
@@ -274,9 +268,14 @@
}
interface TrackComponentAttrs {
- trackState: TrackState;
- track: Track;
+ trackKey: string;
+ heightPx?: number;
+ title: string;
+ buttons?: m.Children;
+ tags?: TrackTags;
+ track?: Track;
}
+
class TrackComponent implements m.ClassComponent<TrackComponentAttrs> {
view({attrs}: m.CVnode<TrackComponentAttrs>) {
// TODO(hjd): The min height below must match the track_shell_title
@@ -286,19 +285,24 @@
'.track',
{
style: {
- height: `${Math.max(18, attrs.track.getHeight())}px`,
+ height: `${Math.max(18, attrs.heightPx ?? 0)}px`,
},
- id: 'track_' + attrs.trackState.key,
+ id: 'track_' + attrs.trackKey,
},
[
- m(TrackShell, {track: attrs.track, trackState: attrs.trackState}),
- m(TrackContent, {track: attrs.track}),
+ m(TrackShell, {
+ buttons: attrs.buttons,
+ title: attrs.title,
+ trackKey: attrs.trackKey,
+ tags: attrs.tags,
+ }),
+ attrs.track && m(TrackContent, {track: attrs.track}),
]);
}
oncreate({attrs}: m.CVnode<TrackComponentAttrs>) {
- if (globals.scrollToTrackKey === attrs.trackState.key) {
- verticalScrollToTrack(attrs.trackState.key);
+ if (globals.scrollToTrackKey === attrs.trackKey) {
+ verticalScrollToTrack(attrs.trackKey);
globals.scrollToTrackKey = undefined;
}
}
@@ -341,6 +345,7 @@
// has disappeared.
private track: Track|undefined;
private trackState: TrackState|undefined;
+ private tags: TrackTags|undefined;
private tryLoadTrack(vnode: m.CVnode<TrackPanelAttrs>) {
const trackKey = vnode.attrs.trackKey;
@@ -364,6 +369,7 @@
};
this.track = pluginManager.createTrack(uri, trackCtx);
+ this.tags = pluginManager.resolveTrackInfo(uri)?.tags;
this.track?.onCreate(trackCtx);
this.trackState = trackState;
@@ -375,9 +381,19 @@
}
if (this.track === undefined || this.trackState === undefined) {
- return m('div', 'No such track');
+ return m(TrackComponent, {
+ trackKey: vnode.attrs.trackKey,
+ title: this.trackState?.name ?? 'Loading...',
+ });
}
- return m(TrackComponent, {trackState: this.trackState, track: this.track});
+ return m(TrackComponent, {
+ tags: this.tags,
+ heightPx: this.track.getHeight(),
+ title: this.trackState.name,
+ trackKey: this.trackState.key,
+ buttons: this.track.getTrackShellButtons(),
+ track: this.track,
+ });
}
oncreate() {
@@ -428,7 +444,10 @@
ctx.translate(TRACK_SHELL_WIDTH, 0);
if (this.track !== undefined) {
- this.track.render(ctx);
+ const trackSize = {...size, width: size.width - TRACK_SHELL_WIDTH};
+ this.track.render(ctx, trackSize);
+ } else {
+ checkerboard(ctx, size.height, 0, size.width - TRACK_SHELL_WIDTH);
}
ctx.restore();
@@ -491,14 +510,10 @@
}
}
- getSliceRect(
- visibleTimeScale: TimeScale, visibleWindow: Span<time, duration>,
- windowSpan: PxSpan, tStart: time, tDur: time, depth: number): SliceRect
- |undefined {
+ getSliceRect(tStart: time, tDur: time, depth: number): SliceRect|undefined {
if (this.track === undefined) {
return undefined;
}
- return this.track.getSliceRect(
- visibleTimeScale, visibleWindow, windowSpan, tStart, tDur, depth);
+ return this.track.getSliceRect(tStart, tDur, depth);
}
}
diff --git a/ui/src/plugins/dev.perfetto.AndroidPerf/index.ts b/ui/src/plugins/dev.perfetto.AndroidPerf/index.ts
index 7658fb6..a521724 100644
--- a/ui/src/plugins/dev.perfetto.AndroidPerf/index.ts
+++ b/ui/src/plugins/dev.perfetto.AndroidPerf/index.ts
@@ -58,6 +58,59 @@
SELECT * FROM android_binder_graph(-1000, 1000, -1000, 1000)`,
'all process binder graph'),
});
+
+ ctx.registerCommand({
+ id: 'dev.perfetto.AndroidPerf#ThreadClusterDistribution',
+ name: 'Run query: runtime cluster distribution for a thread',
+ callback: async (tid) => {
+ if (tid === undefined) {
+ tid = prompt('Enter a thread tid', '');
+ if (tid === null) return;
+ }
+ ctx.tabs.openQuery(`
+ INCLUDE PERFETTO MODULE common.cpus;
+ WITH
+ total_runtime AS (
+ SELECT sum(dur) AS total_runtime
+ FROM sched s
+ LEFT JOIN thread t
+ USING (utid)
+ WHERE t.tid = ${tid}
+ )
+ SELECT
+ c.size AS cluster,
+ sum(dur)/1e6 AS total_dur_ms,
+ sum(dur) * 1.0 / (SELECT * FROM total_runtime) AS percentage
+ FROM sched s
+ LEFT JOIN thread t
+ USING (utid)
+ LEFT JOIN cpus c
+ ON s.cpu = c.cpu_index
+ WHERE t.tid = ${tid}
+ GROUP BY 1`, `runtime cluster distrubtion for tid ${tid}`);
+ },
+ });
+
+ ctx.registerCommand({
+ id: 'dev.perfetto.AndroidPerf#SchedLatency',
+ name: 'Run query: top 50 sched latency for a thread',
+ callback: async (tid) => {
+ if (tid === undefined) {
+ tid = prompt('Enter a thread tid', '');
+ if (tid === null) return;
+ }
+ ctx.tabs.openQuery(`
+ SELECT ts.*, t.tid, t.name, tt.id AS track_id
+ FROM thread_state ts
+ LEFT JOIN thread_track tt
+ USING (utid)
+ LEFT JOIN thread t
+ USING (utid)
+ WHERE ts.state IN ('R', 'R+') AND tid = ${tid}
+ ORDER BY dur DESC
+ LIMIT 50`, `top 50 sched latency slice for tid ${tid}`);
+ },
+ });
}
}
diff --git a/ui/src/plugins/dev.perfetto.AndroidPerfTraceCounters/OWNERS b/ui/src/plugins/dev.perfetto.AndroidPerfTraceCounters/OWNERS
new file mode 100644
index 0000000..e5632b1
--- /dev/null
+++ b/ui/src/plugins/dev.perfetto.AndroidPerfTraceCounters/OWNERS
@@ -0,0 +1 @@
+lukechang@google.com
diff --git a/ui/src/plugins/dev.perfetto.AndroidPerfTraceCounters/index.ts b/ui/src/plugins/dev.perfetto.AndroidPerfTraceCounters/index.ts
new file mode 100644
index 0000000..46fbb46
--- /dev/null
+++ b/ui/src/plugins/dev.perfetto.AndroidPerfTraceCounters/index.ts
@@ -0,0 +1,109 @@
+// 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 {
+ Plugin,
+ PluginContext,
+ PluginContextTrace,
+ PluginDescriptor,
+} from '../../public';
+import {addDebugSliceTrack} from '../../tracks/debug/slice_track';
+
+class AndroidPerfTraceCounters implements Plugin {
+
+ onActivate(_: PluginContext): void {}
+
+ async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
+ ctx.registerCommand({
+ id: 'dev.perfetto.AndroidPerfTraceCounters#ThreadRuntimeIPC',
+ name: 'Add a track to show a thread runtime ipc',
+ callback: async (tid) => {
+ if (tid === undefined) {
+ tid = prompt('Enter a thread tid', '');
+ if (tid === null) return;
+ }
+ const sql_prefix = `
+WITH
+ sched_switch_ipc AS (
+ SELECT
+ ts,
+ EXTRACT_ARG(arg_set_id, 'prev_pid') AS tid,
+ EXTRACT_ARG(arg_set_id, 'prev_comm') AS thread_name,
+ EXTRACT_ARG(arg_set_id, 'inst') / (EXTRACT_ARG(arg_set_id, 'cyc') * 1.0) AS ipc,
+ EXTRACT_ARG(arg_set_id, 'inst') AS instruction,
+ EXTRACT_ARG(arg_set_id, 'cyc') AS cycle,
+ EXTRACT_ARG(arg_set_id, 'stallbm') AS stall_backend_mem,
+ EXTRACT_ARG(arg_set_id, 'l3dm') AS l3_cache_miss
+ FROM ftrace_event
+ 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}
+ ),
+ target_thread_ipc_slice AS (
+ SELECT
+ (
+ SELECT
+ ts
+ FROM target_thread_sched_slice ts
+ WHERE ts.tid = ssi.tid AND ts.ts < ssi.ts
+ ORDER BY ts.ts DESC
+ LIMIT 1
+ ) AS ts,
+ (
+ SELECT
+ dur
+ FROM target_thread_sched_slice ts
+ WHERE ts.tid = ssi.tid AND ts.ts < ssi.ts
+ ORDER BY ts.ts DESC
+ LIMIT 1
+ ) AS dur,
+ ssi.ipc,
+ ssi.instruction,
+ ssi.cycle,
+ ssi.stall_backend_mem,
+ ssi.l3_cache_miss
+ FROM sched_switch_ipc ssi
+ )
+`
+
+ await addDebugSliceTrack(
+ ctx.engine,
+ {
+ sqlSource: sql_prefix + `
+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' ],
+ );
+ ctx.tabs.openQuery(sql_prefix + `
+SELECT
+ (sum(instruction) * 1.0 / sum(cycle)*1.0) AS avg_ipc,
+ sum(dur)/1e6 as total_runtime_ms,
+ sum(instruction) AS total_instructions,
+ sum(cycle) AS total_cycles,
+ 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');
+ },
+ });
+ }
+}
+
+export const plugin: PluginDescriptor = {
+ pluginId: 'dev.perfetto.AndroidPerfTraceCounters',
+ plugin: AndroidPerfTraceCounters,
+};
diff --git a/ui/src/public/index.ts b/ui/src/public/index.ts
index 480676c..7a2aaf2 100644
--- a/ui/src/public/index.ts
+++ b/ui/src/public/index.ts
@@ -15,10 +15,10 @@
import m from 'mithril';
import {Hotkey} from '../base/hotkeys';
-import {duration, Span, time} from '../base/time';
+import {duration, time} from '../base/time';
import {ColorScheme} from '../common/colorizer';
+import {PanelSize} from '../frontend/panel';
import {Store} from '../frontend/store';
-import {PxSpan, TimeScale} from '../frontend/time_scale';
import {EngineProxy} from '../trace_processor/engine';
export {createStore, Store} from '../frontend/store';
@@ -173,12 +173,9 @@
export interface Track {
onCreate(ctx: TrackContext): void;
- render(ctx: CanvasRenderingContext2D): void;
+ render(ctx: CanvasRenderingContext2D, size: PanelSize): void;
onFullRedraw(): void;
- getSliceRect(
- visibleTimeScale: TimeScale, visibleWindow: Span<time, duration>,
- windowSpan: PxSpan, tStart: time, tEnd: time, depth: number): SliceRect
- |undefined;
+ getSliceRect(tStart: time, tEnd: time, depth: number): SliceRect|undefined;
getHeight(): number;
getTrackShellButtons(): m.Children;
onMouseMove(position: {x: number, y: number}): void;
diff --git a/ui/src/tracks/android_log/index.ts b/ui/src/tracks/android_log/index.ts
index 2f78a57..04237b6 100644
--- a/ui/src/tracks/android_log/index.ts
+++ b/ui/src/tracks/android_log/index.ts
@@ -21,6 +21,7 @@
import {LIMIT, TrackData} from '../../common/track_data';
import {checkerboardExcept} from '../../frontend/checkerboard';
import {globals} from '../../frontend/globals';
+import {PanelSize} from '../../frontend/panel';
import {NewTrackArgs} from '../../frontend/track';
import {
Plugin,
@@ -107,8 +108,8 @@
super(args);
}
- renderCanvas(ctx: CanvasRenderingContext2D): void {
- const {visibleTimeScale, windowSpan} = globals.frontendLocalState;
+ renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
+ const {visibleTimeScale} = globals.frontendLocalState;
const data = this.data();
@@ -116,16 +117,9 @@
const dataStartPx = visibleTimeScale.timeToPx(data.start);
const dataEndPx = visibleTimeScale.timeToPx(data.end);
- const visibleStartPx = windowSpan.start;
- const visibleEndPx = windowSpan.end;
checkerboardExcept(
- ctx,
- this.getHeight(),
- visibleStartPx,
- visibleEndPx,
- dataStartPx,
- dataEndPx);
+ ctx, this.getHeight(), 0, size.width, dataStartPx, dataEndPx);
const quantWidth =
Math.max(EVT_PX, visibleTimeScale.durationToPx(data.resolution));
diff --git a/ui/src/tracks/counter/index.ts b/ui/src/tracks/counter/index.ts
index 4f2b7f4..f9b61a5 100644
--- a/ui/src/tracks/counter/index.ts
+++ b/ui/src/tracks/counter/index.ts
@@ -29,6 +29,7 @@
} from '../../common/track_helper';
import {checkerboardExcept} from '../../frontend/checkerboard';
import {globals} from '../../frontend/globals';
+import {PanelSize} from '../../frontend/panel';
import {
EngineProxy,
LONG,
@@ -348,11 +349,10 @@
);
}
- renderCanvas(ctx: CanvasRenderingContext2D): void {
+ renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
// TODO: fonts and colors should come from the CSS and not hardcoded here.
const {
visibleTimeScale: timeScale,
- windowSpan,
} = globals.frontendLocalState;
const data = this.data;
@@ -389,7 +389,7 @@
minimumValue = data.minimumRate;
}
- const endPx = windowSpan.end;
+ const endPx = size.width;
const zeroY = MARGIN_TOP + RECT_HEIGHT / (minimumValue < 0 ? 2 : 1);
// Quantize the Y axis to quarters of powers of tens (7.5K, 10K, 12.5K).
@@ -550,8 +550,8 @@
checkerboardExcept(
ctx,
this.getHeight(),
- windowSpan.start,
- windowSpan.end,
+ 0,
+ size.width,
timeScale.timeToPx(data.start),
timeScale.timeToPx(data.end));
}
diff --git a/ui/src/tracks/cpu_freq/index.ts b/ui/src/tracks/cpu_freq/index.ts
index f07f263..06f3087 100644
--- a/ui/src/tracks/cpu_freq/index.ts
+++ b/ui/src/tracks/cpu_freq/index.ts
@@ -27,6 +27,7 @@
import {TrackData} from '../../common/track_data';
import {checkerboardExcept} from '../../frontend/checkerboard';
import {globals} from '../../frontend/globals';
+import {PanelSize} from '../../frontend/panel';
import {NewTrackArgs} from '../../frontend/track';
import {
Plugin,
@@ -288,12 +289,11 @@
return MARGIN_TOP + RECT_HEIGHT;
}
- renderCanvas(ctx: CanvasRenderingContext2D): void {
+ renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
// TODO: fonts and colors should come from the CSS and not hardcoded here.
const {
visibleTimeScale,
visibleWindowTime,
- windowSpan,
} = globals.frontendLocalState;
const data = this.data();
@@ -307,7 +307,7 @@
assertTrue(data.timestamps.length === data.maxFreqKHz.length);
assertTrue(data.timestamps.length === data.lastIdleValues.length);
- const endPx = windowSpan.end;
+ const endPx = size.width;
const zeroY = MARGIN_TOP + RECT_HEIGHT;
// Quantize the Y axis to quarters of powers of tens (7.5K, 10K, 12.5K).
@@ -383,7 +383,7 @@
// Draw CPU idle rectangles that overlay the CPU freq graph.
ctx.fillStyle = `rgba(240, 240, 240, 1)`;
- for (let i = 0; i < data.lastIdleValues.length; i++) {
+ for (let i = startIdx; i < endIdx; i++) {
if (data.lastIdleValues[i] < 0) {
continue;
}
@@ -456,8 +456,8 @@
checkerboardExcept(
ctx,
this.getHeight(),
- windowSpan.start,
- windowSpan.end,
+ 0,
+ size.width,
visibleTimeScale.timeToPx(data.start),
visibleTimeScale.timeToPx(data.end));
}
diff --git a/ui/src/tracks/cpu_profile/index.ts b/ui/src/tracks/cpu_profile/index.ts
index 59ad373..df0916b 100644
--- a/ui/src/tracks/cpu_profile/index.ts
+++ b/ui/src/tracks/cpu_profile/index.ts
@@ -24,6 +24,7 @@
} from '../../common/track_adapter';
import {TrackData} from '../../common/track_data';
import {globals} from '../../frontend/globals';
+import {PanelSize} from '../../frontend/panel';
import {TimeScale} from '../../frontend/time_scale';
import {NewTrackArgs} from '../../frontend/track';
import {
@@ -102,7 +103,7 @@
return MARGIN_TOP + RECT_HEIGHT - 1;
}
- renderCanvas(ctx: CanvasRenderingContext2D): void {
+ renderCanvas(ctx: CanvasRenderingContext2D, _size: PanelSize): void {
const {
visibleTimeScale: timeScale,
} = globals.frontendLocalState;
diff --git a/ui/src/tracks/cpu_slices/index.ts b/ui/src/tracks/cpu_slices/index.ts
index 0e9c470..f4b2830 100644
--- a/ui/src/tracks/cpu_slices/index.ts
+++ b/ui/src/tracks/cpu_slices/index.ts
@@ -34,6 +34,7 @@
import {TrackData} from '../../common/track_data';
import {checkerboardExcept} from '../../frontend/checkerboard';
import {globals} from '../../frontend/globals';
+import {PanelSize} from '../../frontend/panel';
import {NewTrackArgs} from '../../frontend/track';
import {
EngineProxy,
@@ -217,9 +218,9 @@
return TRACK_HEIGHT;
}
- renderCanvas(ctx: CanvasRenderingContext2D): void {
+ renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
// TODO: fonts and colors should come from the CSS and not hardcoded here.
- const {visibleTimeScale, windowSpan} = globals.frontendLocalState;
+ const {visibleTimeScale} = globals.frontendLocalState;
const data = this.data();
if (data === undefined) return; // Can't possibly draw anything.
@@ -229,8 +230,8 @@
checkerboardExcept(
ctx,
this.getHeight(),
- windowSpan.start,
- windowSpan.end,
+ 0,
+ size.width,
visibleTimeScale.timeToPx(data.start),
visibleTimeScale.timeToPx(data.end));
diff --git a/ui/src/tracks/ftrace/index.ts b/ui/src/tracks/ftrace/index.ts
index 75c741e..6ae8474 100644
--- a/ui/src/tracks/ftrace/index.ts
+++ b/ui/src/tracks/ftrace/index.ts
@@ -18,6 +18,7 @@
import {TrackHelperLEGACY} from '../../common/track_helper';
import {checkerboardExcept} from '../../frontend/checkerboard';
import {globals} from '../../frontend/globals';
+import {PanelSize} from '../../frontend/panel';
import {
EngineProxy,
Plugin,
@@ -89,10 +90,9 @@
return result;
}
- renderCanvas(ctx: CanvasRenderingContext2D): void {
+ renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
const {
visibleTimeScale,
- windowSpan,
} = globals.frontendLocalState;
const data = this.data;
@@ -101,16 +101,9 @@
const dataStartPx = visibleTimeScale.timeToPx(data.start);
const dataEndPx = visibleTimeScale.timeToPx(data.end);
- const visibleStartPx = windowSpan.start;
- const visibleEndPx = windowSpan.end;
checkerboardExcept(
- ctx,
- this.getHeight(),
- visibleStartPx,
- visibleEndPx,
- dataStartPx,
- dataEndPx);
+ ctx, this.getHeight(), 0, size.width, dataStartPx, dataEndPx);
const diamondSideLen = RECT_HEIGHT / Math.sqrt(2);
diff --git a/ui/src/tracks/perf_samples_profile/index.ts b/ui/src/tracks/perf_samples_profile/index.ts
index dd30045..a78e36d 100644
--- a/ui/src/tracks/perf_samples_profile/index.ts
+++ b/ui/src/tracks/perf_samples_profile/index.ts
@@ -24,6 +24,7 @@
import {TrackData} from '../../common/track_data';
import {FLAMEGRAPH_HOVERED_COLOR} from '../../frontend/flamegraph';
import {globals} from '../../frontend/globals';
+import {PanelSize} from '../../frontend/panel';
import {TimeScale} from '../../frontend/time_scale';
import {NewTrackArgs} from '../../frontend/track';
import {
@@ -99,7 +100,7 @@
return MARGIN_TOP + RECT_HEIGHT - 1;
}
- renderCanvas(ctx: CanvasRenderingContext2D): void {
+ renderCanvas(ctx: CanvasRenderingContext2D, _size: PanelSize): void {
const {
visibleTimeScale,
} = globals.frontendLocalState;
diff --git a/ui/src/tracks/process_summary/process_scheduling_track.ts b/ui/src/tracks/process_summary/process_scheduling_track.ts
index a955278..455cac5 100644
--- a/ui/src/tracks/process_summary/process_scheduling_track.ts
+++ b/ui/src/tracks/process_summary/process_scheduling_track.ts
@@ -28,6 +28,7 @@
import {TrackData} from '../../common/track_data';
import {checkerboardExcept} from '../../frontend/checkerboard';
import {globals} from '../../frontend/globals';
+import {PanelSize} from '../../frontend/panel';
import {NewTrackArgs} from '../../frontend/track';
import {
LONG,
@@ -200,11 +201,10 @@
return TRACK_HEIGHT;
}
- renderCanvas(ctx: CanvasRenderingContext2D): void {
+ renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
// TODO: fonts and colors should come from the CSS and not hardcoded here.
const {
visibleTimeScale,
- visibleWindowTime,
visibleTimeSpan,
} = globals.frontendLocalState;
const data = this.data();
@@ -216,8 +216,8 @@
checkerboardExcept(
ctx,
this.getHeight(),
- visibleTimeScale.hpTimeToPx(visibleWindowTime.start),
- visibleTimeScale.hpTimeToPx(visibleWindowTime.end),
+ 0,
+ size.width,
visibleTimeScale.timeToPx(data.start),
visibleTimeScale.timeToPx(data.end));
diff --git a/ui/src/tracks/process_summary/process_summary_track.ts b/ui/src/tracks/process_summary/process_summary_track.ts
index ee0bcc8..383dcb3 100644
--- a/ui/src/tracks/process_summary/process_summary_track.ts
+++ b/ui/src/tracks/process_summary/process_summary_track.ts
@@ -20,6 +20,7 @@
import {LIMIT, TrackData} from '../../common/track_data';
import {checkerboardExcept} from '../../frontend/checkerboard';
import {globals} from '../../frontend/globals';
+import {PanelSize} from '../../frontend/panel';
import {NewTrackArgs} from '../../frontend/track';
import {NUM} from '../../trace_processor/query_result';
@@ -150,10 +151,9 @@
return TRACK_HEIGHT;
}
- renderCanvas(ctx: CanvasRenderingContext2D): void {
+ renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
const {
visibleTimeScale,
- windowSpan,
} = globals.frontendLocalState;
const data = this.data();
if (data === undefined) return; // Can't possibly draw anything.
@@ -161,8 +161,8 @@
checkerboardExcept(
ctx,
this.getHeight(),
- windowSpan.start,
- windowSpan.end,
+ 0,
+ size.width,
visibleTimeScale.timeToPx(data.start),
visibleTimeScale.timeToPx(data.end));
@@ -171,8 +171,8 @@
// TODO(dproy): Dedup with CPU slices.
renderSummary(ctx: CanvasRenderingContext2D, data: Data): void {
- const {visibleTimeScale, windowSpan} = globals.frontendLocalState;
- const startPx = windowSpan.start;
+ const {visibleTimeScale} = globals.frontendLocalState;
+ const startPx = 0;
const bottomY = TRACK_HEIGHT;
let lastX = startPx;
diff --git a/ui/src/tracks/thread_state/index.ts b/ui/src/tracks/thread_state/index.ts
index 7544ddb..074025e 100644
--- a/ui/src/tracks/thread_state/index.ts
+++ b/ui/src/tracks/thread_state/index.ts
@@ -28,6 +28,7 @@
import {TrackData} from '../../common/track_data';
import {checkerboardExcept} from '../../frontend/checkerboard';
import {globals} from '../../frontend/globals';
+import {PanelSize} from '../../frontend/panel';
import {NewTrackArgs} from '../../frontend/track';
import {
Plugin,
@@ -187,11 +188,10 @@
return 2 * MARGIN_TOP + RECT_HEIGHT;
}
- renderCanvas(ctx: CanvasRenderingContext2D): void {
+ renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
const {
visibleTimeScale: timeScale,
visibleTimeSpan,
- windowSpan,
} = globals.frontendLocalState;
const data = this.data();
const charWidth = ctx.measureText('dbpqaouk').width / 8;
@@ -205,8 +205,8 @@
checkerboardExcept(
ctx,
this.getHeight(),
- windowSpan.start,
- windowSpan.end,
+ 0,
+ size.width,
timeScale.timeToPx(data.start),
timeScale.timeToPx(data.end),
);
@@ -257,7 +257,7 @@
const rectStart =
Math.max(0 - EXCESS_WIDTH, timeScale.timeToPx(tStart));
const rectEnd =
- Math.min(windowSpan.end + EXCESS_WIDTH, timeScale.timeToPx(tEnd));
+ Math.min(size.width + EXCESS_WIDTH, timeScale.timeToPx(tEnd));
ctx.strokeStyle = colorScheme.base.cssString;
ctx.beginPath();
ctx.lineWidth = 3;