Package org.ow2.asm

Source Code of org.ow2.asm.ALLPerfTest$RunTest

/***
* ASM performance test: measures the performances of asm package
* Copyright (c) 2002-2005 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.ow2.asm;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.verifier.structurals.ModifiedPass3bVerifier;
import org.ow2.asm.commons.EmptyVisitor;
import org.ow2.asm.commons.LocalVariablesSorter;
import org.ow2.asm.tree.ClassNode;
import org.ow2.asm.tree.MethodNode;
import org.ow2.asm.tree.analysis.Analyzer;
import org.ow2.asm.tree.analysis.BasicValue;
import org.ow2.asm.tree.analysis.SimpleVerifier;
import serp.bytecode.BCClass;
import serp.bytecode.BCMethod;
import serp.bytecode.Code;
import serp.bytecode.Project;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
* @author Eric Bruneton
* @author Peter Lawrey
*/
public abstract class ALLPerfTest {

    static boolean compute;

    static boolean computeFrames;

    static boolean skipDebug;

    static int repeats;

    static List<byte[]> classes = new ArrayList<byte[]>();

    static List<String> classNames = new ArrayList<String>();

    private static final int MAX_ITERATION_SEC = Integer.getInteger("max.iteration.sec",
            10)
            .intValue();

    public static void main(final String[] args)
            throws IOException, InterruptedException
    {
        String clazz = System.getProperty("asm.test.class");
        List<String> jars = findFiles(System.getProperty("java.home"), ".jar");
        jars.addAll(findJars(File.pathSeparatorChar,
                System.getProperty("java.class.path")));
        repeats = Integer.getInteger("repeats", 3).intValue() + 1;

        Set<String> classesFound = new HashSet<String>();
        for (int i = 0; i < jars.size(); i++) {
            ZipFile zip;
            try {
                zip = new ZipFile(jars.get(i));
            } catch (IOException e) {
                System.err.println("Error openning " + jars.get(i));
                e.printStackTrace();
                continue;
            }

            Enumeration<? extends ZipEntry> entries = zip.entries();
            while (entries.hasMoreElements()) {
                ZipEntry e = entries.nextElement();
                String s = e.getName();
                if (s.endsWith(".class")) {
                    s = s.substring(0, s.length() - 6).replace('/', '.');
                    if (!classesFound.add(s)) {
                        continue;
                    }
                    if (clazz == null || s.indexOf(clazz) != -1) {
                        InputStream is = zip.getInputStream(e);
                        byte[] bytes = new ClassReader(is).b;
                        classes.add(bytes);
                        classNames.add(s);
                        is.close();
                        if (classes.size() % 2500 == 0) {
                            System.out.println("... searching, found "
                                    + classes.size() + " classes.");
                        }
                    }
                }
            }
            zip.close();
        }
        System.out.println("Found " + classes.size() + " classes.");

        RunTest nullBCELAdapt = new RunTest() {
            @Override
            public void test(byte[] bytes, int[] errors) throws IOException {
                nullBCELAdapt(bytes);
            }
        };

        RunTest nullAspectjBCELAdapt = new RunTest() {
            @Override
            public void test(byte[] bytes, int[] errors) throws IOException {
                nullAspectjBCELAdapt(bytes);
            }
        };

        RunTest nullJavassistAdapt = new RunTest() {
            ClassPool pool;
            @Override
            public void init() {
                pool = new ClassPool(null);               
            }
            @Override
            public void test(byte[] bytes, int[] errors) throws Exception {
                nullJavassistAdapt(pool, bytes);
            }
        };

        RunTest nullSERPAdapt = new RunTest() {
            Project p;
            BCClass c;
            @Override
            public void init() {
                p = new Project();
                c = null;
            }
            @Override
            public void test(byte[] bytes, int[] errors) throws Exception {
                c = nullSERPAdapt(p, c, bytes);
            }
        };

        // get class info and deserialize tests
       
        runTestAll("get class info", "", new RunTest() {
            @Override
            public void test(byte[] bytes, int[] errors) {
                ClassReader cr = new ClassReader(bytes);
                cr.getAccess();
                cr.getClassName();
                cr.getSuperName();
                cr.getInterfaces();
            }
        });
       
        runTestAll("deserialize", "", new RunTest() {
            @Override
            public void test(byte[] bytes, int[] errors) {
                new ClassReader(bytes).accept(new EmptyVisitor(), 0);
            }
        });

        runTest("deserialize", "tree package", new RunTest() {
            @Override
            public void test(byte[] bytes, int[] errors) {
                new ClassReader(bytes).accept(new ClassNode(), 0);
            }
        });
       
        System.out.println();

        // deserialize and reserialize tests

        runTestAll("deserialize and reserialize", "", new RunTest() {
            @Override
            public void test(byte[] bytes, int[] errors) {
                ClassReader cr = new ClassReader(bytes);
                ClassWriter cw = new ClassWriter(0);
                cr.accept(cw, 0);
                cw.toByteArray();
            }
        });

        runTestAll("deserialize and reserialize",
                "copyPool",
                new RunTest() {
                    @Override
                    public void test(byte[] bytes, int[] errors) {
                        ClassReader cr = new ClassReader(bytes);
                        ClassWriter cw = new ClassWriter(cr, 0);
                        cr.accept(cw, 0);
                        cw.toByteArray();
                    }
                });

        runTest("deserialize and reserialize",
                "tree package",
                new RunTest() {
                    @Override
                    public void test(byte[] bytes, int[] errors) {
                        ClassWriter cw = new ClassWriter(0);
                        ClassNode cn = new ClassNode();
                        new ClassReader(bytes).accept(cn, 0);
                        cn.accept(cw);
                        cw.toByteArray();
                    }
                });

        compute = false;
        computeFrames = false;
       
        runTest("deserialize and reserialize", "BCEL", nullBCELAdapt);

        runTest("deserialize and reserialize",
                "Aspectj BCEL",
                nullAspectjBCELAdapt);
       
        runTest("deserialize and reserialize",
                "Javassist",
                nullJavassistAdapt);

        runTest("deserialize and reserialize",
                "SERP",
                nullSERPAdapt);

        System.out.println();

        // deserialize and reserialize tests with computeMaxs

        runTest("deserialize and reserialize",
                "computeMaxs",
                new RunTest() {
                    @Override
                    public void test(byte[] bytes, int[] errors) {
                        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
                        new ClassReader(bytes).accept(cw, 0);
                        cw.toByteArray();
                    }
                });

        compute = true;
        computeFrames = false;

        runTest("deserialize and reserialize",
                "BCEL and computeMaxs",
                nullBCELAdapt);

        runTest("deserialize and reserialize",
                "Aspectj BCEL and computeMaxs",
                nullAspectjBCELAdapt);
       
        // misc. tests

        runTest("deserialize and reserialize",
                "LocalVariablesSorter",
                new RunTest() {
                    @Override
                    public void test(byte[] bytes, int[] errors) {
                        ClassWriter cw = new ClassWriter(0);
                        new ClassReader(bytes).accept(new ClassAdapter(cw) {

                            @Override
                            public MethodVisitor visitMethod(
                                final int access,
                                final String name,
                                final String desc,
                                final String signature,
                                final String[] exceptions)
                            {
                                return new LocalVariablesSorter(access,
                                        desc,
                                        cv.visitMethod(access,
                                                name,
                                                desc,
                                                signature,
                                                exceptions));
                            }
                        }, ClassReader.EXPAND_FRAMES);
                        cw.toByteArray();
                    }
                });

        // This test repeatedly tests the same classes as SimpleVerifier
        // actually calls Class.forName() on the class which fills the PermGen
        runTestSome("analyze", "SimpleVerifier", new RunTest() {
            @Override
            public void test(byte[] bytes, int[] errors) {
                ClassReader cr = new ClassReader(bytes);
                ClassNode cn = new ClassNode();
                cr.accept(cn, ClassReader.SKIP_DEBUG);
                 List<MethodNode> methods = cn.methods;
                for (int k = 0; k < methods.size(); ++k) {
                    MethodNode method = methods.get(k);
                    Analyzer<?> a = new Analyzer<BasicValue>(new SimpleVerifier());
                    try {
                        a.analyze(cn.name, method);
                    } catch (Throwable th) {
                        // System.err.println(th);
                        ++errors[0];
                    }
                }
            }
        });

        System.out.println();
       
        // deserialize and reserialize tests with computeFrames

        runTest("deserialize and reserialize",
                "computeFrames",
                new RunTest() {
                    @Override
                    public void test(byte[] bytes, int[] errors) {
                        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
                        new ClassReader(bytes).accept(cw, 0);
                        cw.toByteArray();
                    }
                });

        // the BCEL+computeFrames tests must be done only at the end, because
        // after them other tests run very slowly, for some unknown reason
        // (memory usage?)
        compute = false;
        computeFrames = true;
        runTest("deserialize and reserialize",
                "BCEL and computeFrames",
                nullBCELAdapt);

        runTest("deserialize and reserialize",
                "Aspectj BCEL and computeFrames",
                nullAspectjBCELAdapt);
    }

