Remove reached code profiler for Android
This was built to test if the code profiles from the field is better than profiles built using benchmarks. This was never prioritized and remained dead for many years. This CL removes reached code profiler. Bug: 1385901 Change-Id: Ieee9cf27ee5c0f10d4c9715223e91b87bb76e475 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5137037 Reviewed-by: Lei Zhang <thestig@chromium.org> Reviewed-by: Siddhartha S <ssid@chromium.org> Reviewed-by: Egor Pasko <pasko@chromium.org> Commit-Queue: Siddhartha S <ssid@chromium.org> Reviewed-by: Tommy Nyquist <nyquist@chromium.org> Cr-Commit-Position: refs/heads/main@{#1246559}
This commit is contained in:
base
BUILD.gnreached_addresses_bitset.ccreached_addresses_bitset.hreached_addresses_bitset_unittest.ccreached_code_profiler.ccreached_code_profiler.hreached_code_profiler_stub.ccbase_switches.ccbase_switches.h
android
java
src
org
chromium
base
library_loader
test
chrome
android
browser
android
chrome_browser_field_trials.ccflags
android
preferences
android
java
src
org
chromium
chrome
content
app
android
browser
services/tracing/public/mojom
@ -1198,10 +1198,6 @@ component("base") {
|
||||
"android/pre_freeze_background_memory_trimmer.h",
|
||||
"android/radio_utils.cc",
|
||||
"android/radio_utils.h",
|
||||
"android/reached_addresses_bitset.cc",
|
||||
"android/reached_addresses_bitset.h",
|
||||
"android/reached_code_profiler.cc",
|
||||
"android/reached_code_profiler.h",
|
||||
"android/scoped_hardware_buffer_fence_sync.cc",
|
||||
"android/scoped_hardware_buffer_fence_sync.h",
|
||||
"android/scoped_hardware_buffer_handle.cc",
|
||||
@ -1285,12 +1281,6 @@ component("base") {
|
||||
]
|
||||
}
|
||||
|
||||
if (current_cpu != "arm" && current_cpu != "arm64") {
|
||||
# The reached code profiler is only supported on Android arm arch.
|
||||
sources -= [ "android/reached_code_profiler.cc" ]
|
||||
sources += [ "android/reached_code_profiler_stub.cc" ]
|
||||
}
|
||||
|
||||
# This is actually a linker script, but it can be added to the link in the
|
||||
# same way as a library.
|
||||
libs += [ "android/library_loader/anchor_functions.lds" ]
|
||||
@ -3724,7 +3714,6 @@ test("base_unittests") {
|
||||
"android/path_utils_unittest.cc",
|
||||
"android/pre_freeze_background_memory_trimmer_unittest.cc",
|
||||
"android/radio_utils_unittest.cc",
|
||||
"android/reached_addresses_bitset_unittest.cc",
|
||||
"android/scoped_java_ref_unittest.cc",
|
||||
"android/sys_utils_unittest.cc",
|
||||
"android/unguessable_token_android_unittest.cc",
|
||||
|
@ -61,19 +61,10 @@ public class LibraryLoader {
|
||||
// Constant guarding debug logging in this class.
|
||||
static final boolean DEBUG = false;
|
||||
|
||||
// Shared preferences key for the reached code profiler.
|
||||
private static final String DEPRECATED_REACHED_CODE_PROFILER_KEY =
|
||||
"reached_code_profiler_enabled";
|
||||
private static final String REACHED_CODE_SAMPLING_INTERVAL_KEY =
|
||||
"reached_code_sampling_interval";
|
||||
|
||||
// Compile time switch for sharing RELRO between the browser and the app zygote.
|
||||
// TODO(crbug.com/1154224): remove when the issue is closed.
|
||||
private static final boolean ALLOW_CHROMIUM_LINKER_IN_ZYGOTE = true;
|
||||
|
||||
// Default sampling interval for reached code profiler in microseconds.
|
||||
private static final int DEFAULT_REACHED_CODE_SAMPLING_INTERVAL_US = 10000;
|
||||
|
||||
// Shared preferences key for the background thread pool setting.
|
||||
private static final String BACKGROUND_THREAD_POOL_KEY = "background_thread_pool_enabled";
|
||||
|
||||
@ -674,46 +665,6 @@ public class LibraryLoader {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the reached code profiler. The value comes from "ReachedCodeProfiler"
|
||||
* finch experiment, and is pushed on every run. I.e. the effect of the finch experiment
|
||||
* lags by one run, which is the best we can do considering that the profiler has to be enabled
|
||||
* before finch is initialized. Note that since LibraryLoader is in //base, it can't depend
|
||||
* on ChromeFeatureList, and has to rely on external code pushing the value.
|
||||
*
|
||||
* @param enabled whether to enable the reached code profiler.
|
||||
* @param samplingIntervalUs the sampling interval for reached code profiler.
|
||||
*/
|
||||
public static void setReachedCodeProfilerEnabledOnNextRuns(
|
||||
boolean enabled, int samplingIntervalUs) {
|
||||
// Store 0 if the profiler is not enabled, otherwise store the sampling interval in
|
||||
// microseconds.
|
||||
if (enabled && samplingIntervalUs == 0) {
|
||||
samplingIntervalUs = DEFAULT_REACHED_CODE_SAMPLING_INTERVAL_US;
|
||||
} else if (!enabled) {
|
||||
samplingIntervalUs = 0;
|
||||
}
|
||||
SharedPreferences.Editor editor = ContextUtils.getAppSharedPreferences().edit();
|
||||
editor.remove(DEPRECATED_REACHED_CODE_PROFILER_KEY);
|
||||
editor.putInt(REACHED_CODE_SAMPLING_INTERVAL_KEY, samplingIntervalUs).apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return sampling interval for reached code profiler, or 0 when the profiler is disabled. (see
|
||||
* setReachedCodeProfilerEnabledOnNextRuns()).
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static int getReachedCodeSamplingIntervalUs() {
|
||||
try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
|
||||
if (ContextUtils.getAppSharedPreferences()
|
||||
.getBoolean(DEPRECATED_REACHED_CODE_PROFILER_KEY, false)) {
|
||||
return DEFAULT_REACHED_CODE_SAMPLING_INTERVAL_US;
|
||||
}
|
||||
return ContextUtils.getAppSharedPreferences()
|
||||
.getInt(REACHED_CODE_SAMPLING_INTERVAL_KEY, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the background priority thread pool group. The value comes from the
|
||||
* "BackgroundThreadPool" finch experiment, and is pushed on every run, to take effect on the
|
||||
@ -864,19 +815,7 @@ public class LibraryLoader {
|
||||
assert mLibraryProcessType != LibraryProcessType.PROCESS_UNINITIALIZED;
|
||||
|
||||
if (mLibraryProcessType == LibraryProcessType.PROCESS_BROWSER) {
|
||||
// Add a switch for the reached code profiler as late as possible since it requires a
|
||||
// read from the shared preferences. At this point the shared preferences are usually
|
||||
// warmed up.
|
||||
int reachedCodeSamplingIntervalUs = getReachedCodeSamplingIntervalUs();
|
||||
if (reachedCodeSamplingIntervalUs > 0) {
|
||||
CommandLine.getInstance().appendSwitch(BaseSwitches.ENABLE_REACHED_CODE_PROFILER);
|
||||
CommandLine.getInstance()
|
||||
.appendSwitchWithValue(
|
||||
BaseSwitches.REACHED_CODE_SAMPLING_INTERVAL_US,
|
||||
Integer.toString(reachedCodeSamplingIntervalUs));
|
||||
}
|
||||
|
||||
// Similarly, append a switch to enable the background thread pool group if the cached
|
||||
// Append a switch to enable the background thread pool group if the cached
|
||||
// preference indicates it should be enabled.
|
||||
if (isBackgroundThreadPoolEnabled()) {
|
||||
CommandLine.getInstance().appendSwitch(BaseSwitches.ENABLE_BACKGROUND_THREAD_POOL);
|
||||
|
@ -1,118 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/android/reached_addresses_bitset.h"
|
||||
|
||||
#include "base/android/library_loader/anchor_functions.h"
|
||||
#include "base/android/library_loader/anchor_functions_buildflags.h"
|
||||
#include "base/check_op.h"
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
|
||||
namespace base {
|
||||
namespace android {
|
||||
|
||||
namespace {
|
||||
constexpr size_t kBitsPerElement = sizeof(uint32_t) * 8;
|
||||
|
||||
// Below an array of uint32_t in BSS is introduced and then casted to an array
|
||||
// of std::atomic<uint32_t>. In C++20 constructing an std::atomic is not
|
||||
// 'trivial'. See https://github.com/microsoft/STL/issues/661 for reasons of
|
||||
// this change in the standard.
|
||||
//
|
||||
// Assert that both types have the same size. The sizes do not have to match
|
||||
// according to a note in [atomics.types.generic] in C++17. With this assertion
|
||||
// in place it is unlikely that the constructor produces the value other than
|
||||
// (uint32_t)0.
|
||||
static_assert(sizeof(uint32_t) == sizeof(std::atomic<uint32_t>), "");
|
||||
|
||||
// Keep the array in BSS only for non-official builds to avoid potential harm to
|
||||
// data locality and unspecified behavior from the reinterpret_cast below.
|
||||
// In order to start new experiments with base::Feature(ReachedCodeProfiler) on
|
||||
// Canary/Dev this array will need to be reintroduced to official builds. When
|
||||
// doing so, don't forget to update `kConfigurationSupported` in
|
||||
// `reached_code_profiler.cc`
|
||||
#if BUILDFLAG(SUPPORTS_CODE_ORDERING) && !defined(OFFICIAL_BUILD)
|
||||
// Enough for 1 << 29 bytes of code, 512MB.
|
||||
constexpr size_t kTextBitfieldSize = 1 << 20;
|
||||
uint32_t g_text_bitfield[kTextBitfieldSize];
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
ReachedAddressesBitset* ReachedAddressesBitset::GetTextBitset() {
|
||||
#if BUILDFLAG(SUPPORTS_CODE_ORDERING) && !defined(OFFICIAL_BUILD)
|
||||
static ReachedAddressesBitset text_bitset(
|
||||
kStartOfText, kEndOfText,
|
||||
reinterpret_cast<std::atomic<uint32_t>*>(g_text_bitfield),
|
||||
kTextBitfieldSize);
|
||||
return &text_bitset;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ReachedAddressesBitset::RecordAddress(uintptr_t address) {
|
||||
// |address| is outside of the range.
|
||||
if (address < start_address_ || address >= end_address_)
|
||||
return;
|
||||
|
||||
size_t offset = static_cast<size_t>(address - start_address_);
|
||||
uint32_t offset_index = checked_cast<uint32_t>(offset / kBytesGranularity);
|
||||
|
||||
// Atomically set the corresponding bit in the array.
|
||||
std::atomic<uint32_t>* element = reached_ + (offset_index / kBitsPerElement);
|
||||
|
||||
// First, a racy check. This saves a CAS if the bit is already set, and
|
||||
// allows the cache line to remain shared across CPUs in this case.
|
||||
uint32_t value = element->load(std::memory_order_relaxed);
|
||||
uint32_t mask = 1 << (offset_index % kBitsPerElement);
|
||||
if (value & mask)
|
||||
return;
|
||||
element->fetch_or(mask, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> ReachedAddressesBitset::GetReachedOffsets() const {
|
||||
std::vector<uint32_t> offsets;
|
||||
const size_t elements = NumberOfReachableElements();
|
||||
|
||||
for (size_t i = 0; i < elements; ++i) {
|
||||
uint32_t element = reached_[i].load(std::memory_order_relaxed);
|
||||
// No reached addresses at this element.
|
||||
if (element == 0)
|
||||
continue;
|
||||
|
||||
for (size_t j = 0; j < 32; ++j) {
|
||||
if (!((element >> j) & 1))
|
||||
continue;
|
||||
|
||||
size_t offset_index = i * 32 + j;
|
||||
size_t offset = offset_index * kBytesGranularity;
|
||||
offsets.push_back(checked_cast<uint32_t>(offset));
|
||||
}
|
||||
}
|
||||
|
||||
return offsets;
|
||||
}
|
||||
|
||||
ReachedAddressesBitset::ReachedAddressesBitset(
|
||||
uintptr_t start_address,
|
||||
uintptr_t end_address,
|
||||
std::atomic<uint32_t>* storage_ptr,
|
||||
size_t storage_size)
|
||||
: start_address_(start_address),
|
||||
end_address_(end_address),
|
||||
reached_(storage_ptr) {
|
||||
DCHECK_LE(start_address_, end_address_);
|
||||
DCHECK_LE(NumberOfReachableElements(), storage_size * kBitsPerElement);
|
||||
}
|
||||
|
||||
size_t ReachedAddressesBitset::NumberOfReachableElements() const {
|
||||
size_t reachable_bits =
|
||||
(end_address_ + kBytesGranularity - 1) / kBytesGranularity -
|
||||
start_address_ / kBytesGranularity;
|
||||
return (reachable_bits + kBitsPerElement - 1) / kBitsPerElement;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace base
|
@ -1,76 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_ANDROID_REACHED_ADDRESSES_BITSET_H_
|
||||
#define BASE_ANDROID_REACHED_ADDRESSES_BITSET_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
|
||||
#include "base/base_export.h"
|
||||
#include "base/memory/raw_ptr_exclusion.h"
|
||||
#include "base/no_destructor.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
namespace android {
|
||||
|
||||
// ReachedAddressesBitset is a set that stores addresses for the
|
||||
// ReachedCodeProfiler in compact form. Its main features are lock-free
|
||||
// thread-safety and fast adding of elements.
|
||||
//
|
||||
// The addresses are kept with |kBytesGranularity| to save the storage space.
|
||||
//
|
||||
// Once insterted, elements cannot be erased from the set.
|
||||
//
|
||||
// All methods can be called from any thread.
|
||||
class BASE_EXPORT ReachedAddressesBitset {
|
||||
public:
|
||||
// Returns an instance of ReachedAddressesBitset having enough storage space
|
||||
// to keep all addresses from the .text section.
|
||||
// Returns nullptr if SUPPORTS_CODE_ORDERING isn't defined.
|
||||
// This instance is stored in the .bss section of the binary, meaning that it
|
||||
// doesn't incur the binary size overhead and it doesn't increase the resident
|
||||
// memory footprint when not used.
|
||||
static ReachedAddressesBitset* GetTextBitset();
|
||||
|
||||
// Inserts |address| into the bitset iff |address| lies in the range between
|
||||
// |start_address_| and |end_address_|.
|
||||
void RecordAddress(uintptr_t address);
|
||||
|
||||
// Returns a list of recorded addresses in the form of offsets from
|
||||
// |start_address_|.
|
||||
std::vector<uint32_t> GetReachedOffsets() const;
|
||||
|
||||
private:
|
||||
friend class ReachedAddressesBitsetTest;
|
||||
friend class NoDestructor<ReachedAddressesBitset>;
|
||||
|
||||
// Represents the number of bytes that are mapped into the same bit in the
|
||||
// bitset.
|
||||
static constexpr size_t kBytesGranularity = 4;
|
||||
|
||||
// Constructs a ReachedAddressesBitset on top of an external storage of
|
||||
// |storage_size| pointed by |storage_ptr|. This external storage must outlive
|
||||
// the constructed bitset instance. The size of storage must be large enough
|
||||
// to fit all addresses in the range between |start_address| and
|
||||
// |end_address|.
|
||||
ReachedAddressesBitset(uintptr_t start_address,
|
||||
uintptr_t end_address,
|
||||
std::atomic<uint32_t>* storage_ptr,
|
||||
size_t storage_size);
|
||||
|
||||
size_t NumberOfReachableElements() const;
|
||||
|
||||
uintptr_t start_address_;
|
||||
uintptr_t end_address_;
|
||||
// This field is not a raw_ptr<> because the rewriter couldn't handle the
|
||||
// global variable in a build configuration specific code.
|
||||
RAW_PTR_EXCLUSION std::atomic<uint32_t>* reached_;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_ANDROID_REACHED_ADDRESSES_BITSET_H_
|
@ -1,78 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/android/reached_addresses_bitset.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace base {
|
||||
namespace android {
|
||||
|
||||
using testing::ElementsAre;
|
||||
using testing::ElementsAreArray;
|
||||
|
||||
constexpr uintptr_t kStartAddress = 0x1000;
|
||||
constexpr uintptr_t kEndAddress = 0x2000;
|
||||
constexpr size_t kStorageSize = 512;
|
||||
|
||||
class ReachedAddressesBitsetTest : public testing::Test {
|
||||
public:
|
||||
ReachedAddressesBitsetTest()
|
||||
: bitset_(kStartAddress, kEndAddress, storage_, kStorageSize) {
|
||||
memset(storage_, 0, kStorageSize * sizeof(uint32_t));
|
||||
EXPECT_TRUE(bitset()->GetReachedOffsets().empty());
|
||||
}
|
||||
|
||||
ReachedAddressesBitset* bitset() { return &bitset_; }
|
||||
|
||||
private:
|
||||
std::atomic<uint32_t> storage_[kStorageSize];
|
||||
ReachedAddressesBitset bitset_;
|
||||
};
|
||||
|
||||
TEST_F(ReachedAddressesBitsetTest, RecordStartAddress) {
|
||||
bitset()->RecordAddress(kStartAddress);
|
||||
EXPECT_THAT(bitset()->GetReachedOffsets(), ElementsAre(0));
|
||||
}
|
||||
|
||||
TEST_F(ReachedAddressesBitsetTest, RecordLastAddress) {
|
||||
bitset()->RecordAddress(kEndAddress - 4);
|
||||
EXPECT_THAT(bitset()->GetReachedOffsets(),
|
||||
ElementsAre(kEndAddress - 4 - kStartAddress));
|
||||
}
|
||||
|
||||
TEST_F(ReachedAddressesBitsetTest, RecordAddressOutsideOfRange_Small) {
|
||||
bitset()->RecordAddress(kStartAddress - 4);
|
||||
EXPECT_THAT(bitset()->GetReachedOffsets(), ElementsAre());
|
||||
}
|
||||
|
||||
TEST_F(ReachedAddressesBitsetTest, RecordAddressOutsideOfRange_Large) {
|
||||
bitset()->RecordAddress(kEndAddress);
|
||||
EXPECT_THAT(bitset()->GetReachedOffsets(), ElementsAre());
|
||||
}
|
||||
|
||||
TEST_F(ReachedAddressesBitsetTest, RecordUnalignedAddresses) {
|
||||
constexpr uint32_t aligned_offset = 0x100;
|
||||
bitset()->RecordAddress(kStartAddress + aligned_offset + 1);
|
||||
bitset()->RecordAddress(kStartAddress + aligned_offset + 2);
|
||||
bitset()->RecordAddress(kStartAddress + aligned_offset + 3);
|
||||
EXPECT_THAT(bitset()->GetReachedOffsets(), ElementsAre(aligned_offset));
|
||||
}
|
||||
|
||||
TEST_F(ReachedAddressesBitsetTest, FillBitsetOneByOne) {
|
||||
std::vector<uint32_t> expected_offsets;
|
||||
for (uintptr_t address = kStartAddress; address < kEndAddress; address += 4) {
|
||||
bitset()->RecordAddress(address);
|
||||
expected_offsets.push_back(address - kStartAddress);
|
||||
ASSERT_THAT(bitset()->GetReachedOffsets(),
|
||||
ElementsAreArray(expected_offsets))
|
||||
<< "Last added: " << address;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace base
|
@ -1,303 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/android/reached_code_profiler.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <ucontext.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "base/android/library_loader/anchor_functions.h"
|
||||
#include "base/android/orderfile/orderfile_buildflags.h"
|
||||
#include "base/android/reached_addresses_bitset.h"
|
||||
#include "base/base_switches.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/feature_list.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/files/important_file_writer.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/linux_util.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/scoped_generic.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "base/threading/thread.h"
|
||||
#include "base/time/time.h"
|
||||
#include "base/timer/timer.h"
|
||||
#include "build/build_config.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
|
||||
#if !BUILDFLAG(SUPPORTS_CODE_ORDERING)
|
||||
#error Code ordering support is required for the reached code profiler.
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
namespace android {
|
||||
|
||||
namespace {
|
||||
|
||||
#if !defined(NDEBUG) || defined(COMPONENT_BUILD) || defined(OFFICIAL_BUILD)
|
||||
// Always disabled for debug builds to avoid hitting a limit of signal
|
||||
// interrupts that can get delivered into a single HANDLE_EINTR. Also
|
||||
// debugging experience would be bad if there are a lot of signals flying
|
||||
// around.
|
||||
// Always disabled for component builds because in this case the code is not
|
||||
// organized in one contiguous region which is required for the reached code
|
||||
// profiler.
|
||||
// Disabled for official builds because `g_text_bitfield` isn't included in
|
||||
// official builds.
|
||||
constexpr const bool kConfigurationSupported = false;
|
||||
#else
|
||||
constexpr const bool kConfigurationSupported = true;
|
||||
#endif
|
||||
|
||||
constexpr const char kDumpToFileFlag[] = "reached-code-profiler-dump-to-file";
|
||||
|
||||
constexpr uint64_t kIterationsBeforeSkipping = 50;
|
||||
constexpr uint64_t kIterationsBetweenUpdates = 100;
|
||||
constexpr int kProfilerSignal = SIGWINCH;
|
||||
|
||||
constexpr base::TimeDelta kSamplingInterval = base::Milliseconds(10);
|
||||
constexpr base::TimeDelta kDumpInterval = base::Seconds(30);
|
||||
|
||||
void HandleSignal(int signal, siginfo_t* info, void* context) {
|
||||
if (signal != kProfilerSignal)
|
||||
return;
|
||||
|
||||
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
|
||||
#if defined(ARCH_CPU_ARM64)
|
||||
uintptr_t address = ucontext->uc_mcontext.pc;
|
||||
#else
|
||||
uintptr_t address = ucontext->uc_mcontext.arm_pc;
|
||||
#endif
|
||||
ReachedAddressesBitset::GetTextBitset()->RecordAddress(address);
|
||||
}
|
||||
|
||||
struct ScopedTimerCloseTraits {
|
||||
static absl::optional<timer_t> InvalidValue() { return absl::nullopt; }
|
||||
|
||||
static void Free(absl::optional<timer_t> x) { timer_delete(*x); }
|
||||
};
|
||||
|
||||
// RAII object holding an interval timer.
|
||||
using ScopedTimer =
|
||||
base::ScopedGeneric<absl::optional<timer_t>, ScopedTimerCloseTraits>;
|
||||
|
||||
void DumpToFile(const base::FilePath& path,
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
|
||||
DCHECK(task_runner->BelongsToCurrentThread());
|
||||
|
||||
auto dir_path = path.DirName();
|
||||
if (!base::DirectoryExists(dir_path) && !base::CreateDirectory(dir_path)) {
|
||||
PLOG(ERROR) << "Could not create " << dir_path;
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> reached_offsets =
|
||||
ReachedAddressesBitset::GetTextBitset()->GetReachedOffsets();
|
||||
base::StringPiece contents(
|
||||
reinterpret_cast<const char*>(reached_offsets.data()),
|
||||
reached_offsets.size());
|
||||
if (!base::ImportantFileWriter::WriteFileAtomically(path, contents,
|
||||
"ReachedDump")) {
|
||||
LOG(ERROR) << "Could not write reached dump into " << path;
|
||||
}
|
||||
|
||||
task_runner->PostDelayedTask(
|
||||
FROM_HERE, base::BindOnce(&DumpToFile, path, task_runner), kDumpInterval);
|
||||
}
|
||||
|
||||
class ReachedCodeProfiler {
|
||||
public:
|
||||
static ReachedCodeProfiler* GetInstance() {
|
||||
static base::NoDestructor<ReachedCodeProfiler> instance;
|
||||
return instance.get();
|
||||
}
|
||||
|
||||
ReachedCodeProfiler(const ReachedCodeProfiler&) = delete;
|
||||
ReachedCodeProfiler& operator=(const ReachedCodeProfiler&) = delete;
|
||||
|
||||
// Starts to periodically send |kProfilerSignal| to all threads.
|
||||
void Start(LibraryProcessType library_process_type,
|
||||
base::TimeDelta sampling_interval) {
|
||||
if (is_enabled_)
|
||||
return;
|
||||
|
||||
// Set |kProfilerSignal| signal handler.
|
||||
// TODO(crbug.com/916263): consider restoring |old_handler| after the
|
||||
// profiler gets stopped.
|
||||
struct sigaction old_handler;
|
||||
struct sigaction sa;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_sigaction = &HandleSignal;
|
||||
sa.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||
int ret = sigaction(kProfilerSignal, &sa, &old_handler);
|
||||
if (ret) {
|
||||
PLOG(ERROR) << "Error setting signal handler. The reached code profiler "
|
||||
"is disabled";
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a new interval timer.
|
||||
struct sigevent sevp;
|
||||
memset(&sevp, 0, sizeof(sevp));
|
||||
sevp.sigev_notify = SIGEV_THREAD;
|
||||
sevp.sigev_notify_function = &OnTimerNotify;
|
||||
timer_t timerid;
|
||||
ret = timer_create(CLOCK_PROCESS_CPUTIME_ID, &sevp, &timerid);
|
||||
if (ret) {
|
||||
PLOG(ERROR)
|
||||
<< "timer_create() failed. The reached code profiler is disabled";
|
||||
return;
|
||||
}
|
||||
|
||||
timer_.reset(timerid);
|
||||
|
||||
// Start the interval timer.
|
||||
struct itimerspec its;
|
||||
memset(&its, 0, sizeof(its));
|
||||
its.it_interval.tv_nsec =
|
||||
checked_cast<long>(sampling_interval.InNanoseconds());
|
||||
its.it_value = its.it_interval;
|
||||
ret = timer_settime(timerid, 0, &its, nullptr);
|
||||
if (ret) {
|
||||
PLOG(ERROR)
|
||||
<< "timer_settime() failed. The reached code profiler is disabled";
|
||||
return;
|
||||
}
|
||||
|
||||
if (library_process_type == PROCESS_BROWSER)
|
||||
StartDumpingReachedCode();
|
||||
|
||||
is_enabled_ = true;
|
||||
}
|
||||
|
||||
// Stops profiling.
|
||||
void Stop() {
|
||||
timer_.reset();
|
||||
dumping_thread_.reset();
|
||||
is_enabled_ = false;
|
||||
}
|
||||
|
||||
// Returns whether the profiler is currently enabled.
|
||||
bool IsEnabled() { return is_enabled_; }
|
||||
|
||||
private:
|
||||
ReachedCodeProfiler()
|
||||
: current_pid_(getpid()), iteration_number_(0), is_enabled_(false) {}
|
||||
|
||||
static void OnTimerNotify(sigval_t ignored) {
|
||||
ReachedCodeProfiler::GetInstance()->SendSignalToAllThreads();
|
||||
}
|
||||
|
||||
void SendSignalToAllThreads() {
|
||||
// This code should be thread-safe.
|
||||
base::AutoLock scoped_lock(lock_);
|
||||
++iteration_number_;
|
||||
|
||||
if (iteration_number_ <= kIterationsBeforeSkipping ||
|
||||
iteration_number_ % kIterationsBetweenUpdates == 0) {
|
||||
tids_.clear();
|
||||
if (!base::GetThreadsForProcess(current_pid_, &tids_)) {
|
||||
LOG(WARNING) << "Failed to get a list of threads for process "
|
||||
<< current_pid_;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pid_t current_tid = gettid();
|
||||
for (pid_t tid : tids_) {
|
||||
if (tid != current_tid)
|
||||
tgkill(current_pid_, tid, kProfilerSignal);
|
||||
}
|
||||
}
|
||||
|
||||
void StartDumpingReachedCode() {
|
||||
const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
|
||||
if (!cmdline->HasSwitch(kDumpToFileFlag))
|
||||
return;
|
||||
|
||||
base::FilePath dir_path(cmdline->GetSwitchValueASCII(kDumpToFileFlag));
|
||||
if (dir_path.empty()) {
|
||||
if (!base::PathService::Get(base::DIR_CACHE, &dir_path)) {
|
||||
LOG(WARNING) << "Failed to get cache dir path.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto file_path =
|
||||
dir_path.Append(base::StringPrintf("reached-code-%d.txt", getpid()));
|
||||
|
||||
dumping_thread_ =
|
||||
std::make_unique<base::Thread>("ReachedCodeProfilerDumpingThread");
|
||||
dumping_thread_->StartWithOptions(
|
||||
base::Thread::Options(base::ThreadType::kBackground));
|
||||
dumping_thread_->task_runner()->PostDelayedTask(
|
||||
FROM_HERE,
|
||||
base::BindOnce(&DumpToFile, file_path, dumping_thread_->task_runner()),
|
||||
kDumpInterval);
|
||||
}
|
||||
|
||||
base::Lock lock_;
|
||||
std::vector<pid_t> tids_;
|
||||
const pid_t current_pid_;
|
||||
uint64_t iteration_number_;
|
||||
ScopedTimer timer_;
|
||||
std::unique_ptr<base::Thread> dumping_thread_;
|
||||
|
||||
bool is_enabled_;
|
||||
|
||||
friend class NoDestructor<ReachedCodeProfiler>;
|
||||
};
|
||||
|
||||
bool ShouldEnableReachedCodeProfiler() {
|
||||
if (!kConfigurationSupported)
|
||||
return false;
|
||||
|
||||
const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
|
||||
return cmdline->HasSwitch(switches::kEnableReachedCodeProfiler);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void InitReachedCodeProfilerAtStartup(LibraryProcessType library_process_type) {
|
||||
// The profiler shouldn't be run as part of webview.
|
||||
CHECK(library_process_type == PROCESS_BROWSER ||
|
||||
library_process_type == PROCESS_CHILD);
|
||||
|
||||
if (!ShouldEnableReachedCodeProfiler())
|
||||
return;
|
||||
|
||||
int interval_us = 0;
|
||||
base::TimeDelta sampling_interval = kSamplingInterval;
|
||||
if (base::StringToInt(
|
||||
base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
|
||||
switches::kReachedCodeSamplingIntervalUs),
|
||||
&interval_us) &&
|
||||
interval_us > 0) {
|
||||
sampling_interval = base::Microseconds(interval_us);
|
||||
}
|
||||
ReachedCodeProfiler::GetInstance()->Start(library_process_type,
|
||||
sampling_interval);
|
||||
}
|
||||
|
||||
bool IsReachedCodeProfilerEnabled() {
|
||||
return ReachedCodeProfiler::GetInstance()->IsEnabled();
|
||||
}
|
||||
|
||||
bool IsReachedCodeProfilerSupported() {
|
||||
return kConfigurationSupported;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace base
|
@ -1,34 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_ANDROID_REACHED_CODE_PROFILER_H_
|
||||
#define BASE_ANDROID_REACHED_CODE_PROFILER_H_
|
||||
|
||||
#include "base/android/library_loader/library_loader_hooks.h"
|
||||
#include "base/base_export.h"
|
||||
|
||||
namespace base {
|
||||
namespace android {
|
||||
|
||||
// Initializes and starts the reached code profiler for |library_process_type|.
|
||||
// Reached symbols are not recorded before calling this function, so it has to
|
||||
// be called as early in startup as possible. This has to be called before the
|
||||
// process creates any thread.
|
||||
// TODO(crbug.com/916263): Currently, the reached code profiler must be
|
||||
// initialized before the tracing profiler. If we want to start it at later
|
||||
// point, we need to check that the tracing profiler isn't initialized first.
|
||||
BASE_EXPORT void InitReachedCodeProfilerAtStartup(
|
||||
LibraryProcessType library_process_type);
|
||||
|
||||
// Returns whether the reached code profiler is enabled.
|
||||
BASE_EXPORT bool IsReachedCodeProfilerEnabled();
|
||||
|
||||
// Returns whether the reached code profiler can be possibly enabled for the
|
||||
// current build configuration.
|
||||
BASE_EXPORT bool IsReachedCodeProfilerSupported();
|
||||
|
||||
} // namespace android
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_ANDROID_REACHED_CODE_PROFILER_H_
|
@ -1,22 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/android/reached_code_profiler.h"
|
||||
|
||||
namespace base {
|
||||
namespace android {
|
||||
|
||||
void InitReachedCodeProfilerAtStartup(LibraryProcessType library_process_type) {
|
||||
}
|
||||
|
||||
bool IsReachedCodeProfilerEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsReachedCodeProfilerSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace base
|
@ -143,14 +143,6 @@ const char kEnableCrashReporterForTesting[] =
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
// Enables the reached code profiler that samples all threads in all processes
|
||||
// to determine which functions are almost never executed.
|
||||
const char kEnableReachedCodeProfiler[] = "enable-reached-code-profiler";
|
||||
|
||||
// Specifies the profiling interval in microseconds for reached code profiler.
|
||||
const char kReachedCodeSamplingIntervalUs[] =
|
||||
"reached-code-sampling-interval-us";
|
||||
|
||||
// Default country code to be used for search engine localization.
|
||||
const char kDefaultCountryCodeAtInstall[] = "default-country-code";
|
||||
|
||||
|
@ -49,8 +49,6 @@ extern const char kEnableCrashReporterForTesting[];
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
extern const char kEnableReachedCodeProfiler[];
|
||||
extern const char kReachedCodeSamplingIntervalUs[];
|
||||
extern const char kDefaultCountryCodeAtInstall[];
|
||||
extern const char kEnableIdleTracing[];
|
||||
extern const char kForceFieldTrialParams[];
|
||||
|
@ -250,7 +250,6 @@ static_library("test_support") {
|
||||
"android/url_utils.cc",
|
||||
"android/url_utils.h",
|
||||
"multiprocess_test_android.cc",
|
||||
"reached_code_profiler_android.cc",
|
||||
"test_file_util_android.cc",
|
||||
"test_file_util_linux.cc",
|
||||
"test_support_android.cc",
|
||||
|
@ -1,25 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/android/jni_android.h"
|
||||
#include "base/android/reached_code_profiler.h"
|
||||
#include "base/test/test_support_jni_headers/ReachedCodeProfiler_jni.h"
|
||||
|
||||
// This file provides functions to query the state of the reached code profiler
|
||||
// from Java. It's used only for tests.
|
||||
namespace base {
|
||||
namespace android {
|
||||
|
||||
static jboolean JNI_ReachedCodeProfiler_IsReachedCodeProfilerEnabled(
|
||||
JNIEnv* env) {
|
||||
return IsReachedCodeProfilerEnabled();
|
||||
}
|
||||
|
||||
static jboolean JNI_ReachedCodeProfiler_IsReachedCodeProfilerSupported(
|
||||
JNIEnv* env) {
|
||||
return IsReachedCodeProfilerSupported();
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace base
|
@ -34,7 +34,6 @@ chrome_test_java_sources = [
|
||||
"javatests/src/org/chromium/chrome/browser/PopularUrlsTest.java",
|
||||
"javatests/src/org/chromium/chrome/browser/PopupTest.java",
|
||||
"javatests/src/org/chromium/chrome/browser/ProcessIsolationTest.java",
|
||||
"javatests/src/org/chromium/chrome/browser/ReachedCodeProfilerTest.java",
|
||||
"javatests/src/org/chromium/chrome/browser/RestoreHistogramTest.java",
|
||||
"javatests/src/org/chromium/chrome/browser/SafeBrowsingTest.java",
|
||||
"javatests/src/org/chromium/chrome/browser/SelectFileDialogTest.java",
|
||||
|
@ -12,7 +12,6 @@ import androidx.annotation.VisibleForTesting;
|
||||
import org.jni_zero.CalledByNative;
|
||||
|
||||
import org.chromium.base.ApplicationStatus;
|
||||
import org.chromium.base.FieldTrialList;
|
||||
import org.chromium.base.library_loader.LibraryLoader;
|
||||
import org.chromium.build.BuildConfig;
|
||||
import org.chromium.chrome.browser.back_press.BackPressManager;
|
||||
@ -49,8 +48,6 @@ public class ChromeCachedFlags {
|
||||
|
||||
private boolean mIsFinishedCachingNativeFlags;
|
||||
|
||||
private static String sReachedCodeProfilerTrialGroup;
|
||||
|
||||
/**
|
||||
* A list of field trial parameters that will be cached when starting minimal browser mode. See
|
||||
* {@link #cacheMinimalBrowserFlags()}.
|
||||
@ -174,16 +171,7 @@ public class ChromeCachedFlags {
|
||||
* Do not add new simple boolean flags here, add them to {@link #cacheNativeFlags} instead.
|
||||
*/
|
||||
public static void cacheAdditionalNativeFlags() {
|
||||
cacheReachedCodeProfilerTrialGroup();
|
||||
|
||||
// Propagate REACHED_CODE_PROFILER feature value to LibraryLoader. This can't be done in
|
||||
// LibraryLoader itself because it lives in //base and can't depend on ChromeFeatureList.
|
||||
LibraryLoader.setReachedCodeProfilerEnabledOnNextRuns(
|
||||
ChromeFeatureList.isEnabled(ChromeFeatureList.REACHED_CODE_PROFILER),
|
||||
ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
|
||||
ChromeFeatureList.REACHED_CODE_PROFILER, "sampling_interval_us", 0));
|
||||
|
||||
// Similarly, propagate the BACKGROUND_THREAD_POOL feature value to LibraryLoader.
|
||||
// Propagate the BACKGROUND_THREAD_POOL feature value to LibraryLoader.
|
||||
LibraryLoader.setBackgroundThreadPoolEnabledOnNextRuns(
|
||||
ChromeFeatureList.isEnabled(ChromeFeatureList.BACKGROUND_THREAD_POOL));
|
||||
|
||||
@ -192,33 +180,6 @@ public class ChromeCachedFlags {
|
||||
ChromeFeatureList.isEnabled(ChromeFeatureList.CACHE_ACTIVITY_TASKID));
|
||||
}
|
||||
|
||||
/** Caches the trial group of the reached code profiler feature to be using on next startup. */
|
||||
private static void cacheReachedCodeProfilerTrialGroup() {
|
||||
// Make sure that the existing value is saved in a static variable before overwriting it.
|
||||
if (sReachedCodeProfilerTrialGroup == null) {
|
||||
getReachedCodeProfilerTrialGroup();
|
||||
}
|
||||
|
||||
ChromeSharedPreferences.getInstance()
|
||||
.writeString(
|
||||
ChromePreferenceKeys.REACHED_CODE_PROFILER_GROUP,
|
||||
FieldTrialList.findFullName(ChromeFeatureList.REACHED_CODE_PROFILER));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The trial group of the reached code profiler.
|
||||
*/
|
||||
@CalledByNative
|
||||
public static String getReachedCodeProfilerTrialGroup() {
|
||||
if (sReachedCodeProfilerTrialGroup == null) {
|
||||
sReachedCodeProfilerTrialGroup =
|
||||
ChromeSharedPreferences.getInstance()
|
||||
.readString(ChromePreferenceKeys.REACHED_CODE_PROFILER_GROUP, "");
|
||||
}
|
||||
|
||||
return sReachedCodeProfilerTrialGroup;
|
||||
}
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
static void cacheMinimalBrowserFlagsTimeFromNativeTime() {
|
||||
ChromeSharedPreferences.getInstance()
|
||||
|
@ -1,132 +0,0 @@
|
||||
// Copyright 2019 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package org.chromium.chrome.browser;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.chromium.base.BaseSwitches;
|
||||
import org.chromium.base.library_loader.LibraryLoader;
|
||||
import org.chromium.base.test.ReachedCodeProfiler;
|
||||
import org.chromium.base.test.util.CommandLineFlags;
|
||||
import org.chromium.chrome.browser.flags.ChromeFeatureList;
|
||||
import org.chromium.chrome.browser.flags.ChromeSwitches;
|
||||
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
|
||||
import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
|
||||
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
|
||||
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
|
||||
import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
|
||||
import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
|
||||
|
||||
/** Tests for the reached code profiler feature setup. */
|
||||
@RunWith(ChromeJUnit4ClassRunner.class)
|
||||
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
|
||||
public final class ReachedCodeProfilerTest {
|
||||
@Rule
|
||||
public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
|
||||
|
||||
private static final String FAKE_GROUP_NAME = "FakeGroup";
|
||||
|
||||
/**
|
||||
* Tests that passing a command line switch enables the reached code profiler no matter what.
|
||||
*/
|
||||
@Test
|
||||
@SmallTest
|
||||
@DisableFeatures(ChromeFeatureList.REACHED_CODE_PROFILER)
|
||||
@CommandLineFlags.Add(BaseSwitches.ENABLE_REACHED_CODE_PROFILER)
|
||||
public void testExplicitlyEnableViaCommandLineSwitch() {
|
||||
mActivityTestRule.startMainActivityFromLauncher();
|
||||
assertReachedCodeProfilerIsEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that setting a shared preference enables the reached code profiler. This test imitates
|
||||
* the second launch after enabling the feature
|
||||
*/
|
||||
@Test
|
||||
@SmallTest
|
||||
@CommandLineFlags.Add({
|
||||
"enable-features="
|
||||
+ ChromeFeatureList.REACHED_CODE_PROFILER
|
||||
+ "<"
|
||||
+ ChromeFeatureList.REACHED_CODE_PROFILER,
|
||||
"force-fieldtrials=" + ChromeFeatureList.REACHED_CODE_PROFILER + "/" + FAKE_GROUP_NAME,
|
||||
"force-fieldtrial-params="
|
||||
+ ChromeFeatureList.REACHED_CODE_PROFILER
|
||||
+ "."
|
||||
+ FAKE_GROUP_NAME
|
||||
+ ":sampling_interval_us/42"
|
||||
})
|
||||
public void testEnabledViaCachedSharedPreference() {
|
||||
LibraryLoader.setReachedCodeProfilerEnabledOnNextRuns(true, 42);
|
||||
mActivityTestRule.startMainActivityFromLauncher();
|
||||
assertReachedCodeProfilerIsEnabled();
|
||||
Assert.assertEquals(42, LibraryLoader.getReachedCodeSamplingIntervalUs());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the feature state is cached in shared preferences after native initialization.
|
||||
* This test imitates the first run when the feature is enabled.
|
||||
*/
|
||||
@Test
|
||||
@SmallTest
|
||||
@EnableFeatures(ChromeFeatureList.REACHED_CODE_PROFILER)
|
||||
public void testSharedPreferenceIsCached_Enable() {
|
||||
mActivityTestRule.startMainActivityFromLauncher();
|
||||
|
||||
Assert.assertEquals(10000, LibraryLoader.getReachedCodeSamplingIntervalUs());
|
||||
// Enabling takes effect only on the second startup.
|
||||
Assert.assertFalse(ReachedCodeProfiler.isEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the feature state is cached in shared preferences after native initialization.
|
||||
* This test imitates disabling the reached code profiler after it has been enabled for some
|
||||
* time.
|
||||
*/
|
||||
@Test
|
||||
@SmallTest
|
||||
@DisableFeatures(ChromeFeatureList.REACHED_CODE_PROFILER)
|
||||
public void testSharedPreferenceIsCached_Disable() {
|
||||
LibraryLoader.setReachedCodeProfilerEnabledOnNextRuns(true, 0);
|
||||
mActivityTestRule.startMainActivityFromLauncher();
|
||||
Assert.assertEquals(0, LibraryLoader.getReachedCodeSamplingIntervalUs());
|
||||
// Disabling takes effect only on the second startup.
|
||||
assertReachedCodeProfilerIsEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the reached code profiler field trial group is saved in shared preferences for
|
||||
* being used on the next startup.
|
||||
*/
|
||||
@Test
|
||||
@SmallTest
|
||||
@CommandLineFlags.Add(
|
||||
"force-fieldtrials=" + ChromeFeatureList.REACHED_CODE_PROFILER + "/" + FAKE_GROUP_NAME)
|
||||
public void testSharedPreferenceTrialGroupIsCached() {
|
||||
mActivityTestRule.startMainActivityFromLauncher();
|
||||
Assert.assertEquals(
|
||||
FAKE_GROUP_NAME,
|
||||
ChromeSharedPreferences.getInstance()
|
||||
.readString(ChromePreferenceKeys.REACHED_CODE_PROFILER_GROUP, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* The reached code profiler is always disabled in some configurations. This helper allows to
|
||||
* check if the profiler is enabled in supported configurations.
|
||||
*/
|
||||
private void assertReachedCodeProfilerIsEnabled() {
|
||||
if (!ReachedCodeProfiler.isSupported()) {
|
||||
Assert.assertFalse(ReachedCodeProfiler.isEnabled());
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.assertTrue(ReachedCodeProfiler.isEnabled());
|
||||
}
|
||||
}
|
@ -9,13 +9,10 @@
|
||||
#include "base/android/jni_string.h"
|
||||
#include "base/feature_list.h"
|
||||
|
||||
using base::android::ConvertJavaStringToUTF8;
|
||||
using base::android::ConvertUTF8ToJavaString;
|
||||
using base::android::JavaParamRef;
|
||||
using base::android::ScopedJavaLocalRef;
|
||||
|
||||
namespace chrome {
|
||||
namespace android {
|
||||
namespace chrome::android {
|
||||
|
||||
bool IsJavaDrivenFeatureEnabled(const base::Feature& feature) {
|
||||
JNIEnv* env = base::android::AttachCurrentThread();
|
||||
@ -24,12 +21,4 @@ bool IsJavaDrivenFeatureEnabled(const base::Feature& feature) {
|
||||
return Java_ChromeCachedFlags_isEnabled(env, j_feature_name);
|
||||
}
|
||||
|
||||
std::string GetReachedCodeProfilerTrialGroup() {
|
||||
JNIEnv* env = base::android::AttachCurrentThread();
|
||||
ScopedJavaLocalRef<jstring> group =
|
||||
Java_ChromeCachedFlags_getReachedCodeProfilerTrialGroup(env);
|
||||
return ConvertJavaStringToUTF8(env, group);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace chrome
|
||||
} // namespace chrome::android
|
||||
|
@ -5,22 +5,12 @@
|
||||
#ifndef CHROME_BROWSER_ANDROID_FLAGS_CHROME_CACHED_FLAGS_H_
|
||||
#define CHROME_BROWSER_ANDROID_FLAGS_CHROME_CACHED_FLAGS_H_
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/feature_list.h"
|
||||
|
||||
namespace chrome {
|
||||
namespace android {
|
||||
namespace chrome::android {
|
||||
|
||||
bool IsJavaDrivenFeatureEnabled(const base::Feature& feature);
|
||||
|
||||
// Returns a finch group name currently used for the reached code profiler.
|
||||
// Returns an empty string if the group isn't specified.
|
||||
std::string GetReachedCodeProfilerTrialGroup();
|
||||
|
||||
} // namespace android
|
||||
} // namespace chrome
|
||||
} // namespace chrome::android
|
||||
|
||||
#endif // CHROME_BROWSER_ANDROID_FLAGS_CHROME_CACHED_FLAGS_H_
|
||||
|
@ -106,15 +106,6 @@ void ChromeBrowserFieldTrials::SetUpClientSideFieldTrials(
|
||||
|
||||
void ChromeBrowserFieldTrials::RegisterSyntheticTrials() {
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
static constexpr char kReachedCodeProfilerTrial[] =
|
||||
"ReachedCodeProfilerSynthetic2";
|
||||
std::string reached_code_profiler_group =
|
||||
chrome::android::GetReachedCodeProfilerTrialGroup();
|
||||
if (!reached_code_profiler_group.empty()) {
|
||||
ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(
|
||||
kReachedCodeProfilerTrial, reached_code_profiler_group);
|
||||
}
|
||||
|
||||
{
|
||||
// BackgroundThreadPoolSynthetic field trial.
|
||||
const char* group_name;
|
||||
|
@ -234,7 +234,6 @@ const base::Feature* const kFeaturesExposedToJava[] = {
|
||||
&kOmniboxNoopEditUrlSuggestionClicks,
|
||||
&kPartnerCustomizationsUma,
|
||||
&kQuickDeleteForAndroid,
|
||||
&kReachedCodeProfiler,
|
||||
&kReadAloud,
|
||||
&kReadAloudInOverflowMenuInCCT,
|
||||
&kReadAloudPlayback,
|
||||
@ -704,10 +703,6 @@ BASE_FEATURE(kQuickDeleteForAndroid,
|
||||
"QuickDeleteForAndroid",
|
||||
base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
|
||||
BASE_FEATURE(kReachedCodeProfiler,
|
||||
"ReachedCodeProfiler",
|
||||
base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
|
||||
BASE_FEATURE(kReadAloud, "ReadAloud", base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
|
||||
BASE_FEATURE(kReadAloudInOverflowMenuInCCT,
|
||||
|
@ -111,7 +111,6 @@ BASE_DECLARE_FEATURE(kPwaRestoreUi);
|
||||
BASE_DECLARE_FEATURE(kOpenDownloadDialog);
|
||||
BASE_DECLARE_FEATURE(kPartnerCustomizationsUma);
|
||||
BASE_DECLARE_FEATURE(kQuickDeleteForAndroid);
|
||||
BASE_DECLARE_FEATURE(kReachedCodeProfiler);
|
||||
BASE_DECLARE_FEATURE(kReadAloud);
|
||||
BASE_DECLARE_FEATURE(kReadAloudInOverflowMenuInCCT);
|
||||
BASE_DECLARE_FEATURE(kReadAloudPlayback);
|
||||
|
@ -345,7 +345,6 @@ public abstract class ChromeFeatureList {
|
||||
public static final String QUERY_TILES_IN_ZPS_ON_NTP = "OmniboxQueryTilesInZPSOnNTP";
|
||||
public static final String QUICK_DELETE_FOR_ANDROID = "QuickDeleteForAndroid";
|
||||
public static final String QUIET_NOTIFICATION_PROMPTS = "QuietNotificationPrompts";
|
||||
public static final String REACHED_CODE_PROFILER = "ReachedCodeProfiler";
|
||||
public static final String READALOUD = "ReadAloud";
|
||||
public static final String READALOUD_IN_OVERFLOW_MENU_IN_CCT = "ReadAloudInOverflowMenuInCCT";
|
||||
public static final String READALOUD_PLAYBACK = "ReadAloudPlayback";
|
||||
|
@ -653,12 +653,6 @@ public final class ChromePreferenceKeys {
|
||||
public static final String SEARCH_RESUMPTION_MODULE_COLLAPSE_ON_NTP =
|
||||
"Chrome.SearchResumptionModule.Collapse";
|
||||
|
||||
/**
|
||||
* Contains a trial group that was used to determine whether the reached code profiler should be
|
||||
* enabled.
|
||||
*/
|
||||
public static final String REACHED_CODE_PROFILER_GROUP = "reached_code_profiler_group";
|
||||
|
||||
public static final String RLZ_NOTIFIED = "rlz_first_search_notified";
|
||||
|
||||
/** Key used to store the default Search Engine Type before choice is presented. */
|
||||
|
@ -152,6 +152,8 @@ public class DeprecatedChromePreferenceKeys {
|
||||
"prefetch_notification_offline_counter",
|
||||
"prefetch_notification_shown_time",
|
||||
"prioritize_bootstrap_tasks",
|
||||
"reached_code_profiler_group",
|
||||
"reached_code_sampling_interval",
|
||||
"service_manager_for_background_prefetch",
|
||||
"service_manager_for_download_resumption",
|
||||
"signin_promo_impressions_count_bookmarks",
|
||||
|
@ -89,7 +89,6 @@ public class LegacyChromePreferenceKeys {
|
||||
ChromePreferenceKeys.PRIVACY_METRICS_IN_SAMPLE,
|
||||
ChromePreferenceKeys.PROFILES_BOOT_TIMESTAMP,
|
||||
ChromePreferenceKeys.PROMOS_SKIPPED_ON_FIRST_START,
|
||||
ChromePreferenceKeys.REACHED_CODE_PROFILER_GROUP,
|
||||
ChromePreferenceKeys.RLZ_NOTIFIED,
|
||||
ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE,
|
||||
ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_PRESENTED_VERSION,
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#include "content/app/android/library_loader_hooks.h"
|
||||
|
||||
#include "base/android/reached_code_profiler.h"
|
||||
#include "base/i18n/icu_util.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/process/current_process.h"
|
||||
@ -19,13 +18,6 @@ namespace content {
|
||||
bool LibraryLoaded(JNIEnv* env,
|
||||
jclass clazz,
|
||||
base::android::LibraryProcessType library_process_type) {
|
||||
if (library_process_type ==
|
||||
base::android::LibraryProcessType::PROCESS_BROWSER ||
|
||||
library_process_type ==
|
||||
base::android::LibraryProcessType::PROCESS_CHILD) {
|
||||
base::android::InitReachedCodeProfilerAtStartup(library_process_type);
|
||||
}
|
||||
|
||||
// Android's main browser loop is custom so we set the browser name here as
|
||||
// early as possible if this is the browser process or main webview process.
|
||||
if (library_process_type ==
|
||||
|
@ -301,8 +301,6 @@ static const char* const kSwitchNames[] = {
|
||||
switches::kForceVideoOverlays,
|
||||
switches::kSkiaGraphiteBackend,
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
switches::kEnableReachedCodeProfiler,
|
||||
switches::kReachedCodeSamplingIntervalUs,
|
||||
switches::kDisableAdpf,
|
||||
#endif
|
||||
#if BUILDFLAG(IS_CHROMEOS)
|
||||
|
@ -3567,8 +3567,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
|
||||
switches::kDisallowNonExactResourceReuse,
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
switches::kDisableMediaSessionAPI,
|
||||
switches::kEnableReachedCodeProfiler,
|
||||
switches::kReachedCodeSamplingIntervalUs,
|
||||
switches::kRendererWaitForJavaDebugger,
|
||||
#endif
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
|
@ -367,10 +367,6 @@ bool UtilityProcessHost::StartProcess() {
|
||||
switches::kUseGL,
|
||||
switches::kV,
|
||||
switches::kVModule,
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
switches::kEnableReachedCodeProfiler,
|
||||
switches::kReachedCodeSamplingIntervalUs,
|
||||
#endif
|
||||
switches::kEnableExperimentalWebPlatformFeatures,
|
||||
// These flags are used by the audio service:
|
||||
switches::kAudioBufferSize,
|
||||
|
@ -22,8 +22,6 @@ const string kSystemTraceDataSourceName = "org.chromium.trace_system";
|
||||
const string kArcTraceDataSourceName = "org.chromium.trace_arc";
|
||||
const string kSamplerProfilerSourceName = "org.chromium.sampler_profiler";
|
||||
const string kJavaHeapProfilerSourceName = "org.chromium.java_heap_profiler";
|
||||
const string kReachedCodeProfilerSourceName =
|
||||
"org.chromium.reached_code_profiler";
|
||||
const string kNativeHeapProfilerSourceName =
|
||||
"org.chromium.native_heap_profiler";
|
||||
|
||||
|
Reference in New Issue
Block a user