if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private",
"Shared", "Private", "Swapped", "Heap", "Heap", "Heap");
- printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "Dirty",
+ printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "",
"Clean", "Clean", "Dirty", "Size", "Alloc", "Free");
printRow(pw, HEAP_FULL_COLUMN, "", "------", "------", "------", "------",
"------", "------", "------", "------", "------", "------");
import dalvik.system.ZygoteHooks;
import android.system.ErrnoException;
import android.system.Os;
+import android.os.SystemClock;
+import android.util.Slog;
/** @hide */
public final class Zygote {
+ private static final String TAG = "Zygote";
/*
* Bit values for "debugFlags" argument. The definitions are duplicated
* in the native code.
*/
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose) {
+ long startTime = SystemClock.elapsedRealtime();
VM_HOOKS.preFork();
+ checkTime(startTime, "Zygote.preFork");
int pid = nativeForkAndSpecialize(
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose);
+ checkTime(startTime, "Zygote.nativeForkAndSpecialize");
VM_HOOKS.postForkCommon();
+ checkTime(startTime, "Zygote.postForkCommon");
return pid;
}
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose);
/**
+ * Temporary hack: check time since start time and log if over a fixed threshold.
+ *
+ */
+ private static void checkTime(long startTime, String where) {
+ long now = SystemClock.elapsedRealtime();
+ if ((now-startTime) > 1000) {
+ // If we are taking more than a second, log about it.
+ Slog.w(TAG, "Slow operation: " + (now-startTime) + "ms so far, now at " + where);
+ }
+ }
+
+ /**
* Special method to start the system server process. In addition to the
* common actions performed in forkAndSpecialize, the pid of the child
* process is recorded such that the death of the child process will cause
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
private static void callPostForkChildHooks(int debugFlags) {
+ long startTime = SystemClock.elapsedRealtime();
VM_HOOKS.postForkChild(debugFlags);
+ checkTime(startTime, "Zygote.callPostForkChildHooks");
}
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import libcore.io.IoUtils;
+import android.os.SystemClock;
+import android.util.Slog;
/**
* A connection that can make spawn requests.
}
/**
+ * Temporary hack: check time since start time and log if over a fixed threshold.
+ *
+ */
+ private void checkTime(long startTime, String where) {
+ long now = SystemClock.elapsedRealtime();
+ if ((now-startTime) > 1000) {
+ // If we are taking more than a second, log about it.
+ Slog.w(TAG, "Slow operation: " + (now-startTime) + "ms so far, now at " + where);
+ }
+ }
+
+ /**
* Returns the file descriptor of the associated socket.
*
* @return null-ok; file descriptor
*/
- FileDescriptor getFileDesciptor() {
+ FileDescriptor getFileDescriptor() {
return mSocket.getFileDescriptor();
}
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
+ long startTime = SystemClock.elapsedRealtime();
+
try {
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
return true;
}
+ checkTime(startTime, "zygoteConnection.runOnce: readArgumentList");
if (args == null) {
// EOF reached.
closeSocket();
", effective=0x" + Long.toHexString(parsedArgs.effectiveCapabilities));
}
+
applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext);
+ checkTime(startTime, "zygoteConnection.runOnce: apply security policies");
+
applyDebuggerSystemProperty(parsedArgs);
applyInvokeWithSystemProperty(parsedArgs);
+ checkTime(startTime, "zygoteConnection.runOnce: apply security policies");
+
int[][] rlimits = null;
if (parsedArgs.rlimits != null) {
fd = null;
+ checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize");
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose);
+ checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize");
} catch (IOException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (ErrnoException ex) {
} else if (index == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
- fds.add(newPeer.getFileDesciptor());
+ fds.add(newPeer.getFileDescriptor());
} else {
boolean done;
done = peers.get(index).runOnce();
#include <utils/String8.h>
#include <selinux/android.h>
#include <processgroup/processgroup.h>
+#include <inttypes.h>
#include "android_runtime/AndroidRuntime.h"
#include "JNIHelp.h"
}
}
+ // Temporary timing check.
+uint64_t MsTime() {
+ timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000) + now.tv_nsec / UINT64_C(1000000);
+}
+
+
+void ckTime(uint64_t start, const char* where) {
+ uint64_t now = MsTime();
+ if ((now-start) > 1000) {
+ // If we are taking more than a second, log about it.
+ ALOGW("Slow operation: %"PRIu64" ms in %s", (uint64_t)(now-start), where);
+ }
+}
+
// Utility routine to fork zygote and specialize the child process.
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
jint debug_flags, jobjectArray javaRlimits,
jint mount_external,
jstring java_se_info, jstring java_se_name,
bool is_system_server, jintArray fdsToClose) {
+ uint64_t start = MsTime();
SetSigChldHandler();
+ ckTime(start, "ForkAndSpecializeCommon:SetSigChldHandler");
pid_t pid = fork();
// The child process.
gMallocLeakZygoteChild = 1;
+
// Clean up any descriptors which must be closed immediately
DetachDescriptors(env, fdsToClose);
+ ckTime(start, "ForkAndSpecializeCommon:Fork and detach");
+
// Keep capabilities across UID change, unless we're staying root.
if (uid != 0) {
EnableKeepCapabilities(env);
UnsetSigChldHandler();
+ ckTime(start, "ForkAndSpecializeCommon:child process setup");
+
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags);
+ ckTime(start, "ForkAndSpecializeCommon:PostForkChildHooks returns");
if (env->ExceptionCheck()) {
ALOGE("Error calling post fork hooks.");
RuntimeAbort(env);