Commit 30052454 authored by Eric Bruneton's avatar Eric Bruneton
Browse files

Improve the read-write performance test by using the JMH framework.

Results:
AdapterBenchmark.getClassInfo_asm4_0                      thrpt   20  12964,540 ± 100,411  ops/s
AdapterBenchmark.getClassInfo_asm5_0                      thrpt   20  12410,599 ±  64,511  ops/s
AdapterBenchmark.getClassInfo_asm6_0                      thrpt   20  12538,801 ±  67,891  ops/s
AdapterBenchmark.getClassInfo_asm6_1                      thrpt   20  15744,919 ±  54,819  ops/s
AdapterBenchmark.getClassObjectModel_asm4_0               thrpt   20    536,993 ±   2,805  ops/s
AdapterBenchmark.getClassObjectModel_asm5_0               thrpt   20    539,811 ±   2,934  ops/s
AdapterBenchmark.getClassObjectModel_asm6_0               thrpt   20    529,741 ±   1,942  ops/s
AdapterBenchmark.getClassObjectModel_asm6_1               thrpt   20    553,037 ±   3,225  ops/s
AdapterBenchmark.readAndWriteWithComputeFrames_asm4_0     thrpt   20    167,452 ±   0,664  ops/s
AdapterBenchmark.readAndWriteWithComputeFrames_asm5_0     thrpt   20    164,215 ±   0,689  ops/s
AdapterBenchmark.readAndWriteWithComputeFrames_asm6_0     thrpt   20    165,821 ±   0,688  ops/s
AdapterBenchmark.readAndWriteWithComputeFrames_asm6_1     thrpt   20    174,736 ±   0,673  ops/s
AdapterBenchmark.readAndWriteWithComputeMaxs_asm4_0       thrpt   20    301,145 ±   1,328  ops/s
AdapterBenchmark.readAndWriteWithComputeMaxs_asm5_0       thrpt   20    303,352 ±   1,269  ops/s
AdapterBenchmark.readAndWriteWithComputeMaxs_asm6_0       thrpt   20    317,626 ±   1,079  ops/s
AdapterBenchmark.readAndWriteWithComputeMaxs_asm6_1       thrpt   20    321,737 ±   1,544  ops/s
AdapterBenchmark.readAndWriteWithComputeMaxs_aspectJBcel  thrpt   20     82,308 ±   0,389  ops/s
AdapterBenchmark.readAndWriteWithComputeMaxs_bcel         thrpt   20     65,963 ±   0,261  ops/s
AdapterBenchmark.readAndWriteWithComputeMaxs_serp         thrpt   20     33,711 ±   0,090  ops/s
AdapterBenchmark.readAndWriteWithCopyPool_asm4_0          thrpt   20   1144,297 ±   4,976  ops/s
AdapterBenchmark.readAndWriteWithCopyPool_asm5_0          thrpt   20   1142,265 ±   5,866  ops/s
AdapterBenchmark.readAndWriteWithCopyPool_asm6_0          thrpt   20   1128,241 ±   5,340  ops/s
AdapterBenchmark.readAndWriteWithCopyPool_asm6_1          thrpt   20   1235,521 ±   4,344  ops/s
AdapterBenchmark.readAndWriteWithObjectModel_asm4_0       thrpt   20    252,227 ±   1,036  ops/s
AdapterBenchmark.readAndWriteWithObjectModel_asm5_0       thrpt   20    248,238 ±   1,110  ops/s
AdapterBenchmark.readAndWriteWithObjectModel_asm6_0       thrpt   20    246,449 ±   1,103  ops/s
AdapterBenchmark.readAndWriteWithObjectModel_asm6_1       thrpt   20    261,525 ±   1,003  ops/s
AdapterBenchmark.readAndWrite_asm4_0                      thrpt   20    313,583 ±   1,429  ops/s
AdapterBenchmark.readAndWrite_asm5_0                      thrpt   20    319,958 ±   2,057  ops/s
AdapterBenchmark.readAndWrite_asm6_0                      thrpt   20    316,718 ±   1,316  ops/s
AdapterBenchmark.readAndWrite_asm6_1                      thrpt   20    319,508 ±   0,990  ops/s
AdapterBenchmark.readAndWrite_aspectJBcel                 thrpt   20    100,253 ±   0,353  ops/s
AdapterBenchmark.readAndWrite_bcel                        thrpt   20     79,329 ±   0,235  ops/s
AdapterBenchmark.readAndWrite_javassist                   thrpt   20    531,673 ±   1,894  ops/s
AdapterBenchmark.readAndWrite_serp                        thrpt   20     37,049 ±   0,102  ops/s
AdapterBenchmark.read_asm4_0                              thrpt   20    642,491 ±   2,536  ops/s
AdapterBenchmark.read_asm5_0                              thrpt   20    682,731 ±   5,122  ops/s
AdapterBenchmark.read_asm6_0                              thrpt   20    671,490 ±   3,581  ops/s
AdapterBenchmark.read_asm6_1                              thrpt   20    665,407 ±   2,716  ops/s
parent b5e6dc44
// ASM: a very small and fast Java bytecode manipulation framework
// Copyright (c) 2000-2011 INRIA, 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.benchmarks;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.ModuleVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.TypePath;
import org.objectweb.asm.TypeReference;
import org.objectweb.asm.tree.ClassNode;
/**
* An {@link Adapter} implemented with the ASM library.
*
* @author Eric Bruneton
*/
public class ASMAdapter extends Adapter {
private int asmApi;
@Override
public String getVersion() {
for (int i = 6; i >= 4; --i) {
try {
String version = "ASM" + i;
if (Opcodes.class.getField(version) != null) {
asmApi = Opcodes.class.getField(version).getInt(null);
return version;
}
} catch (NoSuchFieldException e) {
continue;
} catch (IllegalAccessException e) {
throw new AssertionError();
}
}
return "";
}
@Override
public ClassInfo getClassInfo(final byte[] classFile) {
ClassReader classReader = new ClassReader(classFile);
return new ClassInfo(
classReader.getAccess(),
classReader.getClassName(),
classReader.getSuperName(),
classReader.getInterfaces());
}
@Override
public Object getClassObjectModel(final byte[] classFile) {
ClassNode classNode = new ClassNode();
new ClassReader(classFile).accept(classNode, 0);
return classNode;
}
@Override
public int read(final byte[] classFile) {
CountingVisitor countingVisitor = new CountingVisitor(asmApi);
new ClassReader(classFile).accept(countingVisitor, 0);
return countingVisitor.count;
}
@Override
public byte[] readAndWrite(final byte[] classFile, final boolean computeMaxs) {
ClassReader classReader = new ClassReader(classFile);
ClassWriter classWriter = new ClassWriter(0);
classReader.accept(classWriter, 0);
return classWriter.toByteArray();
}
@Override
public byte[] readAndWriteWithComputeFrames(final byte[] classFile) {
ClassReader classReader = new ClassReader(classFile);
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
classReader.accept(classWriter, 0);
return classWriter.toByteArray();
}
@Override
public byte[] readAndWriteWithCopyPool(final byte[] classFile) {
ClassReader classReader = new ClassReader(classFile);
ClassWriter classWriter = new ClassWriter(classReader, 0);
classReader.accept(classWriter, 0);
return classWriter.toByteArray();
}
@Override
public byte[] readAndWriteWithObjectModel(final byte[] classFile) {
ClassWriter classWriter = new ClassWriter(0);
ClassNode classNode = new ClassNode();
new ClassReader(classFile).accept(classNode, 0);
classNode.accept(classWriter);
return classWriter.toByteArray();
}
private static class CountingVisitor extends ClassVisitor {
int count;
AnnotationVisitor annotationVisitor =
new AnnotationVisitor(api) {
@Override
public void visit(final String name, final Object value) {
++count;
}
@Override
public void visitEnum(final String name, final String descriptor, final String value) {
++count;
}
@Override
public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
++count;
return this;
}
@Override
public AnnotationVisitor visitArray(final String name) {
++count;
return this;
}
};
public CountingVisitor(int api) {
super(api);
}
@Override
public void visit(
final int version,
final int access,
final String name,
final String signature,
final String superName,
final String[] interfaces) {
++count;
}
@Override
public void visitSource(final String source, final String debug) {
++count;
}
@Override
public ModuleVisitor visitModule(final String name, final int access, final String version) {
++count;
return null;
}
@Override
public void visitOuterClass(final String owner, final String name, final String descriptor) {
++count;
}
@Override
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
++count;
return annotationVisitor;
}
@Override
public AnnotationVisitor visitTypeAnnotation(
final int typeRef,
final TypePath typePath,
final String descriptor,
final boolean visible) {
++count;
return annotationVisitor;
}
@Override
public void visitInnerClass(
final String name, final String outerName, final String innerName, final int access) {
++count;
}
@Override
public FieldVisitor visitField(
final int access,
final String name,
final String descriptor,
final String signature,
final Object value) {
++count;
return new FieldVisitor(api) {
@Override
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
++count;
return annotationVisitor;
}
@Override
public AnnotationVisitor visitTypeAnnotation(
final int typeRef,
final TypePath typePath,
final String descriptor,
final boolean visible) {
++count;
return annotationVisitor;
}
};
}
@Override
public MethodVisitor visitMethod(
final int access,
final String name,
final String descriptor,
final String signature,
final String[] exceptions) {
return new MethodVisitor(api) {
@Override
public void visitParameter(final String name, final int access) {
++count;
}
@Override
public AnnotationVisitor visitAnnotationDefault() {
++count;
return annotationVisitor;
}
@Override
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
++count;
return annotationVisitor;
}
@Override
public AnnotationVisitor visitTypeAnnotation(
final int typeRef,
final TypePath typePath,
final String descriptor,
final boolean visible) {
++count;
return annotationVisitor;
}
@Override
public void visitAnnotableParameterCount(final int parameterCount, final boolean visible) {
++count;
}
@Override
public AnnotationVisitor visitParameterAnnotation(
final int parameter, final String descriptor, final boolean visible) {
++count;
return annotationVisitor;
}
@Override
public void visitFrame(
final int type,
final int nLocal,
final Object[] local,
final int nStack,
final Object[] stack) {
++count;
}
@Override
public void visitInsn(final int opcode) {
++count;
}
@Override
public void visitIntInsn(final int opcode, final int operand) {
++count;
}
@Override
public void visitVarInsn(final int opcode, final int var) {
++count;
}
@Override
public void visitTypeInsn(final int opcode, final String type) {
++count;
}
@Override
public void visitFieldInsn(
final int opcode, final String owner, final String name, final String descriptor) {
++count;
}
@Override
@Deprecated
public void visitMethodInsn(
final int opcode, final String owner, final String name, final String descriptor) {
++count;
}
@Override
public void visitMethodInsn(
final int opcode,
final String owner,
final String name,
final String descriptor,
final boolean isInterface) {
++count;
}
@Override
public void visitInvokeDynamicInsn(
final String name,
final String descriptor,
final Handle bootstrapMethodHandle,
final Object... bootstrapMethodArguments) {
++count;
}
@Override
public void visitJumpInsn(final int opcode, final Label label) {
++count;
}
@Override
public void visitLabel(final Label label) {
++count;
}
@Override
public void visitLdcInsn(final Object value) {
++count;
}
@Override
public void visitIincInsn(final int var, final int increment) {
++count;
}
@Override
public void visitTableSwitchInsn(
final int min, final int max, final Label dflt, final Label... labels) {
++count;
}
@Override
public void visitLookupSwitchInsn(
final Label dflt, final int[] keys, final Label[] labels) {
++count;
}
@Override
public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
++count;
}
@Override
public AnnotationVisitor visitInsnAnnotation(
final int typeRef,
final TypePath typePath,
final String descriptor,
final boolean visible) {
++count;
return annotationVisitor;
}
@Override
public void visitTryCatchBlock(
final Label start, final Label end, final Label handler, final String type) {
++count;
}
@Override
public AnnotationVisitor visitTryCatchAnnotation(
final int typeRef,
final TypePath typePath,
final String descriptor,
final boolean visible) {
++count;
return annotationVisitor;
}
@Override
public void visitLocalVariable(
final String name,
final String descriptor,
final String signature,
final Label start,
final Label end,
final int index) {
++count;
}
@Override
public AnnotationVisitor visitLocalVariableAnnotation(
final int typeRef,
final TypePath typePath,
final Label[] start,
final Label[] end,
final int[] index,
final String descriptor,
final boolean visible) {
++count;
return annotationVisitor;
}
@Override
public void visitLineNumber(final int line, final Label start) {
++count;
}
@Override
public void visitMaxs(final int maxStack, final int maxLocals) {
++count;
}
};
}
}
}
// ASM: a very small and fast Java bytecode manipulation framework
// Copyright (c) 2000-2011 INRIA, 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.benchmarks;
/**
* An empty class adapter, which reads and writes Java classes with no intermediate transformation.
*
* @author Eric Bruneton
*/
public abstract class Adapter {
/** The access flags, name, super class and interfaces of a class. */
public static class ClassInfo {
int access;
String name;
String superClass;
String[] interfaces;
public ClassInfo(
final int access, final String name, final String superClass, final String[] interfaces) {
this.access = access;
this.name = name;
this.superClass = superClass;
this.interfaces = interfaces;
}
}
/** @return the version of this class adapter */
public String getVersion() {
return null;
}
/**
* @param classFile a JVMS ClassFile structure
* @return access flags, name, super class and interfaces of the given class.
*/
public ClassInfo getClassInfo(final byte[] classFile) {
throw new UnsupportedOperationException();
}
/**
* Returns an in-memory, object representation of the given class.
*
* @param classFile a JVMS ClassFile structure
* @return an in-memory, object representation of the given class.
*/
public Object getClassObjectModel(final byte[] classFile) {
throw new UnsupportedOperationException();
}
/**
* Reads a class and returns the number of 'elements' it contains.
*
* @param classFile a JVMS ClassFile structure
* @return the number of 'elements' found in the given class.
*/
public int read(final byte[] classFile) {
throw new UnsupportedOperationException();
}
/**
* Reads a class and writes and returns an equivalent one.
*
* @param classFile a JVMS ClassFile structure
* @param computeMaxs whether to recompute the maximum stack size and maximum number of local
* variables for each method.
* @return the rebuilt class.
*/
public byte[] readAndWrite(final byte[] classFile, final boolean computeMaxs) {
throw new UnsupportedOperationException();
}
/**
* Reads a class and writes and returns an equivalent one with all its stack map frames
* recomputed.
*
* @param classFile a JVMS ClassFile structure
* @return the rebuilt class.
*/
public byte[] readAndWriteWithComputeFrames(final byte[] classFile) {
throw new UnsupportedOperationException();
}
/**
* Reads a class and writes and returns an equivalent one, sharing the same constant pool.
*
* @param classFile a JVMS ClassFile structure
* @return the rebuilt class.
*/
public byte[] readAndWriteWithCopyPool(final byte[] classFile) {
throw new UnsupportedOperationException();
}
/**
* Reads a class and writes and returns an equivalent one, via the construction of in-memory,
* object representation of the class.
*
* @param classFile a JVMS ClassFile structure
* @return the rebuilt class.
*/
public byte[] readAndWriteWithObjectModel(final byte[] classFile) {
throw new UnsupportedOperationException();
}
}