Groundwork for performance related tests

This commit is contained in:
Andy Clement
2014-02-06 13:38:04 -08:00
parent 7afa2a3da7
commit 8dff505b88
9 changed files with 192 additions and 21 deletions

View File

@@ -12,4 +12,4 @@ java.util.logging.ConsoleHandler.formatter = org.springsource.loaded.infra.SLFor
# java.util.logging.ConsoleHandler.level = OFF
# Set the default logging level for the logger named com.mycompany
org.springsource.level = ALL
org.springsource.level = FINEST

View File

@@ -159,6 +159,10 @@ public class SpringLoadedPreProcessor implements Constants {
boolean isReloadableTypeName = typeRegistry.isReloadableTypeName(slashedClassName, protectionDomain, bytes);
if (isReloadableTypeName && GlobalConfiguration.explainMode && log.isLoggable(Level.INFO)) {
log.info("[explanation] Based on the name, type "+slashedClassName+" is considered to be reloadable");
}
// logging causes a ClassCircularity problem when reporting on:
// SL: Type 'org/codehaus/groovy/grails/cli/logging/GrailsConsolePrintStream' is not being made reloadable
// if (GlobalConfiguration.verboseMode && isReloadableTypeName) {

View File

@@ -77,6 +77,21 @@ public class ReloadableTypeTests extends SpringLoadedTests {
assertEquals(7, r.returnValue);
}
@Test
public void removingStaticMethod() throws Exception {
String t = "remote.Perf1";
TypeRegistry typeRegistry = getTypeRegistry(t);
byte[] sc = loadBytesForClass(t);
ReloadableType rtype = typeRegistry.addType(t, sc);
Class<?> clazz = rtype.getClazz();
runUnguarded(clazz, "time");
rtype.loadNewVersion("002", retrieveRename(t, "remote.Perf2"));
runUnguarded(clazz, "time");
}
@Test
public void protectedFieldAccessors() throws Exception {
TypeRegistry tr = getTypeRegistry("prot.SubOne");

View File

@@ -37,6 +37,7 @@ public class ReloadingJVM {
String javaclasspath;
File testdataDirectory;
Process process;
private boolean debug = false;
DataInputStream reader;
DataOutputStream writer;
DataInputStream readerErrors;
@@ -65,8 +66,9 @@ public class ReloadingJVM {
agentJarLocation = search(searchLocation);
}
private ReloadingJVM(String agentOptions) {
private ReloadingJVM(String agentOptions, boolean debug) {
try {
this.debug = debug;
javaclasspath = System.getProperty("java.class.path");
// Create a temporary folder where we can load/replace class files for the file watcher to observe
@@ -81,7 +83,7 @@ public class ReloadingJVM {
if (DEBUG_CLIENT_SIDE) {
System.out.println("(client) Classpath for JVM that is being launched: " + javaclasspath);
}
String OPTS = "";//"-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=4000,server=y,suspend=y";
String OPTS = debug?"-Xdebug -Xrunjdwp:transport=dt_socket,address=5100,server=y,suspend=y":"";
String AGENT_OPTION_STRING = "";
if (agentOptions!=null && agentOptions.length()>0) {
AGENT_OPTION_STRING = "-Dspringloaded="+agentOptions;
@@ -93,6 +95,9 @@ public class ReloadingJVM {
writer = new DataOutputStream(process.getOutputStream());
reader = new DataInputStream(process.getInputStream());
readerErrors = new DataInputStream(process.getErrorStream());
if (debug) {
System.out.println("Debugging launched VM, port 5000");
}
JVMOutput text = waitFor("ReloadingJVM:started");
if (DEBUG_CLIENT_SIDE) {
System.out.println(text);
@@ -103,9 +108,14 @@ public class ReloadingJVM {
}
public static ReloadingJVM launch(String options) {
return new ReloadingJVM(options);
return new ReloadingJVM(options,false);
}
public static ReloadingJVM launch(String options,boolean debug) {
return new ReloadingJVM(options,debug);
}
private JVMOutput waitFor(String message) {
return captureOutput(message);
}
@@ -144,25 +154,28 @@ public class ReloadingJVM {
private JVMOutput captureOutput(String terminationString) {
try {
long time = System.currentTimeMillis();
int timeout = 1000; // 1s timeout
int timeout = 1000+(debug?60000:0); // 1s timeout
byte[] buf = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((System.currentTimeMillis() - time) < timeout) {
while (reader.available() != 0) {
int read = reader.read(buf);
boolean found = false;
while ((System.currentTimeMillis() - time) < timeout && !found) {
// System.out.println("Waiting on ["+terminationString+"] so far: ["+baos.toString()+"]");
while (readerErrors.available() != 0) {
int read = readerErrors.read(buf);
baos.write(buf, 0, read);
if (baos.toString().indexOf(terminationString) != -1) {
break;
}
}
}
String stdout = baos.toString();
baos = new ByteArrayOutputStream();
while (readerErrors.available() != 0) {
int read = readerErrors.read(buf);
baos.write(buf, 0, read);
if (baos.toString().indexOf(terminationString) != -1) {
found = true;
}
try { Thread.sleep(100); } catch (Exception e) {}
}
String stderr = baos.toString();
baos = new ByteArrayOutputStream();
while (reader.available() != 0) {
int read = reader.read(buf);
baos.write(buf, 0, read);
}
String stdout = baos.toString();
if (DEBUG_CLIENT_SIDE) {
System.out.println("(client) >> received \n== STDOUT ==\n" + stdout + "\n== STDERR==\n" + stderr);
}

View File

@@ -36,7 +36,7 @@ import org.springsource.loaded.TypeRegistry;
*/
public class ReloadingJVMCommandProcess {
public static void main(String[] argv) throws IOException {
System.err.println("(jvm) started");
System.err.println("ReloadingJVM:started");System.err.flush();
try {
DataInputStream br = new DataInputStream((System.in));
do {
@@ -52,6 +52,7 @@ public class ReloadingJVMCommandProcess {
// String[] args = (arguments.size() > 0 ? arguments.toArray(new String[arguments.size()]) : null);
if (commandName.equals("exit")) {
System.err.println("ReloadingJVM:terminating!!");
System.exit(0);
return;
} else if (commandName.equals("echo")) {
echoCommand(arguments);
@@ -133,6 +134,7 @@ public class ReloadingJVMCommandProcess {
Class<?> clazz = o.getClass();
Method m = clazz.getDeclaredMethod(methodName);
m.invoke(o);
System.err.println("!!");
} catch (Exception e) {
e.printStackTrace(System.out);
}
@@ -148,6 +150,7 @@ public class ReloadingJVMCommandProcess {
if (!b) {
throw new IllegalStateException("Failed to reload new verion of "+classname);
}
System.err.println("!!");
} catch (Exception e) {
e.printStackTrace(System.out);
}
@@ -167,9 +170,9 @@ public class ReloadingJVMCommandProcess {
System.err.println("(jvm) creating new instance '" + instanceName + "' of type '" + classname + "'");
Class<?> clazz = Class.forName(classname);
instances.put(instanceName, clazz.newInstance());
System.err.println("(jvm) instance successfully created");
System.err.println("(jvm) instance successfully created!!");
} catch (Exception e) {
System.out.println("(jvm) failed to create instance " + e.getMessage());
System.out.println("(jvm) failed to create instance " + e.getMessage()+"!!");
e.printStackTrace(System.out);
}

View File

@@ -95,6 +95,8 @@ public abstract class SpringLoadedTests implements Constants {
protected String GroovyTestDataPath = TestUtils.getPathToClasses("../testdata-groovy");
protected String AspectjrtJar = "../testdata/aspectjrt.jar";
protected String CodeJar = "../testdata/code.jar";
// TODO [java8] replace this with project dependency when Java8 is out
protected String Java8CodeJar = "../testdata-java8/build/libs/testdata-java8.jar";
protected String GroovyrtJar = "../testdata-groovy/groovy-1.8.2.jar";
protected Result result;
protected TypeRegistry registry;
@@ -103,7 +105,7 @@ public abstract class SpringLoadedTests implements Constants {
public void setup() throws Exception {
SpringLoadedPreProcessor.disabled = true;
NameRegistry.reset();
binLoader = new TestClassLoader(toURLs(TestDataPath, AspectjrtJar,CodeJar), this.getClass().getClassLoader());
binLoader = new TestClassLoader(toURLs(TestDataPath, AspectjrtJar, CodeJar, Java8CodeJar), this.getClass().getClassLoader());
}
@After

View File

@@ -80,6 +80,36 @@ public class SpringLoadedTestsInSeparateJVM extends SpringLoadedTests {
assertStdout("jvmtwo.Runner.run1() running", jvm.call("a", "run1"));
}
@Test
public void reloadedPerformance() throws Exception {
// debug();
jvm.newInstance("a","remote.Perf1");
JVMOutput jo = jvm.call("a","time"); // 75ms
jo = jvm.call("a","time"); // 75ms
pause(5);
jvm.updateClass("remote.Perf1",retrieveRename("remote.Perf1","remote.Perf2"));
pause(2);
// In Perf2 the static method is gone, why does it give us a NSME?
jo = jvm.call("a","time"); // 150ms
System.out.println(jo);
}
private final static void debug() {
jvm.shutdown();
jvm = ReloadingJVM.launch("",true);
}
private final static void debug(String options) {
jvm = ReloadingJVM.launch(options,true);
}
private final static void pause(int seconds) {
try {
Thread.sleep(seconds*1000);
} catch (Exception e) {}
}
@Test
public void testReloadingInOtherVM() throws Exception {
jvm.newInstance("a", "remote.One");

View File

@@ -0,0 +1,55 @@
package remote;
import java.util.Random;
public class Perf1 {
int repeats = 100;
public static void main(String[] args) {
time();
}
public static void time() {
timedrun();
timedrun();
timedrun();
}
private static void timedrun() {
long stime = System.currentTimeMillis();
System.out.println(computepi(10000000));
long etime = System.currentTimeMillis();
System.out.println("took "+(etime-stime)+"ms");
}
public static double computepi(int iterations) {
Random randomGen = new Random(System.currentTimeMillis());
int insideCount = 0;
for (int i = 1; i <= iterations; i++) {
insideCount += doOneIteration(randomGen);
}
return calc(iterations, insideCount);
}
private static int doOneIteration(Random randomGen) {
double xPos = getRandom(randomGen);
double yPos = getRandom(randomGen);
return isInside( xPos, yPos);
}
private static int isInside( double xPos, double yPos) {
double distance = Math.sqrt((xPos * xPos) + (yPos * yPos));
if (distance<1.0) return 1;
else return 0;
}
private static double getRandom(Random randomGen) {
return (randomGen.nextDouble()) * 2 - 1.0;
}
private static double calc(int iterations, int insideCount) {
return 4.0 * (insideCount / (double)iterations);
}
}

View File

@@ -0,0 +1,49 @@
package remote;
import java.util.Random;
public class Perf2 {
int repeats = 100;
public static void main(String[] args) {
time();
}
public static void time() {
long stime = System.currentTimeMillis();
System.out.println(computepi(1000000));
long etime = System.currentTimeMillis();
System.out.println("took "+(etime-stime)+"ms");
}
public static double computepi(int iterations) {
Random randomGen = new Random(System.currentTimeMillis());
int insideCount = 0;
for (int i = 1; i <= iterations; i++) {
insideCount += doOneIteration(randomGen);
}
return calc(iterations, insideCount);
}
private static int doOneIteration(Random randomGen) {
double xPos = getRandom(randomGen);
double yPos = getRandom(randomGen);
return isInside( xPos, yPos);
}
private static int isInside( double xPos, double yPos) {
double distance = Math.sqrt((xPos * xPos) + (yPos * yPos));
if (distance<1.0) return 1;
else return 0;
}
private static double getRandom(Random randomGen) {
return (randomGen.nextDouble()) * 2 - 1.0;
}
private static double calc(int iterations, int insideCount) {
return 4.0 * (insideCount / (double)iterations);
}
}