    public static List<String> findFiles(String directory, String suffix) {
        List<String> matches = new ArrayList<String>();
        findFiles(matches, new File(directory), suffix);
        return matches;
    }

    static void findFiles(List<String> matches, File directory, String suffix) {
        File[] files = directory.listFiles();
        for (int i = 0; i < files.length; i++) {
            File file = files[i];
            if (file.isDirectory()) {
                findFiles(matches, file, suffix);
            } else if (file.getName().endsWith(suffix)) {
                matches.add(file.getAbsolutePath());
            }
        }
    }

    static abstract class RunTest {

        public void init() {           
        }
       
        public abstract void test(byte[] bytes, int[] errors) throws Exception;
    }

    static void runTestAll(
        String testName,
        String with,
        RunTest runTest) throws InterruptedException
    {
        runTest0(1, true, testName, with, runTest);
    }

    static void runTest(
        String testName,
        String with,
        RunTest runTest) throws InterruptedException
    {
        runTest0(repeats - 1, false, testName, with, runTest);
    }

    static void runTestSome(
        String testName,
        String with,
        RunTest runTest) throws InterruptedException
    {
        runTest0(repeats - 1, true, testName, with, runTest);
    }

    private static void runTest0(
        int testSkip,
        boolean startAtZero,
        String testName,
        String with,
        RunTest runTest) throws InterruptedException
    {
        if (with.length() > 0) {
            with = " with " + with;
        }
        boolean skipBigClasses = with.contains("BCEL and computeFrames");
        int totalCount = 0;
        long totalSize = 0;
        long totalTime = 0;
        System.out.println("\nStarting " + testName + with + " test.");
        for (int i = 0; i < repeats; ++i) {
            runTest.init();
            long t = System.currentTimeMillis();
            int count = 0;
            long size = 0;
            int[] errors = { 0 };
            long longest = 0;
            int longestSize = 0;
            int skipped = 0;
            for (int j = startAtZero ? 0 : i; j < classes.size(); j += testSkip)
            {
                count++;
                byte[] b = classes.get(j);
                if (skipBigClasses && b.length > 16 * 1024) {
                    skipped++;
                    continue;
                }
                size += b.length;
                try {
                    long start = System.currentTimeMillis();
                    runTest.test(b, errors);
                    long end = System.currentTimeMillis();
                    long time = end - start;
                    if (longest < time) {
                        longest = time;
                        longestSize = b.length;
                    }
                    if (time > MAX_ITERATION_SEC * 1000 / 10) {
                        System.out.println("--- time to " + testName
                                + " the class " + classNames.get(j) + with
                                + " took " + time + " ms. bytes=" + b.length);
                    }
                    if (end - t > MAX_ITERATION_SEC * 1000) {
                        // System.out.println("Stopping iteration due to a
                        // longer run time.");
                        break;
                    }
                } catch (Exception ignored) {
                    errors[0]++;
                } catch (Throwable e) {
                    System.err.println(classNames.get(j) + ": " + e);
                    errors[0]++;
                }
            }
            t = System.currentTimeMillis() - t;
            String errorStr = errors[0] > 0
                    ? " (" + errors[0] + " errors)"
                    : "";
            String skippedStr = skipped == 0
                    ? ""
                    : " ("
                            + skipped
                            + " skipped as BCEL/computeFrames on >16K classes is very slow)";
            String longestStr = "";
            if (longest > 50) {
                longestStr = " the longest took " + longest + " ms (" + longestSize + " bytes)";
            }
            if (i > 0) {
                System.out.println("- to " + testName + ' ' + count
                        + " classes" + with + " = " + t + " ms" + errorStr
                        + longestStr + skippedStr + '.');
                totalCount += count;
                totalSize += size;
                totalTime += t;
            }
        }
        System.out.println("Time to " + testName + ' ' + totalCount
                + " classes" + with + " = " + totalTime + " ms.\n"
                + "Processing rate = " + totalCount * 1000 / totalTime
                + " classes per sec (" + totalSize * 1000 / totalTime / 1024
                + " kB per sec).");
        System.gc();
        Thread.sleep(2500);
    }

