Skip to content

Commit

Permalink
cygprofile: Orderfile-based madvise() and prefetch.
Browse files Browse the repository at this point in the history
Add support for madvising and prefetching different parts of the
native library according to the orderfile. The orderfile will support
organising the library text section into three parts: code that is
used in startup only, commonly used code that is ordered, and all
other code that is not ordered. This change adds another
dummy_function_* to achieve that. The currently-experimental
MadviseRandomText() function is replace with MadviseForOrderfile which
performs more precise madvising of unordered code only as RANDOM.

When madvising for the orderfile is done, library prefetching is
disabled. This will be changed in the future to prefetch only startup
or only ordered code depending on what is more effective in
experiments.

Bug: 758566
Change-Id: I85af8e33a79d9091e282f2640c47d6c83aca7fc2
Reviewed-on: https://chromium-review.googlesource.com/923965
Commit-Queue: Matthew Cary <[email protected]>
Reviewed-by: Camille Lamy <[email protected]>
Reviewed-by: Gabriel Charette <[email protected]>
Reviewed-by: agrieve <[email protected]>
Reviewed-by: Benoit L <[email protected]>
Cr-Commit-Position: refs/heads/master@{#538766}
  • Loading branch information
Matthew Cary authored and Commit Bot committed Feb 23, 2018
1 parent a9a703e commit ed73a1d
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 27 deletions.
28 changes: 18 additions & 10 deletions base/android/library_loader/library_loader_hooks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ void RecordLibraryPreloaderRendereHistogram() {
}
}

#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
bool ShouldDoOrderfileMemoryOptimization() {
return CommandLine::ForCurrentProcess()->HasSwitch(
switches::kOrderfileMemoryOptimization);
}
#endif

} // namespace

