| /*** |
| * ASM performance test: measures the performances of asm package |
| * 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; |
| |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.jar.JarEntry; |
| import java.util.jar.JarInputStream; |
| |
| import org.objectweb.asm.tree.ClassNode; |
| import org.objectweb.asm.tree.InsnList; |
| import org.objectweb.asm.tree.MethodNode; |
| |
| /* |
| * Created on Nov 30, 2004-2011 as part of ASMPerf by treffer |
| */ |
| |
| /** |
| * Memory performances tests for tree package. |
| * |
| * @author treffer |
| */ |
| public class ASMMemTest { |
| |
| public static void main(final String[] args) { |
| if (args.length < 2) { |
| System.out |
| .println("java ASMMemTest <jar-file> <number-of-classes>"); |
| System.exit(1); |
| } |
| |
| Runtime runtime = Runtime.getRuntime(); |
| memDown(runtime); |
| System.out.println("Initial memory load: " |
| .concat(memFormat(getUsedMem(runtime)))); |
| |
| LinkedList<byte[]> fileData = new LinkedList<byte[]>(); |
| int limit = Integer.parseInt(args[1]); |
| try { |
| long totalSize = 0; |
| JarInputStream jar = new JarInputStream( |
| new FileInputStream(args[0])); |
| JarEntry entry = jar.getNextJarEntry(); |
| while (fileData.size() < limit && entry != null) { |
| String name = entry.getName(); |
| if (name.endsWith(".class")) { |
| if (entry.getSize() != -1) { |
| int len = (int) entry.getSize(); |
| byte[] data = new byte[len]; |
| int l = jar.read(data); |
| assert l == len; |
| fileData.add(data); |
| totalSize += data.length; |
| } else { |
| System.err.println("No jar-entry size given... " |
| + "Unimplemented, jar file not supported"); |
| } |
| } |
| entry = jar.getNextJarEntry(); |
| } |
| System.out.println(memFormat(totalSize) + " class data, ~" |
| + memFormat(totalSize / limit) + " per class."); |
| } catch (FileNotFoundException e) { |
| e.printStackTrace(); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| |
| ArrayList<ClassNode> result = new ArrayList<ClassNode>(fileData.size()); |
| long startmem; |
| |
| for (int i = 0; i < 10; i++) { |
| System.out.println("\n> Run ".concat(Integer.toString(i + 1))); |
| Iterator<byte[]> files = fileData.iterator(); |
| result.clear(); |
| memDown(runtime); |
| System.out.println("Empty memory load: " |
| .concat(memFormat(startmem = getUsedMem(runtime)))); |
| |
| long time = -System.currentTimeMillis(); |
| while (files.hasNext()) { |
| byte data[] = files.next(); |
| ClassReader reader = new ClassReader(data); |
| ClassNode clazz = new ClassNode(); |
| reader.accept(clazz, 0); |
| result.add(clazz); |
| } |
| time += System.currentTimeMillis(); |
| |
| memDown(runtime); |
| System.out.println("Time: ".concat(timeFormat(time))); |
| System.out.println("Final memory load: " |
| .concat(memFormat(getUsedMem(runtime)))); |
| System.out.println("ASM memory load: " |
| .concat(memFormat(getUsedMem(runtime) - startmem))); |
| for (int j = 0; j < limit; j++) { |
| ClassNode clazz = result.get(j); |
| List<MethodNode> l = clazz.methods; |
| for (int k = 0, lim = l.size(); k < lim; k++) { |
| MethodNode m = l.get(k); |
| InsnList insn = m.instructions; |
| if (insn != null) { |
| insn.clear(); |
| } |
| } |
| } |
| memDown(runtime); |
| System.out.println("ASM memory load (removed method code): " |
| .concat(memFormat(getUsedMem(runtime) - startmem))); |
| } |
| |
| } |
| |
| public final static long getUsedMem(final Runtime r) { |
| return r.totalMemory() - r.freeMemory(); |
| } |
| |
| public final static String timeFormat(final long time) { |
| int min = (int) (time / (60 * 1000)); |
| int sec = (int) ((time / 1000) % 60); |
| int msec = (int) (time % 1000); |
| StringBuffer sbuf = new StringBuffer(30); |
| if (min > 0) { |
| sbuf.append(min); |
| sbuf.append("min "); |
| } |
| if (sec > 0 || min > 0) { |
| sbuf.append(sec); |
| sbuf.append("s "); |
| } |
| if (msec > 0 || sec > 0 || min > 0) { |
| sbuf.append(msec); |
| sbuf.append("ms "); |
| } |
| sbuf.append('('); |
| sbuf.append(time); |
| sbuf.append("ms)"); |
| return sbuf.toString(); |
| } |
| |
| public final static String memFormat(final long mem) { |
| int gb = (int) ((mem >> 30) & 0x3FF); |
| int mb = (int) ((mem >> 20) & 0x3FF); |
| int kb = (int) ((mem >> 10) & 0x3FF); |
| int bytes = (int) (mem & 0x3FF); |
| StringBuffer sbuf = new StringBuffer(30); |
| if (gb > 0) { |
| sbuf.append(gb); |
| sbuf.append("GB "); |
| } |
| if (mb > 0 || gb > 0) { |
| sbuf.append(mb); |
| sbuf.append("MB "); |
| } |
| if (kb > 0 || mb > 0 || gb > 0) { |
| sbuf.append(kb); |
| sbuf.append("KB "); |
| } |
| if (bytes > 0 || kb > 0 || mb > 0 || gb > 0) { |
| sbuf.append(bytes); |
| sbuf.append("bytes "); |
| } |
| sbuf.append('('); |
| sbuf.append(mem); |
| sbuf.append("bytes)"); |
| return sbuf.toString(); |
| } |
| |
| public final static void memDown(final Runtime r) { |
| long oldmem; |
| do { |
| oldmem = getUsedMem(r); |
| for (int i = 0; i < 10; i++) { |
| // Calling System.gc once is very unsafe |
| System.gc(); |
| try { |
| Thread.sleep(10); |
| } catch (InterruptedException ie) { |
| } |
| } |
| } while (getUsedMem(r) < oldmem); |
| } |
| } |