    private static List<String> findJars(char pathSeparatorChar, String s) {
        List<String> ret = new ArrayList<String>();
        int start = 0;
        int pos = s.indexOf(pathSeparatorChar);
        while (pos >= 0) {
            String name = s.substring(start, pos);
            if (name.endsWith(".jar")) {
                ret.add(name);
            }
            start = pos + 1;
            pos = s.indexOf(pathSeparatorChar, start);
        }
        return ret;
    }

    static void nullBCELAdapt(final byte[] b) throws IOException {
        JavaClass jc = new ClassParser(new ByteArrayInputStream(b),
                "class-name").parse();
        ClassGen cg = new ClassGen(jc);
        ConstantPoolGen cp = cg.getConstantPool();
        Method[] ms = cg.getMethods();
        for (int k = 0; k < ms.length; ++k) {
            MethodGen mg = new MethodGen(ms[k], cg.getClassName(), cp);
            boolean lv = ms[k].getLocalVariableTable() == null;
            boolean ln = ms[k].getLineNumberTable() == null;
            if (lv) {
                mg.removeLocalVariables();
            }
            if (ln) {
                mg.removeLineNumbers();
            }
            mg.stripAttributes(skipDebug);
            InstructionList il = mg.getInstructionList();
            if (il != null) {
                InstructionHandle ih = il.getStart();
                while (ih != null) {
                    ih = ih.getNext();
                }
                if (compute) {
                    mg.setMaxStack();
                    mg.setMaxLocals();
                }
                if (computeFrames) {
                    ModifiedPass3bVerifier verif;
                    verif = new ModifiedPass3bVerifier(jc, k);
                    verif.do_verify();
                }
            }
            cg.replaceMethod(ms[k], mg.getMethod());
        }
        cg.getJavaClass().getBytes();
    }