static void JNI_LibraryLoader_RegisterChromiumAndroidLinkerRendererHistogram(
Expand Down Expand Up @@ -168,15 +175,11 @@ void SetLibraryLoadedHook(LibraryLoadedHook* func) {
static jboolean JNI_LibraryLoader_LibraryLoaded(
JNIEnv* env,
const JavaParamRef<jobject>& jcaller) {
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kMadviseRandomExecutableCode)) {
#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
NativeLibraryPrefetcher::MadviseRandomText();
#else
LOG(WARNING) << switches::kMadviseRandomExecutableCode
<< " is not supported on this architecture.";
#endif
if (ShouldDoOrderfileMemoryOptimization()) {
NativeLibraryPrefetcher::MadviseForOrderfile();
}
#endif

if (g_native_initialization_hook && !g_native_initialization_hook())
return false;
Expand All @@ -196,10 +199,15 @@ static jboolean JNI_LibraryLoader_ForkAndPrefetchNativeLibrary(
JNIEnv* env,
const JavaParamRef<jclass>& clazz) {
#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
return NativeLibraryPrefetcher::ForkAndPrefetchNativeLibrary();
#else
return false;
// Calling madvise(MADV_RANDOM) and prefetching the same region have the
// opposite effects.
// TODO(crbug.com/758566): add library prefetching that only prefetches
// regions not madvise(MADV_RANDOM)'d.
if (!ShouldDoOrderfileMemoryOptimization()) {
return NativeLibraryPrefetcher::ForkAndPrefetchNativeLibrary();
}
#endif
return false;
}

static jint JNI_LibraryLoader_PercentageOfResidentNativeLibraryCode(
Expand Down
39 changes: 31 additions & 8 deletions base/android/library_loader/library_prefetcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <sys/wait.h>
#include <unistd.h>
#include <algorithm>
#include <atomic>
#include <memory>
#include <utility>
#include <vector>
Expand Down Expand Up @@ -81,7 +82,7 @@ bool Mincore(size_t start, size_t end, std::vector<unsigned char>* residency) {
// Returns the start and end of .text, aligned to the lower and upper page
// boundaries, respectively.
std::pair<size_t, size_t> GetTextRange() {
// |kStartOftext| may not be at the beginning of a page, since .plt can be
// |kStartOfText| may not be at the beginning of a page, since .plt can be
// before it, yet in the same mapping for instance.
size_t start_page = kStartOfText - kStartOfText % kPageSize;
// Set the end to the page on which the beginning of the last symbol is. The
Expand All @@ -91,6 +92,29 @@ std::pair<size_t, size_t> GetTextRange() {
return {start_page, end_page};
}

// Returns the start and end pages of the unordered section of .text, aligned to
// lower and upper page boundaries, respectively.
std::pair<size_t, size_t> GetOrderedTextRange() {
size_t start_page = kStartOfOrderedText - kStartOfOrderedText % kPageSize;
// kEndOfUnorderedText is not considered ordered, but the byte immediately
// before is considered ordered and so can not be contained in the start page.
size_t end_page = base::bits::Align(kEndOfOrderedText, kPageSize);
return {start_page, end_page};
}

// Calls madvise(advice) on the specified range. Does nothing if the range is
// empty.
void MadviseOnRange(const std::pair<size_t, size_t>& range, int advice) {
if (range.first >= range.second) {
return;
}
size_t size = range.second - range.first;
int err = madvise(reinterpret_cast<void*>(range.first), size, advice);
if (err) {
PLOG(ERROR) << "madvise() failed";
}
}

// Timestamp in ns since Unix Epoch, and residency, as returned by mincore().
struct TimestampAndResidency {
uint64_t timestamp_nanos;
Expand Down Expand Up @@ -241,14 +265,13 @@ void NativeLibraryPrefetcher::PeriodicallyCollectResidency() {
}

// static
void NativeLibraryPrefetcher::MadviseRandomText() {
void NativeLibraryPrefetcher::MadviseForOrderfile() {
CHECK(IsOrderingSane());
const auto& range = GetTextRange();
size_t size = range.second - range.first;
int err = madvise(reinterpret_cast<void*>(range.first), size, MADV_RANDOM);
if (err) {
PLOG(ERROR) << "madvise() failed";
}
LOG(WARNING) << "Performing experimental madvise from orderfile information";
// First MADV_RANDOM on all of text, then turn the ordered text range back to
// normal. The ordered range may be placed anywhere within .text.
MadviseOnRange(GetTextRange(), MADV_RANDOM);
MadviseOnRange(GetOrderedTextRange(), MADV_NORMAL);
}

} // namespace android
Expand Down
5 changes: 3 additions & 2 deletions base/android/library_loader/library_prefetcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ class BASE_EXPORT NativeLibraryPrefetcher {
// dumps it to disk.
static void PeriodicallyCollectResidency();

// Calls madvise(MADV_RANDOM) on the native library executable code range.
static void MadviseRandomText();
// Calls madvise() on the native library executable, using orderfile
// information to decide how to advise each part of the library.
static void MadviseForOrderfile();

private:
// Returns the percentage of [start, end] currently resident in
Expand Down
7 changes: 4 additions & 3 deletions base/base_switches.cc
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,10 @@ const char kEnableCrashReporterForTesting[] =
#endif

#if defined(OS_ANDROID)
// Calls madvise(MADV_RANDOM) on executable code right after the library is
// loaded, from all processes.
const char kMadviseRandomExecutableCode[] = "madvise-random-executable-code";
// Optimizes memory layout of the native library using the orderfile symbols
// given in base/android/library_loader/anchor_functions.h, via madvise and
// changing the library prefetch behavior.
const char kOrderfileMemoryOptimization[] = "orderfile-memory-optimization";
#endif

} // namespace switches
2 changes: 1 addition & 1 deletion base/base_switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ extern const char kEnableCrashReporterForTesting[];
#endif

#if defined(OS_ANDROID)
extern const char kMadviseRandomExecutableCode[];
extern const char kOrderfileMemoryOptimization[];
#endif

} // namespace switches
Expand Down
2 changes: 1 addition & 1 deletion content/browser/gpu/gpu_process_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ static const char* const kSwitchNames[] = {
switches::kUseCmdDecoder,
switches::kForceVideoOverlays,
#if defined(OS_ANDROID)
switches::kMadviseRandomExecutableCode,
switches::kOrderfileMemoryOptimization,
#endif
};

Expand Down
2 changes: 1 addition & 1 deletion content/browser/renderer_host/render_process_host_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2665,7 +2665,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisallowNonExactResourceReuse,
#if defined(OS_ANDROID)
switches::kDisableMediaSessionAPI,
switches::kMadviseRandomExecutableCode,
switches::kOrderfileMemoryOptimization,
switches::kRendererWaitForJavaDebugger,
#endif
#if defined(OS_MACOSX)
Expand Down
2 changes: 1 addition & 1 deletion content/browser/utility_process_host_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ bool UtilityProcessHostImpl::StartProcess() {
switches::kUtilityStartupDialog,
switches::kUseGL,
#if defined(OS_ANDROID)
switches::kMadviseRandomExecutableCode,
switches::kOrderfileMemoryOptimization,
#endif
};
cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
Expand Down

0 comments on commit ed73a1d

Please sign in to comment.