| /*** |
| * ASM performance test: measures the performances of asm package |
| * Copyright (c) 2002,2003 France Telecom |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of the copyright holders nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| package org.objectweb.asm.test.perf; |
| |
| import java.io.File; |
| import java.io.InputStream; |
| import java.io.FileOutputStream; |
| import java.util.Enumeration; |
| import java.util.zip.ZipEntry; |
| import java.util.zip.ZipFile; |
| import java.util.zip.ZipOutputStream; |
| |
| /** |
| * @author Eric Bruneton |
| */ |
| |
| public abstract class ALL extends ClassLoader { |
| |
| private static ZipFile zip; |
| |
| private static ZipOutputStream dst; |
| |
| private static int mode; |
| |
| private static int total; |
| |
| private static int totalSize; |
| |
| private static double[][] perfs; |
| |
| static boolean compute; |
| |
| static boolean skipDebug; |
| |
| public static void main (String[] args) throws Exception { |
| System.out.println("Comparing ASM, BCEL, SERP and Javassist performances..."); |
| System.out.println("This may take 20 to 30 minutes\n"); |
| // measures performances |
| System.out.println("ASM PERFORMANCES\n"); |
| new ASM().perfs(args); |
| double[][] asmPerfs = perfs; |
| System.out.println("\nBCEL PERFORMANCES\n"); |
| new BCEL().perfs(args); |
| double[][] bcelPerfs = perfs; |
| System.out.println("\nSERP PERFORMANCES\n"); |
| new SERP().perfs(args); |
| double[][] serpPerfs = perfs; |
| System.out.println("\nJavassist PERFORMANCES\n"); |
| new Javassist().perfs(args); |
| double[][] javassistPerfs = perfs; |
| |
| // prints results |
| System.out.println("\nGLOBAL RESULTS"); |
| System.out.println("\nWITH DEBUG INFORMATION\n"); |
| for (int step = 0; step < 2; ++step) { |
| for (mode = 0; mode < 4; ++mode) { |
| switch (mode) { |
| case 0: System.out.print("NO ADAPT: "); break; |
| case 1: System.out.print("NULL ADAPT: "); break; |
| case 2: System.out.print("COMPUTE MAXS: "); break; |
| default: System.out.print("ADD COUNTER: "); break; |
| } |
| System.out.print((float)asmPerfs[step][mode] + " ms"); |
| if (mode > 0) { |
| System.out.print(" (*"); |
| System.out.print((float)(asmPerfs[step][mode]/asmPerfs[step][0])); |
| System.out.print(")"); |
| } |
| System.out.print(" "); |
| System.out.print((float)bcelPerfs[step][mode] + " ms"); |
| if (mode > 0) { |
| System.out.print(" (*"); |
| System.out.print((float)(bcelPerfs[step][mode]/bcelPerfs[step][0])); |
| System.out.print(")"); |
| } |
| System.out.print(" "); |
| System.out.print((float)serpPerfs[step][mode] + " ms"); |
| if (mode > 0) { |
| System.out.print(" (*"); |
| System.out.print((float)(serpPerfs[step][mode]/serpPerfs[step][0])); |
| System.out.print(")"); |
| } |
| System.out.print(" "); |
| System.out.print((float)javassistPerfs[step][mode] + " ms"); |
| if (mode > 0) { |
| System.out.print(" (*"); |
| System.out.print((float)(javassistPerfs[step][mode]/javassistPerfs[step][0])); |
| System.out.print(")"); |
| } |
| System.out.println(); |
| } |
| if (step == 0) { |
| System.out.println("\nWITHOUT DEBUG INFORMATION\n"); |
| } |
| } |
| |
| System.out.println("\nRELATIVE RESULTS"); |
| System.out.println("\nWITH DEBUG INFORMATION\n"); |
| for (int step = 0; step < 2; ++step) { |
| System.err.println("[MEASURE ASM BCEL SERP Javassist]"); |
| for (mode = 1; mode < 4; ++mode) { |
| int base; |
| switch (mode) { |
| case 1: System.out.print("NULL ADAPT: "); base = 0; break; |
| case 2: System.out.print("COMPUTE MAXS: "); base = 1; break; |
| default: System.out.print("ADD COUNTER: "); base = 1; break; |
| } |
| double ref = asmPerfs[step][mode] - asmPerfs[step][base]; |
| System.out.print((float)ref + " ms "); |
| double f = bcelPerfs[step][mode] - bcelPerfs[step][base]; |
| System.out.print((float)f + " ms (*"); |
| System.out.print((float)(f/ref)); |
| System.out.print(") "); |
| double g = serpPerfs[step][mode] - serpPerfs[step][base]; |
| System.out.print((float)g + " ms (*"); |
| System.out.print((float)(g/ref)); |
| System.out.print(")"); |
| double h = javassistPerfs[step][mode] - javassistPerfs[step][base]; |
| System.out.print((float)h + " ms (*"); |
| System.out.print((float)(h/ref)); |
| System.out.print(")"); |
| System.out.println(); |
| } |
| if (step == 0) { |
| System.out.println("\nWITHOUT DEBUG INFORMATION\n"); |
| } |
| } |
| } |
| |
| void perfs (final String[] args) throws Exception { |
| // prepares zip files, if necessary |
| if (!(new File(args[0] + "classes1.zip").exists())) { |
| System.out.println("Preparing zip files from " + args[1] + "..."); |
| for (int step = 0; step < 2; ++step) { |
| dst = new ZipOutputStream( |
| new FileOutputStream(args[0] + "classes" + (step + 1) + ".zip")); |
| mode = step == 0 ? 1 : 4; |
| for (int i = 1; i < args.length; ++i) { |
| ALL loader = newInstance(); |
| zip = new ZipFile(args[i]); |
| Enumeration entries = zip.entries(); |
| while (entries.hasMoreElements()) { |
| String s = ((ZipEntry)entries.nextElement()).getName(); |
| if (s.endsWith(".class")) { |
| s = s.substring(0, s.length() - 6).replace('/', '.'); |
| loader.loadClass(s); |
| } |
| } |
| } |
| dst.close(); |
| dst = null; |
| } |
| System.out.println(); |
| } |
| |
| // measures performances |
| perfs = new double[2][4]; |
| System.out.println("FIRST STEP: WITH DEBUG INFORMATION"); |
| for (int step = 0; step < 2; ++step) { |
| zip = new ZipFile(args[0] + "classes" + (step + 1) + ".zip"); |
| for (mode = 0; mode < 4; ++mode) { |
| for (int i = 0; i < 4; ++i) { |
| ALL loader = newInstance(); |
| total = 0; |
| totalSize = 0; |
| Enumeration entries = zip.entries(); |
| double t = System.currentTimeMillis(); |
| while (entries.hasMoreElements()) { |
| String s = ((ZipEntry)entries.nextElement()).getName(); |
| if (s.endsWith(".class")) { |
| s = s.substring(0, s.length() - 6).replace('/', '.'); |
| loader.loadClass(s); |
| } |
| } |
| t = System.currentTimeMillis() - t; |
| if (i == 0) { |
| perfs[step][mode] = t; |
| } else { |
| perfs[step][mode] = Math.min(perfs[step][mode], t); |
| } |
| switch (mode) { |
| case 0: System.out.print("NO ADAPT: "); break; |
| case 1: System.out.print("NULL ADAPT: "); break; |
| case 2: System.out.print("COMPUTE MAXS: "); break; |
| default: System.out.print("ADD COUNTER: "); break; |
| } |
| System.out.print((float)t + " ms "); |
| System.out.print("(" + total + " classes"); |
| System.out.println(", " + totalSize + " bytes)"); |
| loader = null; |
| gc(); |
| } |
| } |
| if (step == 0) { |
| System.out.println("SECOND STEP: WITHOUT DEBUG INFORMATION"); |
| } |
| } |
| |
| // prints results |
| System.out.println("\nRESULTS"); |
| System.out.println("\nWITH DEBUG INFORMATION\n"); |
| for (int step = 0; step < 2; ++step) { |
| for (mode = 0; mode < 4; ++mode) { |
| switch (mode) { |
| case 0: System.out.print("NO ADAPT: "); break; |
| case 1: System.out.print("NULL ADAPT: "); break; |
| case 2: System.out.print("COMPUTE MAXS: "); break; |
| default: System.out.print("ADD COUNTER: "); break; |
| } |
| System.out.println((float)perfs[step][mode] + " ms"); |
| } |
| if (step == 0) { |
| System.out.println("\nWITHOUT DEBUG INFORMATION\n"); |
| } |
| } |
| } |
| |
| protected Class findClass (final String name) throws ClassNotFoundException { |
| try { |
| byte[] b; |
| String fileName = name.replace('.', '/') + ".class"; |
| InputStream is = zip.getInputStream(zip.getEntry(fileName)); |
| switch (mode) { |
| case 0: |
| b = new byte[is.available()]; |
| int len = 0; |
| while (true) { |
| int n = is.read(b, len, b.length - len); |
| if (n == -1) { |
| if (len < b.length) { |
| byte[] c = new byte[len]; |
| System.arraycopy(b, 0, c, 0, len); |
| b = c; |
| } |
| break; |
| } else { |
| len += n; |
| if (len == b.length) { |
| byte[] c = new byte[b.length + 1000]; |
| System.arraycopy(b, 0, c, 0, len); |
| b = c; |
| } |
| } |
| } |
| break; |
| case 1: |
| compute = false; |
| skipDebug = false; |
| b = nullAdaptClass(is, name); |
| break; |
| case 2: |
| compute = true; |
| skipDebug = false; |
| b = nullAdaptClass(is, name); |
| break; |
| case 3: |
| b = counterAdaptClass(is, name); |
| break; |
| //case 4: |
| default: |
| compute = false; |
| skipDebug = true; |
| b = nullAdaptClass(is, name); |
| break; |
| } |
| if (dst != null) { |
| dst.putNextEntry(new ZipEntry(fileName)); |
| dst.write(b, 0, b.length); |
| dst.closeEntry(); |
| } |
| total += 1; |
| totalSize += b.length; |
| return defineClass(name, b, 0, b.length); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| throw new ClassNotFoundException(name); |
| } |
| } |
| |
| private static void gc () { |
| try { |
| Runtime.getRuntime().gc(); |
| Thread.sleep(50); |
| Runtime.getRuntime().gc(); |
| Thread.sleep(50); |
| Runtime.getRuntime().gc(); |
| Thread.sleep(50); |
| } catch (InterruptedException e) { |
| } |
| } |
| |
| abstract ALL newInstance (); |
| |
| abstract byte[] nullAdaptClass (final InputStream is, final String name) |
| throws Exception; |
| |
| abstract byte[] counterAdaptClass (final InputStream is, final String name) |
| throws Exception; |
| } |