    static void nullAspectjBCELAdapt(final byte[] b) throws IOException {
        org.aspectj.apache.bcel.classfile.JavaClass jc = new org.aspectj.apache.bcel.classfile.ClassParser(new ByteArrayInputStream(b),
                "class-name").parse();
        org.aspectj.apache.bcel.generic.ClassGen cg = new org.aspectj.apache.bcel.generic.ClassGen(jc);
        org.aspectj.apache.bcel.generic.ConstantPoolGen cp = cg.getConstantPool();
        org.aspectj.apache.bcel.classfile.Method[] ms = cg.getMethods();
        for (int k = 0; k < ms.length; ++k) {
            org.aspectj.apache.bcel.generic.MethodGen mg = new org.aspectj.apache.bcel.generic.MethodGen(ms[k],
                    cg.getClassName(),
                    cp);
            boolean lv = ms[k].getLocalVariableTable() == null;
            boolean ln = ms[k].getLineNumberTable() == null;
            if (lv) {
                mg.removeLocalVariables();
            }
            if (ln) {
                mg.removeLineNumbers();
            }
            mg.stripAttributes(skipDebug);
            org.aspectj.apache.bcel.generic.InstructionList il = mg.getInstructionList();
            if (il != null) {
                org.aspectj.apache.bcel.generic.InstructionHandle ih = il.getStart();
                while (ih != null) {
                    ih = ih.getNext();
                }
                if (compute) {
                    mg.setMaxStack();
                    mg.setMaxLocals();
                }
                if (computeFrames) {
                    org.aspectj.apache.bcel.verifier.structurals.ModifiedPass3bVerifier verif = new org.aspectj.apache.bcel.verifier.structurals.ModifiedPass3bVerifier(jc,
                            k);
                    verif.do_verify();
                }
            }
            cg.replaceMethod(ms[k], mg.getMethod());
        }
        cg.getJavaClass().getBytes();
    }

    static void nullJavassistAdapt(ClassPool pool, final byte[] b) throws Exception {
        CtClass cc = pool.makeClass(new ByteArrayInputStream(b));
        CtMethod[] ms = cc.getDeclaredMethods();
        for (int j = 0; j < ms.length; ++j) {
            if (skipDebug) {
                // is there a mean to remove the debug attributes?
            }
            if (compute) {
                // how to force recomputation of maxStack and maxLocals?
            }
        }
        cc.toBytecode();
    }

    static BCClass nullSERPAdapt(Project p, BCClass c, final byte[] b) throws Exception {
        if (c != null) {
            p.removeClass(c);
        }
        c = p.loadClass(new ByteArrayInputStream(b));
        c.getDeclaredFields();
        BCMethod[] methods = c.getDeclaredMethods();
        for (int i = 0; i < methods.length; ++i) {
            Code code = methods[i].getCode(false);
            if (code != null) {
                while (code.hasNext()) {
                    code.next();
                }
                if (compute) {
                    code.calculateMaxStack();
                    code.calculateMaxLocals();
                }
            }
        }
        c.toByteArray();
        return c;
    }
}
TOP

Related Classes of org.ow2.asm.ALLPerfTest$RunTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.