1/***
2 * ASM performance test: measures the performances of asm package
3 * Copyright (c) 2002-2005 France Telecom
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the copyright holders nor the names of its
15 *    contributors may be used to endorse or promote products derived from
16 *    this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
29 */
30package org.objectweb.asm;
31
32import java.io.FileInputStream;
33import java.io.FileNotFoundException;
34import java.io.IOException;
35import java.util.ArrayList;
36import java.util.Iterator;
37import java.util.LinkedList;
38import java.util.List;
39import java.util.jar.JarEntry;
40import java.util.jar.JarInputStream;
41
42import org.objectweb.asm.ClassReader;
43import org.objectweb.asm.tree.ClassNode;
44import org.objectweb.asm.tree.MethodNode;
45
46/*
47 * Created on Nov 30, 2004 as part of ASMPerf by treffer
48 */
49
50/**
51 * Memory performances tests for tree package.
52 *
53 * @author treffer
54 */
55public class ASMMemTest {
56
57    public static void main(String[] args) {
58        if (args.length < 2) {
59            System.out.println("java ASMMemTest <jar-file> <number-of-classes>");
60            System.exit(1);
61        }
62
63        Runtime runtime = Runtime.getRuntime();
64        memDown(runtime);
65        System.out.println("Initial memory load: ".concat(memFormat(getUsedMem(runtime))));
66
67        LinkedList fileData = new LinkedList();
68        int limit = Integer.parseInt(args[1]);
69        try {
70            long totalSize = 0;
71            JarInputStream jar = new JarInputStream(new FileInputStream(args[0]));
72            JarEntry entry = jar.getNextJarEntry();
73            while ((fileData.size() < limit) && (entry != null)) {
74                String name = entry.getName();
75                if (name.endsWith(".class")) {
76                    if (entry.getSize() != -1) {
77                        int len = (int) entry.getSize();
78                        byte[] data = new byte[len];
79                        jar.read(data);
80                        fileData.add(data);
81                        totalSize += data.length;
82                    } else {
83                        System.err.println("No jar-entry size given... Unimplemented, jar file not supported");
84                    }
85                }
86                entry = jar.getNextJarEntry();
87            }
88            System.out.println(memFormat(totalSize) + " class data, ~"
89                    + memFormat(totalSize / limit) + " per class.");
90        } catch (FileNotFoundException e) {
91            e.printStackTrace();
92        } catch (IOException e) {
93            e.printStackTrace();
94        }
95
96        ArrayList result = new ArrayList(fileData.size());
97        long startmem;
98
99        for (int i = 0; i < 10; i++) {
100            System.out.println("\n> Run ".concat(Integer.toString(i + 1)));
101            Iterator files = fileData.iterator();
102            result.clear();
103            memDown(runtime);
104            System.out.println("Empty memory load: ".concat(memFormat(startmem = getUsedMem(runtime))));
105
106            long time = -System.currentTimeMillis();
107            while (files.hasNext()) {
108                byte data[] = (byte[]) files.next();
109                ClassReader reader = new ClassReader(data);
110                ClassNode clazz = new ClassNode();
111                reader.accept(clazz, false);
112                result.add(clazz);
113            }
114            time += System.currentTimeMillis();
115
116            memDown(runtime);
117            System.out.println("Time: ".concat(timeFormat(time)));
118            System.out.println("Final memory load: ".concat(memFormat(getUsedMem(runtime))));
119            System.out.println("ASM memory load: ".concat(memFormat(getUsedMem(runtime)
120                    - startmem)));
121            for (int j = 0; j < limit; j++) {
122                ClassNode clazz = (ClassNode) result.get(j);
123                List l = clazz.methods;
124                for (int k = 0, lim = l.size(); k < lim; k++) {
125                    MethodNode m = (MethodNode) l.get(k);
126                    List insn = m.instructions;
127                    if (insn != null)
128                        insn.clear();
129                    /*
130                     * for (int ins = 0, insmax = insn.size(); ins < insmax;
131                     * ins++) { if (insn.get(ins) instanceof VarInsnNode) {
132                     * insn.set(ins, null); } }
133                     */
134                }
135            }
136            memDown(runtime);
137            System.out.println("ASM memory load (removed method code): ".concat(memFormat(getUsedMem(runtime)
138                    - startmem)));
139        }
140
141    }
142
143    public final static long getUsedMem(final Runtime r) {
144        return r.totalMemory() - r.freeMemory();
145    }
146
147    public final static String timeFormat(final long time) {
148        int min = (int) (time / (60 * 1000));
149        int sec = (int) ((time / (1000)) % 60);
150        int msec = (int) (time % 1000);
151        StringBuffer sbuf = new StringBuffer(30);
152        if (min > 0) {
153            sbuf.append(min);
154            sbuf.append("min ");
155        }
156        if ((sec > 0) || (min > 0)) {
157            sbuf.append(sec);
158            sbuf.append("s ");
159        }
160        if ((msec > 0) || (sec > 0) || (min > 0)) {
161            sbuf.append(msec);
162            sbuf.append("ms ");
163        }
164        sbuf.append("(");
165        sbuf.append(time);
166        sbuf.append("ms)");
167        return sbuf.toString();
168    }
169
170    public final static String memFormat(final long mem) {
171        int gb = (int) ((mem >> 30) & 0x3FF);
172        int mb = (int) ((mem >> 20) & 0x3FF);
173        int kb = (int) ((mem >> 10) & 0x3FF);
174        int bytes = (int) (mem & 0x3FF);
175        StringBuffer sbuf = new StringBuffer(30);
176        if (gb > 0) {
177            sbuf.append(gb);
178            sbuf.append("GB ");
179        }
180        if ((mb > 0) || (gb > 0)) {
181            sbuf.append(mb);
182            sbuf.append("MB ");
183        }
184        if ((kb > 0) || (mb > 0) || (gb > 0)) {
185            sbuf.append(kb);
186            sbuf.append("KB ");
187        }
188        if ((bytes > 0) || (kb > 0) || (mb > 0) || (gb > 0)) {
189            sbuf.append(bytes);
190            sbuf.append("bytes ");
191        }
192        sbuf.append("(");
193        sbuf.append(mem);
194        sbuf.append("bytes)");
195        return sbuf.toString();
196    }
197
198    public final static void memDown(final Runtime r) {
199        long oldmem;
200        do {
201            oldmem = getUsedMem(r);
202            for (int i = 0; i < 10; i++) {
203                // Calling System.gc once is very unsafe
204                System.gc();
205                try {
206                    Thread.sleep(10);
207                } catch (InterruptedException ie) {
208                }
209            }
210        } while (getUsedMem(r) < oldmem);
211    }
212}