From bbbe552a31f7229708bfc748480ce538218ae076 Mon Sep 17 00:00:00 2001 From: buzbee Date: Thu, 23 May 2013 13:53:50 -0700 Subject: [PATCH] JIT tuning; set cache size on command line The tuning knobs for triggering trace compilation for the JIT had not been revisited for several years. In that time, the working set of some applications have significantly increased, leading to frequent cache overlows & flushes. This CL adds the ability to set the maximum size of the JIT's cache on the command line, and we expect to use different settings depending on device configuration (rule of thumb: 1K for each 1M for system RAM, with 2M limit). Additionally, the trace compilation trigger has been tightened to limit the compilation of cold traces. Change-Id: Ice22c5d9d46a93e465c57dd83f50ca3912f1672e --- vm/Globals.h | 4 +++- vm/Init.cpp | 4 ++++ vm/compiler/Compiler.cpp | 2 +- vm/compiler/codegen/arm/Assemble.cpp | 2 ++ vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.cpp | 8 +++++++- vm/compiler/codegen/arm/armv5te/ArchVariant.cpp | 8 +++++++- vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.cpp | 8 +++++++- vm/compiler/codegen/arm/armv7-a/ArchVariant.cpp | 8 +++++++- vm/compiler/codegen/mips/mips/ArchVariant.cpp | 6 +++++- vm/compiler/codegen/x86/CodegenInterface.cpp | 6 +++++- vm/interp/InterpState.h | 2 +- 11 files changed, 49 insertions(+), 9 deletions(-) diff --git a/vm/Globals.h b/vm/Globals.h index 234a57d84..5854dbdec 100644 --- a/vm/Globals.h +++ b/vm/Globals.h @@ -738,6 +738,8 @@ extern struct DvmGlobals gDvm; #if defined(WITH_JIT) +#define DEFAULT_CODE_CACHE_SIZE 0xffffffff + /* Trace profiling modes. Ordering matters - off states before on states */ enum TraceProfilingModes { kTraceProfilingDisabled = 0, // Not profiling @@ -802,7 +804,7 @@ struct DvmJitGlobals { /* How many entries in the JitEntryTable are in use */ unsigned int jitTableEntriesUsed; - /* Bytes allocated for the code cache */ + /* Max bytes allocated for the code cache. Rough rule of thumb: 1K per 1M of system RAM */ unsigned int codeCacheSize; /* Trigger for trace selection */ diff --git a/vm/Init.cpp b/vm/Init.cpp index bcb2824ae..6719e1c12 100644 --- a/vm/Init.cpp +++ b/vm/Init.cpp @@ -141,6 +141,7 @@ static void usage(const char* progName) "[,hexopvalue[-endvalue]]*\n"); dvmFprintf(stderr, " -Xincludeselectedmethod\n"); dvmFprintf(stderr, " -Xjitthreshold:decimalvalue\n"); + dvmFprintf(stderr, " -Xjitcodecachesize:decimalvalueofkbytes\n"); dvmFprintf(stderr, " -Xjitblocking\n"); dvmFprintf(stderr, " -Xjitmethod:signature[,signature]* " "(eg Ljava/lang/String\\;replace)\n"); @@ -1126,6 +1127,8 @@ static int processOptions(int argc, const char* const argv[], gDvmJit.blockingMode = true; } else if (strncmp(argv[i], "-Xjitthreshold:", 15) == 0) { gDvmJit.threshold = atoi(argv[i] + 15); + } else if (strncmp(argv[i], "-Xjitcodecachesize:", 19) == 0) { + gDvmJit.codeCacheSize = atoi(argv[i] + 19) * 1024; } else if (strncmp(argv[i], "-Xincludeselectedop", 19) == 0) { gDvmJit.includeSelectedOp = true; } else if (strncmp(argv[i], "-Xincludeselectedmethod", 23) == 0) { @@ -1281,6 +1284,7 @@ static void setCommandLineDefaults() gDvmJit.includeSelectedOffset = false; gDvmJit.methodTable = NULL; gDvmJit.classTable = NULL; + gDvmJit.codeCacheSize = DEFAULT_CODE_CACHE_SIZE; gDvm.constInit = false; gDvm.commonInit = false; diff --git a/vm/compiler/Compiler.cpp b/vm/compiler/Compiler.cpp index 188027f3d..fbde41f5b 100644 --- a/vm/compiler/Compiler.cpp +++ b/vm/compiler/Compiler.cpp @@ -182,7 +182,7 @@ bool dvmCompilerSetupCodeCache(void) MAP_PRIVATE , fd, 0); close(fd); if (gDvmJit.codeCache == MAP_FAILED) { - ALOGE("Failed to mmap the JIT code cache: %s", strerror(errno)); + ALOGE("Failed to mmap the JIT code cache of size %d: %s", gDvmJit.codeCacheSize, strerror(errno)); return false; } diff --git a/vm/compiler/codegen/arm/Assemble.cpp b/vm/compiler/codegen/arm/Assemble.cpp index 7406d3e88..ac4e64c11 100644 --- a/vm/compiler/codegen/arm/Assemble.cpp +++ b/vm/compiler/codegen/arm/Assemble.cpp @@ -2148,6 +2148,8 @@ void dvmCompilerSortAndPrintTraceProfiles() } ALOGD("JIT: Average execution count -> %d",(int)(sum / numTraces)); + // How efficiently are we using code cache memory? Bigger is better. + ALOGD("JIT: CodeCache efficiency -> %.2f",(float)sum / (float)gDvmJit.codeCacheByteUsed); /* Dump the sorted entries. The count of each trace will be reset to 0. */ for (i=0; i < gDvmJit.jitTableSize; i++) { diff --git a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.cpp b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.cpp index 713ecfa10..6c89b11e9 100644 --- a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.cpp +++ b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.cpp @@ -55,7 +55,13 @@ bool dvmCompilerArchVariantInit(void) if (gDvmJit.threshold == 0) { gDvmJit.threshold = 200; } - gDvmJit.codeCacheSize = 512*1024; + if (gDvmJit.codeCacheSize == DEFAULT_CODE_CACHE_SIZE) { + gDvmJit.codeCacheSize = 512 * 1024; + } else if ((gDvmJit.codeCacheSize == 0) && (gDvm.executionMode == kExecutionModeJit)) { + gDvm.executionMode = kExecutionModeInterpFast; + } + /* Hard limit for Arm of 2M */ + assert(gDvmJit.codeCacheSize <= 2 * 1024 * 1024); #if defined(WITH_SELF_VERIFICATION) /* Force into blocking mode */ diff --git a/vm/compiler/codegen/arm/armv5te/ArchVariant.cpp b/vm/compiler/codegen/arm/armv5te/ArchVariant.cpp index 25d650e6d..5c7fbbe41 100644 --- a/vm/compiler/codegen/arm/armv5te/ArchVariant.cpp +++ b/vm/compiler/codegen/arm/armv5te/ArchVariant.cpp @@ -55,7 +55,13 @@ bool dvmCompilerArchVariantInit(void) if (gDvmJit.threshold == 0) { gDvmJit.threshold = 200; } - gDvmJit.codeCacheSize = 512*1024; + if (gDvmJit.codeCacheSize == DEFAULT_CODE_CACHE_SIZE) { + gDvmJit.codeCacheSize = 512 * 1024; + } else if ((gDvmJit.codeCacheSize == 0) && (gDvm.executionMode == kExecutionModeJit)) { + gDvm.executionMode = kExecutionModeInterpFast; + } + /* Hard limit for Arm of 2M */ + assert(gDvmJit.codeCacheSize <= 2 * 1024 * 1024); #if defined(WITH_SELF_VERIFICATION) /* Force into blocking mode */ diff --git a/vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.cpp b/vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.cpp index 40ee04072..324c39879 100644 --- a/vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.cpp +++ b/vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.cpp @@ -50,7 +50,13 @@ bool dvmCompilerArchVariantInit(void) if (gDvmJit.threshold == 0) { gDvmJit.threshold = 40; } - gDvmJit.codeCacheSize = 1024*1024; + if (gDvmJit.codeCacheSize == DEFAULT_CODE_CACHE_SIZE) { + gDvmJit.codeCacheSize = 1500 * 1024; + } else if ((gDvmJit.codeCacheSize == 0) && (gDvm.executionMode == kExecutionModeJit)) { + gDvm.executionMode = kExecutionModeInterpFast; + } + /* Hard limit for Arm of 2M */ + assert(gDvmJit.codeCacheSize <= 2 * 1024 * 1024); #if defined(WITH_SELF_VERIFICATION) /* Force into blocking */ diff --git a/vm/compiler/codegen/arm/armv7-a/ArchVariant.cpp b/vm/compiler/codegen/arm/armv7-a/ArchVariant.cpp index 40ee04072..324c39879 100644 --- a/vm/compiler/codegen/arm/armv7-a/ArchVariant.cpp +++ b/vm/compiler/codegen/arm/armv7-a/ArchVariant.cpp @@ -50,7 +50,13 @@ bool dvmCompilerArchVariantInit(void) if (gDvmJit.threshold == 0) { gDvmJit.threshold = 40; } - gDvmJit.codeCacheSize = 1024*1024; + if (gDvmJit.codeCacheSize == DEFAULT_CODE_CACHE_SIZE) { + gDvmJit.codeCacheSize = 1500 * 1024; + } else if ((gDvmJit.codeCacheSize == 0) && (gDvm.executionMode == kExecutionModeJit)) { + gDvm.executionMode = kExecutionModeInterpFast; + } + /* Hard limit for Arm of 2M */ + assert(gDvmJit.codeCacheSize <= 2 * 1024 * 1024); #if defined(WITH_SELF_VERIFICATION) /* Force into blocking */ diff --git a/vm/compiler/codegen/mips/mips/ArchVariant.cpp b/vm/compiler/codegen/mips/mips/ArchVariant.cpp index d720f85af..10f5da10d 100644 --- a/vm/compiler/codegen/mips/mips/ArchVariant.cpp +++ b/vm/compiler/codegen/mips/mips/ArchVariant.cpp @@ -55,7 +55,11 @@ bool dvmCompilerArchVariantInit(void) if (gDvmJit.threshold == 0) { gDvmJit.threshold = 200; } - gDvmJit.codeCacheSize = 512*1024; + if (gDvmJit.codeCacheSize == DEFAULT_CODE_CACHE_SIZE) { + gDvmJit.codeCacheSize = 512 * 1024; + } else if ((gDvmJit.codeCacheSize == 0) && (gDvm.executionMode == kExecutionModeJit)) { + gDvm.executionMode = kExecutionModeInterpFast; + } #if defined(WITH_SELF_VERIFICATION) /* Force into blocking mode */ diff --git a/vm/compiler/codegen/x86/CodegenInterface.cpp b/vm/compiler/codegen/x86/CodegenInterface.cpp index 46f097971..451c5e537 100644 --- a/vm/compiler/codegen/x86/CodegenInterface.cpp +++ b/vm/compiler/codegen/x86/CodegenInterface.cpp @@ -67,7 +67,11 @@ bool dvmCompilerArchInit() { if (gDvmJit.threshold == 0) { gDvmJit.threshold = 255; } - gDvmJit.codeCacheSize = 512*1024; + if (gDvmJit.codeCacheSize == DEFAULT_CODE_CACHE_SIZE) { + gDvmJit.codeCacheSize = 512 * 1024; + } else if ((gDvmJit.codeCacheSize == 0) && (gDvm.executionMode == kExecutionModeJit)) { + gDvm.executionMode = kExecutionModeInterpFast; + } gDvmJit.optLevel = kJitOptLevelO1; //Disable Method-JIT diff --git a/vm/interp/InterpState.h b/vm/interp/InterpState.h index cc0a13fb9..eaac33766 100644 --- a/vm/interp/InterpState.h +++ b/vm/interp/InterpState.h @@ -191,7 +191,7 @@ enum SelfVerificationState { /* Number of entries in the 2nd level JIT profiler filter cache */ #define JIT_TRACE_THRESH_FILTER_SIZE 32 /* Number of low dalvik pc address bits to include in 2nd level filter key */ -#define JIT_TRACE_THRESH_FILTER_PC_BITS 4 +#define JIT_TRACE_THRESH_FILTER_PC_BITS 16 #define MAX_JIT_RUN_LEN 64 enum JitHint { -- 2.11.0