Merge "TraceProcessor: increase HTTP max req size"
diff --git a/Android.bp b/Android.bp
index 372249e..c7f2447 100644
--- a/Android.bp
+++ b/Android.bp
@@ -8116,6 +8116,8 @@
"src/trace_processor/metrics/sql/android/span_view_stats.sql",
"src/trace_processor/metrics/sql/android/startup/hsc.sql",
"src/trace_processor/metrics/sql/android/startup/launches.sql",
+ "src/trace_processor/metrics/sql/android/startup/launches_maxsdk28.sql",
+ "src/trace_processor/metrics/sql/android/startup/launches_minsdk29.sql",
"src/trace_processor/metrics/sql/android/thread_counter_span_view.sql",
"src/trace_processor/metrics/sql/android/unsymbolized_frames.sql",
"src/trace_processor/metrics/sql/chrome/actual_power_by_category.sql",
diff --git a/BUILD b/BUILD
index 94521a4..ccc51d8 100644
--- a/BUILD
+++ b/BUILD
@@ -1088,6 +1088,8 @@
"src/trace_processor/metrics/sql/android/span_view_stats.sql",
"src/trace_processor/metrics/sql/android/startup/hsc.sql",
"src/trace_processor/metrics/sql/android/startup/launches.sql",
+ "src/trace_processor/metrics/sql/android/startup/launches_maxsdk28.sql",
+ "src/trace_processor/metrics/sql/android/startup/launches_minsdk29.sql",
"src/trace_processor/metrics/sql/android/thread_counter_span_view.sql",
"src/trace_processor/metrics/sql/android/unsymbolized_frames.sql",
"src/trace_processor/metrics/sql/chrome/actual_power_by_category.sql",
diff --git a/src/base/file_utils.cc b/src/base/file_utils.cc
index 7ccbad4..8f998dd 100644
--- a/src/base/file_utils.cc
+++ b/src/base/file_utils.cc
@@ -237,15 +237,14 @@
if (glob_path.length() + 1 > MAX_PATH)
return base::ErrStatus("Directory path %s is too long", dir_path.c_str());
WIN32_FIND_DATAA ffd;
- // We do not use a ScopedResource for the HANDLE from FindFirstFile because
- // the invalid value INVALID_HANDLE_VALUE is not a constexpr under some
- // compile configurations, and thus cannot be used as a template argument.
- HANDLE hFind = FindFirstFileA(glob_path.c_str(), &ffd);
- if (hFind == INVALID_HANDLE_VALUE) {
+
+ base::ScopedResource<HANDLE, FindClose, nullptr, false,
+ base::PlatformHandleChecker>
+ hFind(FindFirstFileA(glob_path.c_str(), &ffd));
+ if (!hFind) {
// For empty directories, there should be at least one entry '.'.
// If FindFirstFileA returns INVALID_HANDLE_VALUE, this means directory
// couldn't be accessed.
- FindClose(hFind);
return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
}
do {
@@ -254,13 +253,12 @@
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
std::string subdir_path = cur_dir + ffd.cFileName + '/';
dir_queue.push_back(subdir_path);
- } else if (ffd.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) {
+ } else {
const std::string full_path = cur_dir + ffd.cFileName;
PERFETTO_CHECK(full_path.length() > root_dir_path.length());
output.push_back(full_path.substr(root_dir_path.length()));
}
- } while (FindNextFileA(hFind, &ffd));
- FindClose(hFind);
+ } while (FindNextFileA(*hFind, &ffd));
#else
ScopedDir dir = ScopedDir(opendir(cur_dir.c_str()));
if (!dir) {
diff --git a/src/base/http/http_server.cc b/src/base/http/http_server.cc
index ebb57e7..0b098e1 100644
--- a/src/base/http/http_server.cc
+++ b/src/base/http/http_server.cc
@@ -464,11 +464,12 @@
append("HTTP/1.1 ");
append(http_code);
append("\r\n");
- for (const char* hdr : headers) {
- if (strlen(hdr) == 0)
+ for (const char* hdr_cstr : headers) {
+ StringView hdr = (hdr_cstr);
+ if (hdr.empty())
continue;
- has_connection_header |= strncasecmp(hdr, "connection:", 11) == 0;
- append(hdr);
+ has_connection_header |= hdr.substr(0, 11).CaseInsensitiveEq("connection:");
+ append(hdr_cstr);
append("\r\n");
}
content_len_actual_ = 0;
diff --git a/src/base/http/http_server_unittest.cc b/src/base/http/http_server_unittest.cc
index 9726ab6..be65198 100644
--- a/src/base/http/http_server_unittest.cc
+++ b/src/base/http/http_server_unittest.cc
@@ -66,16 +66,17 @@
auto checkpoint = task_runner_->CreateCheckpoint(checkpoint_name);
std::string rxbuf;
sock.SetBlocking(false);
- task_runner_->AddFileDescriptorWatch(sock.fd(), [&] {
+ task_runner_->AddFileDescriptorWatch(sock.watch_handle(), [&] {
char buf[1024]{};
auto rsize = PERFETTO_EINTR(sock.Receive(buf, sizeof(buf)));
- ASSERT_GE(rsize, 0);
+ if (rsize < 0)
+ return;
rxbuf.append(buf, static_cast<size_t>(rsize));
if (rsize == 0 || (min_bytes && rxbuf.length() >= min_bytes))
checkpoint();
});
task_runner_->RunUntilCheckpoint(checkpoint_name);
- task_runner_->RemoveFileDescriptorWatch(sock.fd());
+ task_runner_->RemoveFileDescriptorWatch(sock.watch_handle());
return rxbuf;
}
@@ -289,7 +290,9 @@
srv_.AddAllowedOrigin("notallowed.com");
HttpCli cli(&task_runner_);
- EXPECT_CALL(handler_, OnHttpConnectionClosed(_));
+ auto close_checkpoint = task_runner_.CreateCheckpoint("close");
+ EXPECT_CALL(handler_, OnHttpConnectionClosed(_))
+ .WillOnce(InvokeWithoutArgs(close_checkpoint));
EXPECT_CALL(handler_, OnHttpRequest(_))
.WillOnce(Invoke([&](const HttpRequest& req) {
EXPECT_EQ(req.origin.ToStdString(), "http://notallowed.com");
@@ -314,6 +317,7 @@
EXPECT_EQ(cli.Recv(expected_resp.size()), expected_resp);
cli.sock.Shutdown();
+ task_runner_.RunUntilCheckpoint("close");
}
} // namespace
diff --git a/src/base/http/sha1.cc b/src/base/http/sha1.cc
index da3f753..f3e1e5d 100644
--- a/src/base/http/sha1.cc
+++ b/src/base/http/sha1.cc
@@ -30,7 +30,7 @@
#if defined(__GNUC__)
return __builtin_bswap32(x);
#elif defined(_MSC_VER)
- return _byteswap_ulong(val);
+ return _byteswap_ulong(x);
#else
return (((x & 0xff000000u) >> 24) | ((x & 0x00ff0000u) >> 8) |
((x & 0x0000ff00u) << 8) | ((x & 0x000000ffu) << 24));
diff --git a/src/base/unix_socket_unittest.cc b/src/base/unix_socket_unittest.cc
index c838663..45c09d5 100644
--- a/src/base/unix_socket_unittest.cc
+++ b/src/base/unix_socket_unittest.cc
@@ -332,53 +332,6 @@
tx_thread.join();
}
-// Regression test for b/193234818. SO_SNDTIMEO is unreliable on most systems.
-// It doesn't guarantee that the whole send() call blocks for at most X, as the
-// kernel rearms the timeout if the send buffers frees up and allows a partial
-// send. This test reproduces the issue 100% on Mac. Unfortunately on Linux the
-// repro seem to happen only when a suspend happens in the middle.
-TEST_F(UnixSocketTest, BlockingSendTimeout) {
- TestTaskRunner ttr;
- UnixSocketRaw send_sock;
- UnixSocketRaw recv_sock;
- std::tie(send_sock, recv_sock) =
- UnixSocketRaw::CreatePairPosix(kTestSocket.family(), SockType::kStream);
-
- auto blocking_send_done = ttr.CreateCheckpoint("blocking_send_done");
-
- std::thread tx_thread([&] {
- // Fill the tx buffer in non-blocking mode.
- send_sock.SetBlocking(false);
- char buf[1024 * 16]{};
- while (send_sock.Send(buf, sizeof(buf)) > 0) {
- }
-
- // Then do a blocking send. It should return a partial value within the tx
- // timeout.
- send_sock.SetBlocking(true);
- send_sock.SetTxTimeout(10);
- ASSERT_LT(send_sock.Send(buf, sizeof(buf)),
- static_cast<ssize_t>(sizeof(buf)));
- ttr.PostTask(blocking_send_done);
- });
-
- // This task needs to be slow enough so that doesn't unblock the send, but
- // fast enough so that within a blocking cycle, the send re-attempts and
- // re-arms the timeout.
- PeriodicTask read_slowly_task(&ttr);
- PeriodicTask::Args args;
- args.period_ms = 1; // Read 1 byte every ms (1 KiB/s).
- args.task = [&] {
- char rxbuf[1]{};
- recv_sock.Receive(rxbuf, sizeof(rxbuf));
- };
- read_slowly_task.Start(args);
-
- ttr.RunUntilCheckpoint("blocking_send_done");
- read_slowly_task.Reset();
- tx_thread.join();
-}
-
// Regression test for b/76155349 . If the receiver end disconnects while the
// sender is in the middle of a large send(), the socket should gracefully give
// up (i.e. Shutdown()) but not crash.
@@ -939,6 +892,53 @@
ASSERT_EQ(hdr.msg_iov, nullptr);
ASSERT_EQ(memcmp(&send_buf[0], &recv_buf[0], send_buf.size()), 0);
}
+
+// Regression test for b/193234818. SO_SNDTIMEO is unreliable on most systems.
+// It doesn't guarantee that the whole send() call blocks for at most X, as the
+// kernel rearms the timeout if the send buffers frees up and allows a partial
+// send. This test reproduces the issue 100% on Mac. Unfortunately on Linux the
+// repro seem to happen only when a suspend happens in the middle.
+TEST_F(UnixSocketTest, BlockingSendTimeout) {
+ TestTaskRunner ttr;
+ UnixSocketRaw send_sock;
+ UnixSocketRaw recv_sock;
+ std::tie(send_sock, recv_sock) =
+ UnixSocketRaw::CreatePairPosix(kTestSocket.family(), SockType::kStream);
+
+ auto blocking_send_done = ttr.CreateCheckpoint("blocking_send_done");
+
+ std::thread tx_thread([&] {
+ // Fill the tx buffer in non-blocking mode.
+ send_sock.SetBlocking(false);
+ char buf[1024 * 16]{};
+ while (send_sock.Send(buf, sizeof(buf)) > 0) {
+ }
+
+ // Then do a blocking send. It should return a partial value within the tx
+ // timeout.
+ send_sock.SetBlocking(true);
+ send_sock.SetTxTimeout(10);
+ ASSERT_LT(send_sock.Send(buf, sizeof(buf)),
+ static_cast<ssize_t>(sizeof(buf)));
+ ttr.PostTask(blocking_send_done);
+ });
+
+ // This task needs to be slow enough so that doesn't unblock the send, but
+ // fast enough so that within a blocking cycle, the send re-attempts and
+ // re-arms the timeout.
+ PeriodicTask read_slowly_task(&ttr);
+ PeriodicTask::Args args;
+ args.period_ms = 1; // Read 1 byte every ms (1 KiB/s).
+ args.task = [&] {
+ char rxbuf[1]{};
+ recv_sock.Receive(rxbuf, sizeof(rxbuf));
+ };
+ read_slowly_task.Start(args);
+
+ ttr.RunUntilCheckpoint("blocking_send_done");
+ read_slowly_task.Reset();
+ tx_thread.join();
+}
#endif // !OS_WIN
} // namespace
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index 390d82f..403b300 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -223,8 +223,14 @@
void FtraceParser::ParseFtraceStats(ConstBytes blob) {
protos::pbzero::FtraceStats::Decoder evt(blob.data, blob.size);
- size_t phase =
- evt.phase() == protos::pbzero::FtraceStats_Phase_END_OF_TRACE ? 1 : 0;
+ bool is_start =
+ evt.phase() == protos::pbzero::FtraceStats_Phase_START_OF_TRACE;
+ bool is_end = evt.phase() == protos::pbzero::FtraceStats_Phase_END_OF_TRACE;
+ if (!is_start && !is_end) {
+ PERFETTO_ELOG("Ignoring unknown ftrace stats phase %d", evt.phase());
+ return;
+ }
+ size_t phase = is_end ? 1 : 0;
// This code relies on the fact that each ftrace_cpu_XXX_end event is
// just after the corresponding ftrace_cpu_XXX_begin event.
@@ -238,15 +244,81 @@
for (auto it = evt.cpu_stats(); it; ++it) {
protos::pbzero::FtraceCpuStats::Decoder cpu_stats(*it);
int cpu = static_cast<int>(cpu_stats.cpu());
+
+ int64_t entries = static_cast<int64_t>(cpu_stats.entries());
+ int64_t overrun = static_cast<int64_t>(cpu_stats.overrun());
+ int64_t commit_overrun = static_cast<int64_t>(cpu_stats.commit_overrun());
+ int64_t bytes_read = static_cast<int64_t>(cpu_stats.bytes_read());
+ int64_t dropped_events = static_cast<int64_t>(cpu_stats.dropped_events());
+ int64_t read_events = static_cast<int64_t>(cpu_stats.read_events());
+ int64_t now_ts = static_cast<int64_t>(cpu_stats.now_ts() * 1e9);
+
storage->SetIndexedStats(stats::ftrace_cpu_entries_begin + phase, cpu,
- static_cast<int64_t>(cpu_stats.entries()));
+ entries);
storage->SetIndexedStats(stats::ftrace_cpu_overrun_begin + phase, cpu,
- static_cast<int64_t>(cpu_stats.overrun()));
+ overrun);
storage->SetIndexedStats(stats::ftrace_cpu_commit_overrun_begin + phase,
- cpu,
- static_cast<int64_t>(cpu_stats.commit_overrun()));
+ cpu, commit_overrun);
storage->SetIndexedStats(stats::ftrace_cpu_bytes_read_begin + phase, cpu,
- static_cast<int64_t>(cpu_stats.bytes_read()));
+ bytes_read);
+ storage->SetIndexedStats(stats::ftrace_cpu_dropped_events_begin + phase,
+ cpu, dropped_events);
+ storage->SetIndexedStats(stats::ftrace_cpu_read_events_begin + phase, cpu,
+ read_events);
+ storage->SetIndexedStats(stats::ftrace_cpu_now_ts_begin + phase, cpu,
+ now_ts);
+
+ if (is_end) {
+ auto opt_entries_begin =
+ storage->GetIndexedStats(stats::ftrace_cpu_entries_begin, cpu);
+ if (opt_entries_begin) {
+ int64_t delta_entries = entries - opt_entries_begin.value();
+ storage->SetIndexedStats(stats::ftrace_cpu_entries_delta, cpu,
+ delta_entries);
+ }
+
+ auto opt_overrun_begin =
+ storage->GetIndexedStats(stats::ftrace_cpu_overrun_begin, cpu);
+ if (opt_overrun_begin) {
+ int64_t delta_overrun = overrun - opt_overrun_begin.value();
+ storage->SetIndexedStats(stats::ftrace_cpu_overrun_delta, cpu,
+ delta_overrun);
+ }
+
+ auto opt_commit_overrun_begin =
+ storage->GetIndexedStats(stats::ftrace_cpu_commit_overrun_begin, cpu);
+ if (opt_commit_overrun_begin) {
+ int64_t delta_commit_overrun =
+ commit_overrun - opt_commit_overrun_begin.value();
+ storage->SetIndexedStats(stats::ftrace_cpu_commit_overrun_delta, cpu,
+ delta_commit_overrun);
+ }
+
+ auto opt_bytes_read_begin =
+ storage->GetIndexedStats(stats::ftrace_cpu_bytes_read_begin, cpu);
+ if (opt_bytes_read_begin) {
+ int64_t delta_bytes_read = bytes_read - opt_bytes_read_begin.value();
+ storage->SetIndexedStats(stats::ftrace_cpu_bytes_read_delta, cpu,
+ delta_bytes_read);
+ }
+
+ auto opt_dropped_events_begin =
+ storage->GetIndexedStats(stats::ftrace_cpu_dropped_events_begin, cpu);
+ if (opt_dropped_events_begin) {
+ int64_t delta_dropped_events =
+ dropped_events - opt_dropped_events_begin.value();
+ storage->SetIndexedStats(stats::ftrace_cpu_dropped_events_delta, cpu,
+ delta_dropped_events);
+ }
+
+ auto opt_read_events_begin =
+ storage->GetIndexedStats(stats::ftrace_cpu_read_events_begin, cpu);
+ if (opt_read_events_begin) {
+ int64_t delta_read_events = read_events - opt_read_events_begin.value();
+ storage->SetIndexedStats(stats::ftrace_cpu_read_events_delta, cpu,
+ delta_read_events);
+ }
+ }
// oldest_event_ts can often be set to very high values, possibly because
// of wrapping. Ensure that we are not overflowing to avoid ubsan
@@ -266,14 +338,6 @@
storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
cpu, static_cast<int64_t>(oldest_event_ts));
}
-
- storage->SetIndexedStats(stats::ftrace_cpu_now_ts_begin + phase, cpu,
- static_cast<int64_t>(cpu_stats.now_ts() * 1e9));
- storage->SetIndexedStats(stats::ftrace_cpu_dropped_events_begin + phase,
- cpu,
- static_cast<int64_t>(cpu_stats.dropped_events()));
- storage->SetIndexedStats(stats::ftrace_cpu_read_events_begin + phase, cpu,
- static_cast<int64_t>(cpu_stats.read_events()));
}
}
diff --git a/src/trace_processor/metrics/metrics.cc b/src/trace_processor/metrics/metrics.cc
index 6926cff..6c2536e 100644
--- a/src/trace_processor/metrics/metrics.cc
+++ b/src/trace_processor/metrics/metrics.cc
@@ -620,8 +620,9 @@
auto metric_it = std::find_if(
ctx->metrics->begin(), ctx->metrics->end(),
[path](const SqlMetricFile& metric) { return metric.path == path; });
- if (metric_it == ctx->metrics->end())
- return base::ErrStatus("RUN_METRIC: Unknown filename provided");
+ if (metric_it == ctx->metrics->end()) {
+ return base::ErrStatus("RUN_METRIC: Unknown filename provided %s", path);
+ }
const auto& sql = metric_it->sql;
std::unordered_map<std::string, std::string> substitutions;
diff --git a/src/trace_processor/metrics/sql/BUILD.gn b/src/trace_processor/metrics/sql/BUILD.gn
index 064630b..7ddbf2a 100644
--- a/src/trace_processor/metrics/sql/BUILD.gn
+++ b/src/trace_processor/metrics/sql/BUILD.gn
@@ -71,6 +71,8 @@
"android/gpu_counter_span_view.sql",
"android/thread_counter_span_view.sql",
"android/unsymbolized_frames.sql",
+ "android/startup/launches_maxsdk28.sql",
+ "android/startup/launches_minsdk29.sql",
"android/startup/launches.sql",
"android/startup/hsc.sql",
"chrome/actual_power_by_category.sql",
diff --git a/src/trace_processor/metrics/sql/android/startup/launches.sql b/src/trace_processor/metrics/sql/android/startup/launches.sql
index c3be64c..492bac5 100644
--- a/src/trace_processor/metrics/sql/android/startup/launches.sql
+++ b/src/trace_processor/metrics/sql/android/startup/launches.sql
@@ -12,29 +12,6 @@
-- 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.
---
-
--- Marks the beginning of the trace and is equivalent to when the statsd launch
--- logging begins.
-DROP VIEW IF EXISTS activity_intent_received;
-CREATE VIEW activity_intent_received AS
-SELECT ts FROM slice
-WHERE name = 'MetricsLogger:launchObserverNotifyIntentStarted';
-
--- We partition the trace into spans based on posted activity intents.
--- We will refine these progressively in the next steps to only encompass
--- activity starts.
-DROP TABLE IF EXISTS activity_intent_recv_spans;
-CREATE TABLE activity_intent_recv_spans(id INT, ts BIG INT, dur BIG INT);
-
-INSERT INTO activity_intent_recv_spans
-SELECT
- ROW_NUMBER()
- OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS id,
- ts,
- LEAD(ts, 1, (SELECT end_ts FROM trace_bounds)) OVER(ORDER BY ts) - ts AS dur
-FROM activity_intent_received
-ORDER BY ts;
-- The start of the launching event corresponds to the end of the AM handling
-- the startActivity intent, whereas the end corresponds to the first frame drawn.
@@ -52,64 +29,66 @@
WHERE s.name GLOB 'launching: *'
AND (process.name IS NULL OR process.name = 'system_server');
--- Filter activity_intent_recv_spans, keeping only the ones that triggered
--- a launch.
-DROP VIEW IF EXISTS launch_partitions;
-CREATE VIEW launch_partitions AS
-SELECT * FROM activity_intent_recv_spans AS spans
-WHERE 1 = (
- SELECT COUNT(1)
- FROM launching_events
- WHERE launching_events.ts BETWEEN spans.ts AND spans.ts + spans.dur);
+SELECT CREATE_FUNCTION(
+ 'ANDROID_SDK_LEVEL()',
+ 'INT', "
+ SELECT int_value
+ FROM metadata
+ WHERE name = 'android_sdk_version'
+ ");
--- Successful activity launch. The end of the 'launching' event is not related
--- to whether it actually succeeded or not.
-DROP VIEW IF EXISTS activity_intent_launch_successful;
-CREATE VIEW activity_intent_launch_successful AS
-SELECT ts FROM slice
-WHERE name = 'MetricsLogger:launchObserverNotifyActivityLaunchFinished';
-
--- All activity launches in the trace, keyed by ID.
-DROP TABLE IF EXISTS launches;
-CREATE TABLE launches(
- ts BIG INT,
- ts_end BIG INT,
- dur BIG INT,
- id INT,
- package STRING);
-
--- Use the starting event package name. The finish event package name
--- is not reliable in the case of failed launches.
-INSERT INTO launches
-SELECT
- lpart.ts AS ts,
- launching_events.ts_end AS ts_end,
- launching_events.ts_end - lpart.ts AS dur,
- lpart.id AS id,
- package_name AS package
-FROM launch_partitions AS lpart
-JOIN launching_events ON
- (launching_events.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur) AND
- (launching_events.ts_end BETWEEN lpart.ts AND lpart.ts + lpart.dur)
-WHERE (
- SELECT COUNT(1)
- FROM activity_intent_launch_successful AS successful
- WHERE successful.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur
-) > 0;
+-- Note: on Q, we didn't have Android fingerprints but we *did*
+-- have ActivityMetricsLogger events so we will use this approach
+-- if we see any such events.
+SELECT CASE
+ WHEN (
+ ANDROID_SDK_LEVEL() >= 29
+ OR (
+ SELECT COUNT(1) FROM slice
+ WHERE name GLOB 'MetricsLogger:*'
+ ) > 0
+ )
+ THEN RUN_METRIC('android/startup/launches_minsdk29.sql')
+ ELSE RUN_METRIC('android/startup/launches_maxsdk28.sql')
+END;
-- Maps a launch to the corresponding set of processes that handled the
-- activity start. The vast majority of cases should be a single process.
-- However it is possible that the process dies during the activity launch
-- and is respawned.
DROP TABLE IF EXISTS launch_processes;
-CREATE TABLE launch_processes(launch_id INT, upid BIG INT);
+CREATE TABLE launch_processes(launch_id INT, upid BIG INT, launch_type STRING);
-INSERT INTO launch_processes
-SELECT launches.id, process.upid
-FROM launches
- LEFT JOIN package_list ON (launches.package = package_list.package_name)
- JOIN process ON (launches.package = process.name OR process.uid = package_list.uid)
- JOIN thread ON (process.upid = thread.upid AND process.pid = thread.tid)
-WHERE (process.start_ts IS NULL OR process.start_ts < launches.ts_end)
-AND (thread.end_ts IS NULL OR thread.end_ts > launches.ts_end)
-ORDER BY process.start_ts DESC;
+SELECT CREATE_FUNCTION(
+ 'STARTUP_SLICE_COUNT(start_ts LONG, end_ts LONG, utid INT, name STRING)',
+ 'INT',
+ '
+ SELECT COUNT(1)
+ FROM thread_track t
+ JOIN slice s ON s.track_id = t.id
+ WHERE
+ t.utid = $utid AND
+ s.ts >= $start_ts AND
+ s.ts < $end_ts AND
+ s.name = $name
+ '
+);
+
+INSERT INTO launch_processes(launch_id, upid, launch_type)
+SELECT
+ l.id AS launch_id,
+ p.upid,
+ CASE
+ WHEN STARTUP_SLICE_COUNT(l.ts, l.ts_end, t.utid, 'bindApplication') > 0
+ THEN 'cold'
+ WHEN STARTUP_SLICE_COUNT(l.ts, l.ts_end, t.utid, 'activityStart') > 0
+ THEN 'warm'
+ WHEN STARTUP_SLICE_COUNT(l.ts, l.ts_end, t.utid, 'activityResume') > 0
+ THEN 'hot'
+ ELSE NULL
+ END AS launch_type
+FROM launches l
+LEFT JOIN package_list ON (l.package = package_list.package_name)
+JOIN process p ON (l.package = p.name OR p.uid = package_list.uid)
+JOIN thread t ON (p.upid = t.upid AND t.is_main_thread)
+WHERE launch_type IS NOT NULL;
diff --git a/src/trace_processor/metrics/sql/android/startup/launches_maxsdk28.sql b/src/trace_processor/metrics/sql/android/startup/launches_maxsdk28.sql
new file mode 100644
index 0000000..8753da1
--- /dev/null
+++ b/src/trace_processor/metrics/sql/android/startup/launches_maxsdk28.sql
@@ -0,0 +1,36 @@
+--
+-- Copyright 2021 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
+--
+-- https://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.
+--
+
+-- All activity launches in the trace, keyed by ID.
+DROP TABLE IF EXISTS launches;
+CREATE TABLE launches(
+ id INTEGER PRIMARY KEY,
+ ts BIG INT,
+ ts_end BIG INT,
+ dur BIG INT,
+ package STRING
+);
+
+-- Cold/warm starts emitted launching slices on API level 28-.
+INSERT INTO launches(ts, ts_end, dur, package)
+SELECT
+ launching_events.ts AS ts,
+ launching_events.ts_end AS ts_end,
+ launching_events.ts_end - launching_events.ts AS dur,
+ package_name AS package
+FROM launching_events;
+
+-- TODO(lalitm): add handling of hot starts using frame timings.
diff --git a/src/trace_processor/metrics/sql/android/startup/launches_minsdk29.sql b/src/trace_processor/metrics/sql/android/startup/launches_minsdk29.sql
new file mode 100644
index 0000000..1f4c0f7
--- /dev/null
+++ b/src/trace_processor/metrics/sql/android/startup/launches_minsdk29.sql
@@ -0,0 +1,82 @@
+--
+-- Copyright 2021 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
+--
+-- https://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.
+--
+
+-- Marks the beginning of the trace and is equivalent to when the statsd launch
+-- logging begins.
+DROP VIEW IF EXISTS activity_intent_received;
+CREATE VIEW activity_intent_received AS
+SELECT ts FROM slice
+WHERE name = 'MetricsLogger:launchObserverNotifyIntentStarted';
+
+-- We partition the trace into spans based on posted activity intents.
+-- We will refine these progressively in the next steps to only encompass
+-- activity starts.
+DROP TABLE IF EXISTS activity_intent_recv_spans;
+CREATE TABLE activity_intent_recv_spans(id INT, ts BIG INT, dur BIG INT);
+
+INSERT INTO activity_intent_recv_spans
+SELECT
+ ROW_NUMBER()
+ OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS id,
+ ts,
+ LEAD(ts, 1, (SELECT end_ts FROM trace_bounds)) OVER(ORDER BY ts) - ts AS dur
+FROM activity_intent_received
+ORDER BY ts;
+
+-- Filter activity_intent_recv_spans, keeping only the ones that triggered
+-- a launch.
+DROP VIEW IF EXISTS launch_partitions;
+CREATE VIEW launch_partitions AS
+SELECT * FROM activity_intent_recv_spans AS spans
+WHERE 1 = (
+ SELECT COUNT(1)
+ FROM launching_events
+ WHERE launching_events.ts BETWEEN spans.ts AND spans.ts + spans.dur);
+
+-- Successful activity launch. The end of the 'launching' event is not related
+-- to whether it actually succeeded or not.
+DROP VIEW IF EXISTS activity_intent_launch_successful;
+CREATE VIEW activity_intent_launch_successful AS
+SELECT ts FROM slice
+WHERE name = 'MetricsLogger:launchObserverNotifyActivityLaunchFinished';
+
+-- All activity launches in the trace, keyed by ID.
+DROP TABLE IF EXISTS launches;
+CREATE TABLE launches(
+ ts BIG INT,
+ ts_end BIG INT,
+ dur BIG INT,
+ id INT,
+ package STRING);
+
+-- Use the starting event package name. The finish event package name
+-- is not reliable in the case of failed launches.
+INSERT INTO launches
+SELECT
+ lpart.ts AS ts,
+ launching_events.ts_end AS ts_end,
+ launching_events.ts_end - lpart.ts AS dur,
+ lpart.id AS id,
+ package_name AS package
+FROM launch_partitions AS lpart
+JOIN launching_events ON
+ (launching_events.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur) AND
+ (launching_events.ts_end BETWEEN lpart.ts AND lpart.ts + lpart.dur)
+WHERE (
+ SELECT COUNT(1)
+ FROM activity_intent_launch_successful AS successful
+ WHERE successful.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur
+) > 0;
diff --git a/src/trace_processor/storage/stats.h b/src/trace_processor/storage/stats.h
index 7e537ca..b52a4c9 100644
--- a/src/trace_processor/storage/stats.h
+++ b/src/trace_processor/storage/stats.h
@@ -35,22 +35,28 @@
F(ftrace_bundle_tokenizer_errors, kSingle, kError, kAnalysis, ""), \
F(ftrace_cpu_bytes_read_begin, kIndexed, kInfo, kTrace, ""), \
F(ftrace_cpu_bytes_read_end, kIndexed, kInfo, kTrace, ""), \
- F(ftrace_cpu_commit_overrun_begin, kIndexed, kError, kTrace, ""), \
- F(ftrace_cpu_commit_overrun_end, kIndexed, kError, kTrace, ""), \
- F(ftrace_cpu_dropped_events_begin, kIndexed, kError, kTrace, ""), \
- F(ftrace_cpu_dropped_events_end, kIndexed, kError, kTrace, ""), \
+ F(ftrace_cpu_bytes_read_delta, kIndexed, kInfo, kTrace, ""), \
+ F(ftrace_cpu_commit_overrun_begin, kIndexed, kInfo, kTrace, ""), \
+ F(ftrace_cpu_commit_overrun_end, kIndexed, kInfo, kTrace, ""), \
+ F(ftrace_cpu_commit_overrun_delta, kIndexed, kError, kTrace, ""), \
+ F(ftrace_cpu_dropped_events_begin, kIndexed, kInfo, kTrace, ""), \
+ F(ftrace_cpu_dropped_events_end, kIndexed, kInfo, kTrace, ""), \
+ F(ftrace_cpu_dropped_events_delta, kIndexed, kError, kTrace, ""), \
F(ftrace_cpu_entries_begin, kIndexed, kInfo, kTrace, ""), \
F(ftrace_cpu_entries_end, kIndexed, kInfo, kTrace, ""), \
+ F(ftrace_cpu_entries_delta, kIndexed, kInfo, kTrace, ""), \
F(ftrace_cpu_now_ts_begin, kIndexed, kInfo, kTrace, ""), \
F(ftrace_cpu_now_ts_end, kIndexed, kInfo, kTrace, ""), \
F(ftrace_cpu_oldest_event_ts_begin, kIndexed, kInfo, kTrace, ""), \
F(ftrace_cpu_oldest_event_ts_end, kIndexed, kInfo, kTrace, ""), \
F(ftrace_cpu_overrun_begin, kIndexed, kInfo, kTrace, ""), \
- F(ftrace_cpu_overrun_end, kIndexed, kDataLoss, kTrace, \
+ F(ftrace_cpu_overrun_end, kIndexed, kInfo, kTrace, ""), \
+ F(ftrace_cpu_overrun_delta, kIndexed, kDataLoss, kTrace, \
"The kernel ftrace buffer cannot keep up with the rate of events " \
"produced. Indexed by CPU. This is likely a misconfiguration."), \
F(ftrace_cpu_read_events_begin, kIndexed, kInfo, kTrace, ""), \
F(ftrace_cpu_read_events_end, kIndexed, kInfo, kTrace, ""), \
+ F(ftrace_cpu_read_events_delta, kIndexed, kInfo, kTrace, ""), \
F(fuchsia_non_numeric_counters, kSingle, kError, kAnalysis, ""), \
F(fuchsia_timestamp_overflow, kSingle, kError, kAnalysis, ""), \
F(fuchsia_invalid_event, kSingle, kError, kAnalysis, ""), \
diff --git a/src/trace_processor/storage/trace_storage.h b/src/trace_processor/storage/trace_storage.h
index f092c74..af98024 100644
--- a/src/trace_processor/storage/trace_storage.h
+++ b/src/trace_processor/storage/trace_storage.h
@@ -256,6 +256,17 @@
stats_[key].indexed_values[index] = value;
}
+ // Example usage: opt_cpu_failure = GetIndexedStats(stats::cpu_failure, 1);
+ base::Optional<int64_t> GetIndexedStats(size_t key, int index) {
+ PERFETTO_DCHECK(key < stats::kNumKeys);
+ PERFETTO_DCHECK(stats::kTypes[key] == stats::kIndexed);
+ auto kv = stats_[key].indexed_values.find(index);
+ if (kv != stats_[key].indexed_values.end()) {
+ return kv->second;
+ }
+ return base::nullopt;
+ }
+
class ScopedStatsTracer {
public:
ScopedStatsTracer(TraceStorage* storage, size_t key)
diff --git a/src/trace_processor/timestamped_trace_piece.h b/src/trace_processor/timestamped_trace_piece.h
index ca61546..1b1a0f6 100644
--- a/src/trace_processor/timestamped_trace_piece.h
+++ b/src/trace_processor/timestamped_trace_piece.h
@@ -77,9 +77,19 @@
std::array<double, kMaxNumExtraCounters> extra_counter_values = {};
};
+// On Windows std::aligned_storage was broken before VS 2017 15.8 and the
+// compiler (even clang-cl) requires -D_ENABLE_EXTENDED_ALIGNED_STORAGE. Given
+// the alignment here is purely a performance enhancment with no other
+// functional requirement, disable it on Win.
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#define PERFETTO_TTS_ALIGNMENT alignas(64)
+#else
+#define PERFETTO_TTS_ALIGNMENT
+#endif
+
// A TimestampedTracePiece is (usually a reference to) a piece of a trace that
// is sorted by TraceSorter.
-struct alignas(64) TimestampedTracePiece {
+struct PERFETTO_TTS_ALIGNMENT TimestampedTracePiece {
enum class Type {
kInvalid = 0,
kFtraceEvent,
diff --git a/src/tracing/test/api_test_support.cc b/src/tracing/test/api_test_support.cc
index 0142d28..a03135d 100644
--- a/src/tracing/test/api_test_support.cc
+++ b/src/tracing/test/api_test_support.cc
@@ -27,6 +27,10 @@
#include "test/test_helper.h"
#endif
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <Windows.h>
+#endif
+
namespace perfetto {
namespace test {
diff --git a/test/trace_processor/parsing/android_sched_and_ps_stats.out b/test/trace_processor/parsing/android_sched_and_ps_stats.out
index 4ff60f7..fcc2279 100644
--- a/test/trace_processor/parsing/android_sched_and_ps_stats.out
+++ b/test/trace_processor/parsing/android_sched_and_ps_stats.out
@@ -15,38 +15,62 @@
"ftrace_cpu_bytes_read_end",5,"info","trace",1188
"ftrace_cpu_bytes_read_end",6,"info","trace",1576
"ftrace_cpu_bytes_read_end",7,"info","trace",3264
-"ftrace_cpu_commit_overrun_begin",0,"error","trace",0
-"ftrace_cpu_commit_overrun_begin",1,"error","trace",0
-"ftrace_cpu_commit_overrun_begin",2,"error","trace",0
-"ftrace_cpu_commit_overrun_begin",3,"error","trace",0
-"ftrace_cpu_commit_overrun_begin",4,"error","trace",0
-"ftrace_cpu_commit_overrun_begin",5,"error","trace",0
-"ftrace_cpu_commit_overrun_begin",6,"error","trace",0
-"ftrace_cpu_commit_overrun_begin",7,"error","trace",0
-"ftrace_cpu_commit_overrun_end",0,"error","trace",0
-"ftrace_cpu_commit_overrun_end",1,"error","trace",0
-"ftrace_cpu_commit_overrun_end",2,"error","trace",0
-"ftrace_cpu_commit_overrun_end",3,"error","trace",0
-"ftrace_cpu_commit_overrun_end",4,"error","trace",0
-"ftrace_cpu_commit_overrun_end",5,"error","trace",0
-"ftrace_cpu_commit_overrun_end",6,"error","trace",0
-"ftrace_cpu_commit_overrun_end",7,"error","trace",0
-"ftrace_cpu_dropped_events_begin",0,"error","trace",0
-"ftrace_cpu_dropped_events_begin",1,"error","trace",0
-"ftrace_cpu_dropped_events_begin",2,"error","trace",0
-"ftrace_cpu_dropped_events_begin",3,"error","trace",0
-"ftrace_cpu_dropped_events_begin",4,"error","trace",0
-"ftrace_cpu_dropped_events_begin",5,"error","trace",0
-"ftrace_cpu_dropped_events_begin",6,"error","trace",0
-"ftrace_cpu_dropped_events_begin",7,"error","trace",0
-"ftrace_cpu_dropped_events_end",0,"error","trace",0
-"ftrace_cpu_dropped_events_end",1,"error","trace",0
-"ftrace_cpu_dropped_events_end",2,"error","trace",0
-"ftrace_cpu_dropped_events_end",3,"error","trace",0
-"ftrace_cpu_dropped_events_end",4,"error","trace",0
-"ftrace_cpu_dropped_events_end",5,"error","trace",0
-"ftrace_cpu_dropped_events_end",6,"error","trace",0
-"ftrace_cpu_dropped_events_end",7,"error","trace",0
+"ftrace_cpu_bytes_read_delta",0,"info","trace",20236
+"ftrace_cpu_bytes_read_delta",1,"info","trace",11380
+"ftrace_cpu_bytes_read_delta",2,"info","trace",12336
+"ftrace_cpu_bytes_read_delta",3,"info","trace",6236
+"ftrace_cpu_bytes_read_delta",4,"info","trace",2676
+"ftrace_cpu_bytes_read_delta",5,"info","trace",1188
+"ftrace_cpu_bytes_read_delta",6,"info","trace",1576
+"ftrace_cpu_bytes_read_delta",7,"info","trace",3264
+"ftrace_cpu_commit_overrun_begin",0,"info","trace",0
+"ftrace_cpu_commit_overrun_begin",1,"info","trace",0
+"ftrace_cpu_commit_overrun_begin",2,"info","trace",0
+"ftrace_cpu_commit_overrun_begin",3,"info","trace",0
+"ftrace_cpu_commit_overrun_begin",4,"info","trace",0
+"ftrace_cpu_commit_overrun_begin",5,"info","trace",0
+"ftrace_cpu_commit_overrun_begin",6,"info","trace",0
+"ftrace_cpu_commit_overrun_begin",7,"info","trace",0
+"ftrace_cpu_commit_overrun_end",0,"info","trace",0
+"ftrace_cpu_commit_overrun_end",1,"info","trace",0
+"ftrace_cpu_commit_overrun_end",2,"info","trace",0
+"ftrace_cpu_commit_overrun_end",3,"info","trace",0
+"ftrace_cpu_commit_overrun_end",4,"info","trace",0
+"ftrace_cpu_commit_overrun_end",5,"info","trace",0
+"ftrace_cpu_commit_overrun_end",6,"info","trace",0
+"ftrace_cpu_commit_overrun_end",7,"info","trace",0
+"ftrace_cpu_commit_overrun_delta",0,"error","trace",0
+"ftrace_cpu_commit_overrun_delta",1,"error","trace",0
+"ftrace_cpu_commit_overrun_delta",2,"error","trace",0
+"ftrace_cpu_commit_overrun_delta",3,"error","trace",0
+"ftrace_cpu_commit_overrun_delta",4,"error","trace",0
+"ftrace_cpu_commit_overrun_delta",5,"error","trace",0
+"ftrace_cpu_commit_overrun_delta",6,"error","trace",0
+"ftrace_cpu_commit_overrun_delta",7,"error","trace",0
+"ftrace_cpu_dropped_events_begin",0,"info","trace",0
+"ftrace_cpu_dropped_events_begin",1,"info","trace",0
+"ftrace_cpu_dropped_events_begin",2,"info","trace",0
+"ftrace_cpu_dropped_events_begin",3,"info","trace",0
+"ftrace_cpu_dropped_events_begin",4,"info","trace",0
+"ftrace_cpu_dropped_events_begin",5,"info","trace",0
+"ftrace_cpu_dropped_events_begin",6,"info","trace",0
+"ftrace_cpu_dropped_events_begin",7,"info","trace",0
+"ftrace_cpu_dropped_events_end",0,"info","trace",0
+"ftrace_cpu_dropped_events_end",1,"info","trace",0
+"ftrace_cpu_dropped_events_end",2,"info","trace",0
+"ftrace_cpu_dropped_events_end",3,"info","trace",0
+"ftrace_cpu_dropped_events_end",4,"info","trace",0
+"ftrace_cpu_dropped_events_end",5,"info","trace",0
+"ftrace_cpu_dropped_events_end",6,"info","trace",0
+"ftrace_cpu_dropped_events_end",7,"info","trace",0
+"ftrace_cpu_dropped_events_delta",0,"error","trace",0
+"ftrace_cpu_dropped_events_delta",1,"error","trace",0
+"ftrace_cpu_dropped_events_delta",2,"error","trace",0
+"ftrace_cpu_dropped_events_delta",3,"error","trace",0
+"ftrace_cpu_dropped_events_delta",4,"error","trace",0
+"ftrace_cpu_dropped_events_delta",5,"error","trace",0
+"ftrace_cpu_dropped_events_delta",6,"error","trace",0
+"ftrace_cpu_dropped_events_delta",7,"error","trace",0
"ftrace_cpu_entries_begin",0,"info","trace",4
"ftrace_cpu_entries_begin",1,"info","trace",4
"ftrace_cpu_entries_begin",2,"info","trace",23
@@ -63,6 +87,14 @@
"ftrace_cpu_entries_end",5,"info","trace",21
"ftrace_cpu_entries_end",6,"info","trace",26
"ftrace_cpu_entries_end",7,"info","trace",54
+"ftrace_cpu_entries_delta",0,"info","trace",337
+"ftrace_cpu_entries_delta",1,"info","trace",191
+"ftrace_cpu_entries_delta",2,"info","trace",202
+"ftrace_cpu_entries_delta",3,"info","trace",107
+"ftrace_cpu_entries_delta",4,"info","trace",45
+"ftrace_cpu_entries_delta",5,"info","trace",21
+"ftrace_cpu_entries_delta",6,"info","trace",26
+"ftrace_cpu_entries_delta",7,"info","trace",54
"ftrace_cpu_now_ts_begin",0,"info","trace",81473010735000
"ftrace_cpu_now_ts_begin",1,"info","trace",81473010800000
"ftrace_cpu_now_ts_begin",2,"info","trace",81473010839000
@@ -103,14 +135,22 @@
"ftrace_cpu_overrun_begin",5,"info","trace",0
"ftrace_cpu_overrun_begin",6,"info","trace",0
"ftrace_cpu_overrun_begin",7,"info","trace",0
-"ftrace_cpu_overrun_end",0,"data_loss","trace",0
-"ftrace_cpu_overrun_end",1,"data_loss","trace",0
-"ftrace_cpu_overrun_end",2,"data_loss","trace",0
-"ftrace_cpu_overrun_end",3,"data_loss","trace",0
-"ftrace_cpu_overrun_end",4,"data_loss","trace",0
-"ftrace_cpu_overrun_end",5,"data_loss","trace",0
-"ftrace_cpu_overrun_end",6,"data_loss","trace",0
-"ftrace_cpu_overrun_end",7,"data_loss","trace",0
+"ftrace_cpu_overrun_end",0,"info","trace",0
+"ftrace_cpu_overrun_end",1,"info","trace",0
+"ftrace_cpu_overrun_end",2,"info","trace",0
+"ftrace_cpu_overrun_end",3,"info","trace",0
+"ftrace_cpu_overrun_end",4,"info","trace",0
+"ftrace_cpu_overrun_end",5,"info","trace",0
+"ftrace_cpu_overrun_end",6,"info","trace",0
+"ftrace_cpu_overrun_end",7,"info","trace",0
+"ftrace_cpu_overrun_delta",0,"data_loss","trace",0
+"ftrace_cpu_overrun_delta",1,"data_loss","trace",0
+"ftrace_cpu_overrun_delta",2,"data_loss","trace",0
+"ftrace_cpu_overrun_delta",3,"data_loss","trace",0
+"ftrace_cpu_overrun_delta",4,"data_loss","trace",0
+"ftrace_cpu_overrun_delta",5,"data_loss","trace",0
+"ftrace_cpu_overrun_delta",6,"data_loss","trace",0
+"ftrace_cpu_overrun_delta",7,"data_loss","trace",0
"ftrace_cpu_read_events_begin",0,"info","trace",0
"ftrace_cpu_read_events_begin",1,"info","trace",0
"ftrace_cpu_read_events_begin",2,"info","trace",0
@@ -127,6 +167,14 @@
"ftrace_cpu_read_events_end",5,"info","trace",23232
"ftrace_cpu_read_events_end",6,"info","trace",36733
"ftrace_cpu_read_events_end",7,"info","trace",39240
+"ftrace_cpu_read_events_delta",0,"info","trace",62303
+"ftrace_cpu_read_events_delta",1,"info","trace",54916
+"ftrace_cpu_read_events_delta",2,"info","trace",55882
+"ftrace_cpu_read_events_delta",3,"info","trace",47953
+"ftrace_cpu_read_events_delta",4,"info","trace",31345
+"ftrace_cpu_read_events_delta",5,"info","trace",23232
+"ftrace_cpu_read_events_delta",6,"info","trace",36733
+"ftrace_cpu_read_events_delta",7,"info","trace",39240
"traced_buf_buffer_size",0,"info","trace",0
"traced_buf_bytes_overwritten",0,"info","trace",0
"traced_buf_bytes_read",0,"info","trace",0
diff --git a/test/trace_processor/startup/android_startup.out b/test/trace_processor/startup/android_startup.out
index a7dd383..5d323e4 100644
--- a/test/trace_processor/startup/android_startup.out
+++ b/test/trace_processor/startup/android_startup.out
@@ -18,12 +18,12 @@
}
}
zygote_new_process: false
- activity_hosting_process_count: 2
+ activity_hosting_process_count: 1
to_first_frame {
dur_ns: 108
main_thread_by_task_state {
- running_dur_ns: 41
- runnable_dur_ns: 129
+ running_dur_ns: 10
+ runnable_dur_ns: 80
uninterruptible_sleep_dur_ns: 0
interruptible_sleep_dur_ns: 10
}
@@ -34,6 +34,10 @@
}
mcycles_by_core_type {
}
+ time_activity_start {
+ dur_ns: 2
+ dur_ms: 2e-06
+ }
dur_ms: 0.000108
}
report_fully_drawn {
diff --git a/test/trace_processor/startup/android_startup.py b/test/trace_processor/startup/android_startup.py
index 494849c..c5f0e37 100644
--- a/test/trace_processor/startup/android_startup.py
+++ b/test/trace_processor/startup/android_startup.py
@@ -22,7 +22,7 @@
trace.add_process(1, 0, 'init')
trace.add_process(2, 1, 'system_server')
trace.add_process(3, 1, 'com.google.android.calendar', 10001)
-trace.add_process(4, 1, 'com.google.android.calendar')
+trace.add_process(4, 3, 'com.google.android.calendar', 10001)
trace.add_package_list(
ts=1, name='com.google.android.calendar', uid=10001, version_code=123)
@@ -42,6 +42,13 @@
ts=110, tid=2, pid=2, buf='launching: com.google.android.calendar')
trace.add_sched(ts=110, prev_pid=0, next_pid=3)
+
+# As the process already existed before intent started, this is a
+# warm/hot start (we choose warm). Therefore, emit an activityStart
+# slice.
+trace.add_atrace_begin(ts=115, tid=3, pid=3, buf='activityStart')
+trace.add_atrace_end(ts=117, tid=3, pid=3)
+
# P1: 10ns running
trace.add_sched(ts=120, prev_pid=3, next_pid=0, prev_state='S')
# P1: 10ns sleep
diff --git a/test/trace_processor/startup/android_startup_attribution.out b/test/trace_processor/startup/android_startup_attribution.out
index 87b1a30..3c74145 100644
--- a/test/trace_processor/startup/android_startup_attribution.out
+++ b/test/trace_processor/startup/android_startup_attribution.out
@@ -17,6 +17,10 @@
dur_ns: 2
dur_ms: 2e-06
}
+ time_activity_resume {
+ dur_ns: 5
+ dur_ms: 5e-06
+ }
dur_ms: 999.9999
time_dex_open {
dur_ns: 20
diff --git a/test/trace_processor/startup/android_startup_attribution.py b/test/trace_processor/startup/android_startup_attribution.py
index cf3ab8e..2f8a4be 100644
--- a/test/trace_processor/startup/android_startup_attribution.py
+++ b/test/trace_processor/startup/android_startup_attribution.py
@@ -18,7 +18,7 @@
import synth_common
APP_PID = 3
-APP_TID = 1
+APP_TID = APP_PID
SECOND_APP_TID = 3
JIT_TID = 4
GC_TID = 5
@@ -65,6 +65,10 @@
tid=SYSTEM_SERVER_TID,
buf='launching: com.some.app')
+# Emulate a hot start (and therefore that we only see activityResume).
+trace.add_atrace_begin(ts=125, tid=APP_TID, pid=APP_PID, buf='activityResume')
+trace.add_atrace_end(ts=130, tid=APP_TID, pid=APP_PID)
+
# OpenDex slices within the startup.
trace.add_atrace_begin(
ts=150, pid=APP_PID, tid=APP_TID, buf='OpenDexFilesFromOat(something)')
diff --git a/test/trace_processor/startup/android_startup_process_track.out b/test/trace_processor/startup/android_startup_process_track.out
index 357603d..7a8ae0f 100644
--- a/test/trace_processor/startup/android_startup_process_track.out
+++ b/test/trace_processor/startup/android_startup_process_track.out
@@ -8,7 +8,7 @@
}
zygote_new_process: false
to_first_frame {
- dur_ns: 4
+ dur_ns: 5
main_thread_by_task_state {
running_dur_ns: 0
runnable_dur_ns: 0
@@ -22,11 +22,19 @@
}
mcycles_by_core_type {
}
- dur_ms: 4e-06
+ time_bind_application {
+ dur_ns: 1
+ dur_ms: 1e-06
+ }
+ dur_ms: 5e-06
+ to_bind_application {
+ dur_ns: 3
+ dur_ms: 3e-06
+ }
}
event_timestamps {
intent_received: 100
- first_frame: 104
+ first_frame: 105
}
activity_hosting_process_count: 1
}
@@ -39,7 +47,7 @@
}
zygote_new_process: false
to_first_frame {
- dur_ns: 4
+ dur_ns: 5
main_thread_by_task_state {
running_dur_ns: 0
runnable_dur_ns: 0
@@ -53,11 +61,19 @@
}
mcycles_by_core_type {
}
- dur_ms: 4e-06
+ time_bind_application {
+ dur_ns: 1
+ dur_ms: 1e-06
+ }
+ dur_ms: 5e-06
+ to_bind_application {
+ dur_ns: 3
+ dur_ms: 3e-06
+ }
}
event_timestamps {
intent_received: 200
- first_frame: 204
+ first_frame: 205
}
activity_hosting_process_count: 1
}
diff --git a/test/trace_processor/startup/android_startup_process_track.py b/test/trace_processor/startup/android_startup_process_track.py
index a9696ad..07fcf92 100644
--- a/test/trace_processor/startup/android_startup_process_track.py
+++ b/test/trace_processor/startup/android_startup_process_track.py
@@ -34,10 +34,12 @@
new_tid=pid,
new_comm='com.google.android.calendar',
flags=0)
+ trace.add_atrace_begin(ts=ts + 3, tid=pid, pid=pid, buf='bindApplication')
+ trace.add_atrace_end(ts=ts + 4, tid=pid, pid=pid)
trace.add_atrace_async_end(
- ts=ts + 4, tid=2, pid=2, buf='launching: com.google.android.calendar')
+ ts=ts + 5, tid=2, pid=2, buf='launching: com.google.android.calendar')
trace.add_atrace_begin(
- ts=ts + 5,
+ ts=ts + 6,
tid=2,
pid=2,
buf='MetricsLogger:launchObserverNotifyActivityLaunchFinished')
diff --git a/tools/gen_amalgamated_sql_metrics.py b/tools/gen_amalgamated_sql_metrics.py
index eed5d8e..16f6aac 100755
--- a/tools/gen_amalgamated_sql_metrics.py
+++ b/tools/gen_amalgamated_sql_metrics.py
@@ -85,7 +85,7 @@
with open(file_name, 'r') as f:
relpath = os.path.relpath(file_name, root_path)
sql_outputs[relpath] = "".join(
- x for x in f.readlines() if not x.startswith('--'))
+ x.lstrip() for x in f.readlines() if not x.lstrip().startswith('--'))
with open(args.cpp_out, 'w+') as output:
output.write(REPLACEMENT_HEADER)
diff --git a/tools/test_data b/tools/test_data
index cf8ae14..7dd8975 100755
--- a/tools/test_data
+++ b/tools/test_data
@@ -141,7 +141,7 @@
subprocess.check_call(cmd)
with open(fs.path + SUFFIX + '.swp', 'w') as f:
f.write(fs.actual_digest)
- os.rename(fs.path + SUFFIX + '.swp', fs.path + SUFFIX)
+ os.replace(fs.path + SUFFIX + '.swp', fs.path + SUFFIX)
return fs
map_concurrently(upload_one_file, files_to_upload)
@@ -194,7 +194,7 @@
if digest != fs.expected_digest:
raise Exception('Mismatching digest for %s. expected=%s, actual=%s' %
(uri, fs.expected_digest, digest))
- os.rename(tmp_path, fs.path)
+ os.replace(tmp_path, fs.path)
return fs
map_concurrently(download_one_file, files_to_download)