| Index: base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
|
| diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
|
| index 7dc015dc8f9ecb7c420e55046b2351646fb9fd2f..9dc686572d0bb4a5f85b2b74c8fa5d012c6fb480 100644
|
| --- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
|
| +++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
|
| @@ -5,7 +5,6 @@
|
| package org.chromium.base.library_loader;
|
|
|
| import android.content.Context;
|
| -import android.content.pm.ApplicationInfo;
|
| import android.os.AsyncTask;
|
| import android.os.SystemClock;
|
| import android.util.Log;
|
| @@ -15,14 +14,8 @@ import org.chromium.base.CommandLine;
|
| import org.chromium.base.JNINamespace;
|
| import org.chromium.base.TraceEvent;
|
| import org.chromium.base.VisibleForTesting;
|
| +import org.chromium.base.metrics.RecordHistogram;
|
|
|
| -import java.io.File;
|
| -import java.io.FileNotFoundException;
|
| -import java.io.IOException;
|
| -import java.io.RandomAccessFile;
|
| -import java.nio.MappedByteBuffer;
|
| -import java.nio.channels.FileChannel;
|
| -import java.util.HashMap;
|
| import java.util.Locale;
|
|
|
| import javax.annotation.Nullable;
|
| @@ -97,9 +90,6 @@ public class LibraryLoader {
|
| // final (like now) or be protected in some way (volatile of synchronized).
|
| private final int mLibraryProcessType;
|
|
|
| - // Library -> Path it has been loaded from.
|
| - private final HashMap<String, String> mLoadedFrom;
|
| -
|
| /**
|
| * @param libraryProcessType the process the shared library is loaded in. refer to
|
| * LibraryProcessType for possible values.
|
| @@ -119,7 +109,6 @@ public class LibraryLoader {
|
|
|
| private LibraryLoader(int libraryProcessType) {
|
| mLibraryProcessType = libraryProcessType;
|
| - mLoadedFrom = new HashMap<String, String>();
|
| }
|
|
|
| /**
|
| @@ -204,43 +193,10 @@ public class LibraryLoader {
|
| }
|
| }
|
|
|
| - private void prefetchLibraryToMemory(Context context, String library) {
|
| - String libFilePath = mLoadedFrom.get(library);
|
| - if (libFilePath == null) {
|
| - Log.i(TAG, "File path not found for " + library);
|
| - return;
|
| - }
|
| - String apkFilePath = context.getApplicationInfo().sourceDir;
|
| - if (libFilePath.equals(apkFilePath)) {
|
| - // TODO(lizeb): Make pre-faulting work with libraries loaded from the APK.
|
| - return;
|
| - }
|
| - try {
|
| - TraceEvent.begin("LibraryLoader.prefetchLibraryToMemory");
|
| - File file = new File(libFilePath);
|
| - int size = (int) file.length();
|
| - FileChannel channel = new RandomAccessFile(file, "r").getChannel();
|
| - MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, size);
|
| - // TODO(lizeb): Figure out whether walking the entire library is really necessary.
|
| - // Page size is 4096 for all current Android architectures.
|
| - for (int index = 0; index < size; index += 4096) {
|
| - // Note: Testing shows that neither the Java compiler nor
|
| - // Dalvik/ART eliminates this loop.
|
| - buffer.get(index);
|
| - }
|
| - } catch (FileNotFoundException e) {
|
| - Log.w(TAG, "Library file not found: " + e);
|
| - } catch (IOException e) {
|
| - Log.w(TAG, "Impossible to map the file: " + e);
|
| - } finally {
|
| - TraceEvent.end("LibraryLoader.prefetchLibraryToMemory");
|
| - }
|
| - }
|
| -
|
| /** Prefetches the native libraries in a background thread.
|
| *
|
| - * Launches an AsyncTask that maps the native libraries into memory, reads a
|
| - * part of each page from it, than unmaps it. This is done to warm up the
|
| + * Launches an AsyncTask that, through a short-lived forked process, reads a
|
| + * part of each page of the native library. This is done to warm up the
|
| * page cache, turning hard page faults into soft ones.
|
| *
|
| * This is done this way, as testing shows that fadvise(FADV_WILLNEED) is
|
| @@ -252,15 +208,13 @@ public class LibraryLoader {
|
| new AsyncTask<Void, Void, Void>() {
|
| @Override
|
| protected Void doInBackground(Void... params) {
|
| - // Note: AsyncTasks are executed in a low priority background
|
| - // thread, which is the desired behavior here since we don't
|
| - // want to interfere with the rest of the initialization.
|
| - for (String library : NativeLibraries.LIBRARIES) {
|
| - if (Linker.isChromiumLinkerLibrary(library)) {
|
| - continue;
|
| - }
|
| - prefetchLibraryToMemory(context, library);
|
| + TraceEvent.begin("LibraryLoader.asyncPrefetchLibrariesToMemory");
|
| + boolean success = nativeForkAndPrefetchNativeLibrary();
|
| + if (!success) {
|
| + Log.w(TAG, "Forking a process to prefetch the native library failed.");
|
| }
|
| + RecordHistogram.recordBooleanHistogram("LibraryLoader.PrefetchStatus", success);
|
| + TraceEvent.end("LibraryLoader.asyncPrefetchLibrariesToMemory");
|
| return null;
|
| }
|
| }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
| @@ -340,7 +294,6 @@ public class LibraryLoader {
|
| ? "using no map executable support fallback"
|
| : "directly")
|
| + " from within " + apkFilePath);
|
| - mLoadedFrom.put(library, apkFilePath);
|
| } else {
|
| // Unpack library fallback.
|
| Log.i(TAG, "Loading " + library
|
| @@ -350,19 +303,10 @@ public class LibraryLoader {
|
| context, library);
|
| fallbackWasUsed = true;
|
| Log.i(TAG, "Built fallback library " + libFilePath);
|
| - mLoadedFrom.put(library, libFilePath);
|
| }
|
| } else {
|
| // The library is in its own file.
|
| Log.i(TAG, "Loading " + library);
|
| - if (context != null) {
|
| - ApplicationInfo applicationInfo = context.getApplicationInfo();
|
| - File file = new File(applicationInfo.nativeLibraryDir, libFilePath);
|
| - mLoadedFrom.put(library, file.getAbsolutePath());
|
| - } else {
|
| - Log.i(TAG, "No context, cannot locate the native library file for "
|
| - + library);
|
| - }
|
| }
|
|
|
| // Load the library.
|
| @@ -580,4 +524,9 @@ public class LibraryLoader {
|
| // Get the version of the native library. This is needed so that we can check we
|
| // have the right version before initializing the (rest of the) JNI.
|
| private native String nativeGetVersionNumber();
|
| +
|
| + // Finds the ranges corresponding to the native library pages, forks a new
|
| + // process to prefetch these pages and waits for it. The new process then
|
| + // terminates. This is blocking.
|
| + private static native boolean nativeForkAndPrefetchNativeLibrary();
|
| }
|
|
|