diff options
author | xueliang.zhong <xueliang.zhong@linaro.org> | 2016-08-08 14:49:02 +0100 |
---|---|---|
committer | xueliang.zhong <xueliang.zhong@linaro.org> | 2016-08-23 10:36:21 +0100 |
commit | f92372020c9ec0bf2b805415a37355fb257dc540 (patch) | |
tree | 4e1ef376ec715b9364feea7d271a8bdfe0ec8534 /benchmarks | |
parent | ed22d9ec8111ead8259365d3ad9b40c76e6e27b8 (diff) | |
download | art-testing-f92372020c9ec0bf2b805415a37355fb257dc540.tar.gz |
Add new cases for comparing ART JIT and AOT modes
A new folder benchmarks/jit_aot/ is added to compare and benchmark
ART JIT and AOT performance.
Currently two micro benchmarks are added:
- benchmarks/jit_aot/Invoke.java
- benchmarks/jit_aot/LoadCheck.java
benchmarks/jit_aot/Invoke.java:
This benchmark compares the performance of ART JIT and AOT,
on their abilities to optimize and inline invoke-virtual and invoke-static.
benchmarks/jit_aot/LoadCheck.java:
This benchmark compares the performance of ART JIT and AOT,
on their abilities to optimize invokes to other user defined class (LoadClassCheck).
Change-Id: I3ae388abe37f376f959983c4a4c6344a769482f7
Diffstat (limited to 'benchmarks')
-rw-r--r-- | benchmarks/benchmarksgame/fastaredux_revised.java | 250 | ||||
-rw-r--r-- | benchmarks/jit_aot/Invoke.java | 109 | ||||
-rw-r--r-- | benchmarks/jit_aot/LoadCheck.java | 110 |
3 files changed, 219 insertions, 250 deletions
diff --git a/benchmarks/benchmarksgame/fastaredux_revised.java b/benchmarks/benchmarksgame/fastaredux_revised.java deleted file mode 100644 index ba581f4..0000000 --- a/benchmarks/benchmarksgame/fastaredux_revised.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * This benchmark has been ported from "The Computer Language Benchmarks Game" suite and modified - * to fit the benchmarking framework. - * The original benchmarks printed long strings to the stdout. This print was overrided to do - * nothing to fit the framework. These action can cause difference in behaviour of the original and - * changed benchmarks; it hasn't been estimated yet. - * - * The original file is `fastaredux/fastaredux.java-3.java` from the archive - * available at - * http://benchmarksgame.alioth.debian.org/download/benchmarksgame-sourcecode.zip. - * See LICENSE file in the same folder (BSD 3-clause). - * - * The Computer Language Benchmarks Game - * http://benchmarksgame.alioth.debian.org/ - * - * modified by Enotus - * - */ - -/* - * Description: Generate and write random DNA sequences. - * Main Focus: TODO - * - */ - -/* - * This benchmark has been modified from original fastaredux.java. - * Original benchmark implements a Random class which is a random double generator, - * and is heavily used by RandomFasta in its inner calculation. - * - * This behavior can be very unfriendly to ART AOT because: - * Random is a user defined class. Currently in AOT mode, - * ART cannot assume this class is always loaded, - * thus ART AOT compiler has to generate LoadClass check before invoking Random.next() method. - * Since Random.next() is called inside a loop of a hot function addLine(), - * the LoadClass check overhead causes this benchmark runs twice slower - * in AOT mode compared to JIT mode. - * - * In interpreter + JIT mode, JIT compiler can assume that a user defined class is always loaded - * during previous interpretation stage, thus it avoid generating LoadClass check. - * - * In this revised benchmark, random double generation is implemented as part of RandomFasta class, - * thus LoadClass check is avoided in ART AOT, and the performance becomes as good as ART JIT. - */ - -package benchmarks.benchmarksgame; - -import java.io.*; - -// CHECKSTYLE.OFF: .* -public class fastaredux_revised { - - static final int LINE_LENGTH = 60; - static final int OUT_BUFFER_SIZE = 256*1024; - static final int LOOKUP_SIZE = 4*1024; - static final double LOOKUP_SCALE = LOOKUP_SIZE - 1; - - static final class Freq { - byte c; - double p; - Freq(char cc, double pp) {c = (byte) cc;p = pp;} - } - - static final String ALU = - "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" - + "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" - + "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" - + "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" - + "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" - + "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" - + "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; - static final Freq[] IUB = { - new Freq('a', 0.27), - new Freq('c', 0.12), - new Freq('g', 0.12), - new Freq('t', 0.27), - new Freq('B', 0.02), - new Freq('D', 0.02), - new Freq('H', 0.02), - new Freq('K', 0.02), - new Freq('M', 0.02), - new Freq('N', 0.02), - new Freq('R', 0.02), - new Freq('S', 0.02), - new Freq('V', 0.02), - new Freq('W', 0.02), - new Freq('Y', 0.02)}; - static final Freq[] HomoSapiens = { - new Freq('a', 0.3029549426680), - new Freq('c', 0.1979883004921), - new Freq('g', 0.1975473066391), - new Freq('t', 0.3015094502008)}; - - static void sumAndScale(Freq[] a) { - double p = 0; - for (int i = 0; i < a.length; i++) - a[i].p = (p += a[i].p) * LOOKUP_SCALE; - a[a.length - 1].p = LOOKUP_SCALE; - } - - static final class Out { - - static byte buf[] = new byte[OUT_BUFFER_SIZE]; - static final int lim = OUT_BUFFER_SIZE - 2*LINE_LENGTH - 1; - static int ct = 0; - static OutputStream stream; - - static void checkFlush() throws IOException { - if (ct >= lim) { stream.write(buf, 0, ct); ct = 0;} - } - - static void close() throws IOException { - stream.write(buf, 0, ct);ct = 0; - stream.close(); - } - } - - static final class RandomFasta { - - static final Freq[] lookup=new Freq[LOOKUP_SIZE]; - - static final int IM = 139968; - static final int IA = 3877; - static final int IC = 29573; - static final double SCALE = LOOKUP_SCALE / IM; - static int last = 42; - - static double nextRandDouble() { - return SCALE * (last = (last * IA + IC) % IM); - } - - static void makeLookup(Freq[] a) { - for (int i = 0, j = 0; i < LOOKUP_SIZE; i++) { - while (a[j].p < i) j++; - lookup[i] = a[j]; - } - } - - static void addLine(int bytes) throws IOException{ - Out.checkFlush(); - int lct=Out.ct; - while(lct<Out.ct+bytes){ - double r = nextRandDouble(); // Avoid introducing LoadClass in ART AOT. - int ai = (int) r; while (lookup[ai].p < r) ai++; - Out.buf[lct++] = lookup[ai].c; - } - Out.buf[lct++] = (byte)'\n'; - Out.ct=lct; - } - - static void make(String desc, Freq[] a, int n) throws IOException { - makeLookup(a); - - System.arraycopy(desc.getBytes(), 0, Out.buf, Out.ct, desc.length()); - Out.ct+=desc.length(); - - while (n > 0) { - int bytes = Math.min(LINE_LENGTH, n); - addLine(bytes); - n -= bytes; - } - } - } - - static final class RepeatFasta { - - static void make(String desc, byte[] alu, int n) throws IOException { - System.arraycopy(desc.getBytes(), 0, Out.buf, Out.ct, desc.length()); - Out.ct+=desc.length(); - - byte buf[] = new byte[alu.length + LINE_LENGTH]; - for (int i = 0; i < buf.length; i += alu.length) - System.arraycopy(alu, 0, buf, i, Math.min(alu.length, buf.length - i)); - - int pos = 0; - while (n > 0) { - int bytes = Math.min(LINE_LENGTH, n); - Out.checkFlush(); - System.arraycopy(buf, pos, Out.buf, Out.ct, bytes); Out.ct+=bytes; - Out.buf[Out.ct++] = (byte)'\n'; - pos = (pos + bytes) % alu.length; - n -= bytes; - } - } - } - - private void old_main() throws IOException { - int n = 1000; - - RepeatFasta.make(">ONE Homo sapiens alu\n", ALU.getBytes(), n * 2); - RandomFasta.make(">TWO IUB ambiguity codes\n", IUB, n * 3); - RandomFasta.make(">THREE Homo sapiens frequency\n", HomoSapiens, n * 5); - } - // CHECKSTYLE.ON: .* - - /** Writes to nowhere */ - public class NullOutputStream extends OutputStream { - @Override - public void write(int b) throws IOException { - } - } - - public void timeFastaRedux(int iters) throws IOException { - sumAndScale(IUB); - sumAndScale(HomoSapiens); - - Out.stream = new NullOutputStream(); - - for (int i = 0; i < iters; i++) { - old_main(); - } - } - - static final int VERIFY_MAGIC_NUMBER = 25; - - public boolean verifyFastaRedux() throws IOException { - int n = VERIFY_MAGIC_NUMBER; - Out.buf = new byte[OUT_BUFFER_SIZE]; - sumAndScale(IUB); - sumAndScale(HomoSapiens); - - RepeatFasta.make(">ONE Homo sapiens alu\n", ALU.getBytes(), n * 2); - RandomFasta.make(">TWO IUB ambiguity codes\n", IUB, n * 3); - RandomFasta.make(">THREE Homo sapiens frequency\n", HomoSapiens, n * 5); - - int expected = 0; - int found = Out.buf[VERIFY_MAGIC_NUMBER - 1]; - if (expected != found) { - System.out.println("ERROR: Expected " + expected + " but found " + found); - return false; - } - - return true; - } - - public static void main(String[] args) throws IOException { - int rc = 0; - fastaredux obj = new fastaredux(); - - final long before = System.currentTimeMillis(); - obj.timeFastaRedux(10); - final long after = System.currentTimeMillis(); - - if (!obj.verifyFastaRedux()) { - rc++; - } - System.out.println("benchmarks/benchmarksgame/fastaredux: " + (after - before)); - System.exit(rc); - } -} diff --git a/benchmarks/jit_aot/Invoke.java b/benchmarks/jit_aot/Invoke.java new file mode 100644 index 0000000..a01dd5b --- /dev/null +++ b/benchmarks/jit_aot/Invoke.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2016 Linaro Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This benchmark is inspired by benchmarks/caffeinemark. + * Original benchmark implements a recursion method which calls itself with invoke-virtual. + * + * This behavior can be different on JIT and AOT mode, because: + * - JIT mode can optimize invoke-virtual with inline cache mechanism. + * - AOT mode has no such optimization. + * + * This benchmark exposes such difference between ART JIT and AOT mode. + */ + +package benchmarks.jit_aot; + +public class Invoke { + + public int recursionInvokeVirtual(int i) { + if (i == 0) { + return 0; + } else { + return i + recursionInvokeVirtual(i - 1); + } + } + + public static int recursionInvokeStatic(int i) { + if (i == 0) { + return 0; + } else { + return i + recursionInvokeStatic(i - 1); + } + } + + public final int recursionInvokeFinal(int i) { + if (i == 0) { + return 0; + } else { + return i + recursionInvokeFinal(i - 1); + } + } + + private int recursionInvokePrivate(int i) { + if (i == 0) { + return 0; + } else { + return i + recursionInvokePrivate(i - 1); + } + } + + public void timeRecursionInvokeVirtual(int iters) { + for (int i = 0; i < iters; i++) { + recursionInvokeVirtual(i); + } + } + + public void timeRecursionInvokeStatic(int iters) { + for (int i = 0; i < iters; i++) { + recursionInvokeStatic(i); + } + } + + public void timeRecursionInvokeFinal(int iters) { + for (int i = 0; i < iters; i++) { + recursionInvokeFinal(i); + } + } + + public void timeRecursionInvokePrivate(int iters) { + for (int i = 0; i < iters; i++) { + recursionInvokePrivate(i); + } + } + + public boolean verify() { + return true; + } + + public static void main(String[] args) { + int rc = 0; + Invoke obj = new Invoke(); + + final long before = System.currentTimeMillis(); + obj.timeRecursionInvokeVirtual(1000); + obj.timeRecursionInvokeStatic(1000); + obj.timeRecursionInvokeFinal(1000); + obj.timeRecursionInvokePrivate(1000); + final long after = System.currentTimeMillis(); + if (!obj.verify()) { + rc++; + } + System.out.println("benchmarks/jit_aot/Invoke: " + (after - before)); + + System.exit(rc); + } +} diff --git a/benchmarks/jit_aot/LoadCheck.java b/benchmarks/jit_aot/LoadCheck.java new file mode 100644 index 0000000..2d9af29 --- /dev/null +++ b/benchmarks/jit_aot/LoadCheck.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2016 Linaro Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This benchmark is inspired by benchmarksgame/fastaredux.java. + * Original benchmark implements a Random class which is a random double generator, + * and is heavily used by another class in its inner calculation. + * + * This behavior can be very unfriendly to ART AOT because: + * Random is a user defined class. Currently in AOT mode, + * ART cannot assume this class is always loaded, + * thus ART AOT compiler has to generate LoadClass check before invoking Random.next() method. + * Since Random.next() is called inside a loop of a hot function addLine(), + * the LoadClass check overhead causes this benchmark runs twice slower + * in AOT mode compared to JIT mode. + * + * In interpreter + JIT mode, JIT compiler can assume that a user defined class is always loaded + * during previous interpretation stage, thus it avoid generating LoadClass check. + * + * This benchmark exposes such difference between ART JIT and AOT mode. + */ + +package benchmarks.jit_aot; + +public class LoadCheck { + static final class Random { + static final int IM = 139968; + static final int IA = 3877; + static final int IC = 29573; + static final double LOOKUP_SCALE = 4 * 1024 - 1; + static final double SCALE = LOOKUP_SCALE / IM; + static int last = 42; + + static double next() { + return SCALE * (last = (last * IA + IC) % IM); + } + } + + static final int IM = 139968; + static final int IA = 3877; + static final int IC = 29573; + static final double LOOKUP_SCALE = 4 * 1024 - 1; + static final double SCALE = LOOKUP_SCALE / IM; + static int last = 42; + + public double sum; + + static double nextRandDouble() { + return SCALE * (last = (last * IA + IC) % IM); + } + + public void randomSumInvokeStaticMethod(int val) { + sum = (double)val; + for (int i = 0; i < 10000; i++) { + sum += nextRandDouble(); + } + } + + public void randomSumInvokeUserClass(int val) { + sum = (double)val; + for (int i = 0; i < 10000; i++) { + sum += Random.next(); + } + } + + public void timeRandomSumInvokeStaticMethod(int iters) { + for (int i = 0; i < iters; i++) { + randomSumInvokeStaticMethod(iters); + } + } + + public void timeRandomSumInvokeUserClass(int iters) { + for (int i = 0; i < iters; i++) { + randomSumInvokeUserClass(iters); + } + } + + public boolean verify() { + return true; + } + + public static void main(String[] args) { + int rc = 0; + LoadCheck obj = new LoadCheck(); + + final long before = System.currentTimeMillis(); + obj.timeRandomSumInvokeStaticMethod(10000); + obj.timeRandomSumInvokeUserClass(10000); + final long after = System.currentTimeMillis(); + if (!obj.verify()) { + rc++; + } + System.out.println("benchmarks/jit_aot/LoadCheck: " + (after - before)); + + System.exit(rc); + } +} |