diff options
author | Elliott Hughes <enh@google.com> | 2013-02-13 16:21:51 -0800 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2013-02-13 16:21:51 -0800 |
commit | 97aba27f961a5a6f37dcaf7f455df371e250ede3 (patch) | |
tree | b31965a67f8db0c08586c3484e330dcf8f97df6d /benchmarks | |
parent | 8d1430e1d9cb3ac5c85b3d75119260cb44791f7f (diff) | |
download | libcore-97aba27f961a5a6f37dcaf7f455df371e250ede3.zip libcore-97aba27f961a5a6f37dcaf7f455df371e250ede3.tar.gz libcore-97aba27f961a5a6f37dcaf7f455df371e250ede3.tar.bz2 |
Add the code.google.com/p/dalvik benchmarks to libcore.
I'll remove them from code.google.com afterwards.
Change-Id: I369a301ed0e116c7971caebc607c5a86d06d4ee2
Diffstat (limited to 'benchmarks')
70 files changed, 7239 insertions, 0 deletions
diff --git a/benchmarks/AdditionBenchmark.java b/benchmarks/AdditionBenchmark.java new file mode 100644 index 0000000..a18856e --- /dev/null +++ b/benchmarks/AdditionBenchmark.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +/** + * What do various kinds of addition cost? + */ +public class AdditionBenchmark extends SimpleBenchmark { + public int timeAddConstantToLocalInt(int reps) { + int result = 0; + for (int i = 0; i < reps; ++i) { + result += 123; + } + return result; + } + public int timeAddTwoLocalInts(int reps) { + int result = 0; + int constant = 123; + for (int i = 0; i < reps; ++i) { + result += constant; + } + return result; + } + public long timeAddConstantToLocalLong(int reps) { + long result = 0; + for (int i = 0; i < reps; ++i) { + result += 123L; + } + return result; + } + public long timeAddTwoLocalLongs(int reps) { + long result = 0; + long constant = 123L; + for (int i = 0; i < reps; ++i) { + result += constant; + } + return result; + } + public float timeAddConstantToLocalFloat(int reps) { + float result = 0.0f; + for (int i = 0; i < reps; ++i) { + result += 123.0f; + } + return result; + } + public float timeAddTwoLocalFloats(int reps) { + float result = 0.0f; + float constant = 123.0f; + for (int i = 0; i < reps; ++i) { + result += constant; + } + return result; + } + public double timeAddConstantToLocalDouble(int reps) { + double result = 0.0; + for (int i = 0; i < reps; ++i) { + result += 123.0; + } + return result; + } + public double timeAddTwoLocalDoubles(int reps) { + double result = 0.0; + double constant = 123.0; + for (int i = 0; i < reps; ++i) { + result += constant; + } + return result; + } +} diff --git a/benchmarks/ArrayCopyBenchmark.java b/benchmarks/ArrayCopyBenchmark.java new file mode 100644 index 0000000..75ad243 --- /dev/null +++ b/benchmarks/ArrayCopyBenchmark.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +import java.util.Arrays; + +public class ArrayCopyBenchmark extends SimpleBenchmark { + public void timeManualArrayCopy(int reps) { + char[] src = new char[8192]; + for (int rep = 0; rep < reps; ++rep) { + char[] dst = new char[8192]; + for (int i = 0; i < 8192; ++i) { + dst[i] = src[i]; + } + } + } + + public void time_System_arrayCopy(int reps) { + char[] src = new char[8192]; + for (int rep = 0; rep < reps; ++rep) { + char[] dst = new char[8192]; + System.arraycopy(src, 0, dst, 0, 8192); + } + } + + public void time_Arrays_copyOf(int reps) { + char[] src = new char[8192]; + for (int rep = 0; rep < reps; ++rep) { + char[] dst = Arrays.copyOf(src, 8192); + } + } + + public void time_Arrays_copyOfRange(int reps) { + char[] src = new char[8192]; + for (int rep = 0; rep < reps; ++rep) { + char[] dst = Arrays.copyOfRange(src, 0, 8192); + } + } +} diff --git a/benchmarks/ArrayIterationBenchmark.java b/benchmarks/ArrayIterationBenchmark.java new file mode 100644 index 0000000..bdc255b --- /dev/null +++ b/benchmarks/ArrayIterationBenchmark.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +/** + * How do various ways of iterating through an array compare? + */ +public class ArrayIterationBenchmark extends SimpleBenchmark { + Foo[] mArray = new Foo[27]; + { + for (int i = 0; i < mArray.length; ++i) mArray[i] = new Foo(); + } + public void timeArrayIteration(int reps) { + for (int rep = 0; rep < reps; ++rep) { + int sum = 0; + for (int i = 0; i < mArray.length; i++) { + sum += mArray[i].mSplat; + } + } + } + public void timeArrayIterationCached(int reps) { + for (int rep = 0; rep < reps; ++rep) { + int sum = 0; + Foo[] localArray = mArray; + int len = localArray.length; + + for (int i = 0; i < len; i++) { + sum += localArray[i].mSplat; + } + } + } + public void timeArrayIterationForEach(int reps) { + for (int rep = 0; rep < reps; ++rep) { + int sum = 0; + for (Foo a: mArray) { + sum += a.mSplat; + } + } + } +} diff --git a/benchmarks/ArrayListIterationBenchmark.java b/benchmarks/ArrayListIterationBenchmark.java new file mode 100644 index 0000000..4e5f145 --- /dev/null +++ b/benchmarks/ArrayListIterationBenchmark.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +import java.util.ArrayList; + +/** + * Is a hand-coded counted loop through an ArrayList cheaper than enhanced for? + */ +public class ArrayListIterationBenchmark extends SimpleBenchmark { + ArrayList<Foo> mList = new ArrayList<Foo>(); + { + for (int i = 0; i < 27; ++i) mList.add(new Foo()); + } + public void timeArrayListIterationIndexed(int reps) { + for (int rep = 0; rep < reps; ++rep) { + int sum = 0; + ArrayList<Foo> list = mList; + int len = list.size(); + for (int i = 0; i < len; ++i) { + sum += list.get(i).mSplat; + } + } + } + public void timeArrayListIterationForEach(int reps) { + for (int rep = 0; rep < reps; ++rep) { + int sum = 0; + for (Foo a : mList) { + sum += a.mSplat; + } + } + } +} diff --git a/benchmarks/BufferedZipFileBenchmark.java b/benchmarks/BufferedZipFileBenchmark.java new file mode 100644 index 0000000..f4d3822 --- /dev/null +++ b/benchmarks/BufferedZipFileBenchmark.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package benchmarks; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.util.Random; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; + +public final class BufferedZipFileBenchmark extends SimpleBenchmark { + @Param({"128", "1024", "8192", "65536"}) int compressedSize; + @Param({"4", "32", "128"}) int readSize; + + private File file; + + @Override protected void setUp() throws Exception { + file = File.createTempFile(getClass().getName(), ".zip"); + file.deleteOnExit(); + + Random random = new Random(0); + ZipOutputStream out = new ZipOutputStream(new FileOutputStream(file)); + byte[] data = new byte[8192]; + out.putNextEntry(new ZipEntry("entry.data")); + int written = 0; + while (written < compressedSize) { + random.nextBytes(data); + int toWrite = Math.min(compressedSize - written, data.length); + out.write(data, 0, toWrite); + written += toWrite; + } + out.close(); + } + + public void timeUnbufferedRead(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + ZipFile zipFile = new ZipFile(file); + ZipEntry entry = zipFile.getEntry("entry.data"); + InputStream in = zipFile.getInputStream(entry); + byte[] buffer = new byte[readSize]; + while (in.read(buffer) != -1) { + } + in.close(); + zipFile.close(); + } + } + + public void timeBufferedRead(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + ZipFile zipFile = new ZipFile(file); + ZipEntry entry = zipFile.getEntry("entry.data"); + InputStream in = new BufferedInputStream(zipFile.getInputStream(entry)); + byte[] buffer = new byte[readSize]; + while (in.read(buffer) != -1) { + } + in.close(); + zipFile.close(); + } + } +} diff --git a/benchmarks/FieldAccessBenchmark.java b/benchmarks/FieldAccessBenchmark.java new file mode 100644 index 0000000..19cb060 --- /dev/null +++ b/benchmarks/FieldAccessBenchmark.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +/** + * What does field access cost? + */ +public class FieldAccessBenchmark extends SimpleBenchmark { + private static class Inner { + public int publicInnerIntVal; + protected int protectedInnerIntVal; + private int privateInnerIntVal; + int packageInnerIntVal; + } + int intVal = 42; + final int finalIntVal = 42; + static int staticIntVal = 42; + static final int staticFinalIntVal = 42; + public int timeField(int reps) { + int result = 0; + for (int rep = 0; rep < reps; ++rep) { + result = intVal; + } + return result; + } + public int timeFieldFinal(int reps) { + int result = 0; + for (int rep = 0; rep < reps; ++rep) { + result = finalIntVal; + } + return result; + } + public int timeFieldStatic(int reps) { + int result = 0; + for (int rep = 0; rep < reps; ++rep) { + result = staticIntVal; + } + return result; + } + public int timeFieldStaticFinal(int reps) { + int result = 0; + for (int rep = 0; rep < reps; ++rep) { + result = staticFinalIntVal; + } + return result; + } + public int timeFieldCached(int reps) { + int result = 0; + int cachedIntVal = this.intVal; + for (int rep = 0; rep < reps; ++rep) { + result = cachedIntVal; + } + return result; + } + public int timeFieldPrivateInnerClassPublicField(int reps) { + int result = 0; + Inner inner = new Inner(); + for (int rep = 0; rep < reps; ++rep) { + result = inner.publicInnerIntVal; + } + return result; + } + public int timeFieldPrivateInnerClassProtectedField(int reps) { + int result = 0; + Inner inner = new Inner(); + for (int rep = 0; rep < reps; ++rep) { + result = inner.protectedInnerIntVal; + } + return result; + } + public int timeFieldPrivateInnerClassPrivateField(int reps) { + int result = 0; + Inner inner = new Inner(); + for (int rep = 0; rep < reps; ++rep) { + result = inner.privateInnerIntVal; + } + return result; + } + public int timeFieldPrivateInnerClassPackageField(int reps) { + int result = 0; + Inner inner = new Inner(); + for (int rep = 0; rep < reps; ++rep) { + result = inner.packageInnerIntVal; + } + return result; + } +} diff --git a/benchmarks/Foo.java b/benchmarks/Foo.java new file mode 100644 index 0000000..d288dd6 --- /dev/null +++ b/benchmarks/Foo.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks; + +/** + * A trivial class used by several benchmarks. + */ +public class Foo { + int mSplat; +} diff --git a/benchmarks/HashedCollectionsBenchmark.java b/benchmarks/HashedCollectionsBenchmark.java new file mode 100644 index 0000000..a826271 --- /dev/null +++ b/benchmarks/HashedCollectionsBenchmark.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.LinkedHashMap; + +/** + * How do the various hash maps compare? + */ +public class HashedCollectionsBenchmark extends SimpleBenchmark { + public void timeHashMapGet(int reps) { + HashMap<String, String> map = new HashMap<String, String>(); + map.put("hello", "world"); + for (int i = 0; i < reps; ++i) { + map.get("hello"); + } + } + public void timeHashMapGet_Synchronized(int reps) { + HashMap<String, String> map = new HashMap<String, String>(); + synchronized (map) { + map.put("hello", "world"); + } + for (int i = 0; i < reps; ++i) { + synchronized (map) { + map.get("hello"); + } + } + } + public void timeHashtableGet(int reps) { + Hashtable<String, String> map = new Hashtable<String, String>(); + map.put("hello", "world"); + for (int i = 0; i < reps; ++i) { + map.get("hello"); + } + } + public void timeLinkedHashMapGet(int reps) { + LinkedHashMap<String, String> map = new LinkedHashMap<String, String>(); + map.put("hello", "world"); + for (int i = 0; i < reps; ++i) { + map.get("hello"); + } + } + public void timeConcurrentHashMapGet(int reps) { + ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>(); + map.put("hello", "world"); + for (int i = 0; i < reps; ++i) { + map.get("hello"); + } + } +} diff --git a/benchmarks/MethodInvocationBenchmark.java b/benchmarks/MethodInvocationBenchmark.java new file mode 100644 index 0000000..7a5e1b6 --- /dev/null +++ b/benchmarks/MethodInvocationBenchmark.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +/** + * Compares various kinds of method invocation. + */ +public class MethodInvocationBenchmark extends SimpleBenchmark { + interface I { + void emptyInterface(); + } + + static class C implements I { + private int field; + + private int getField() { + return field; + } + + public int timeInternalGetter(int reps) { + int result = 0; + for (int i = 0; i < reps; ++i) { + result = getField(); + } + return result; + } + + public int timeInternalFieldAccess(int reps) { + int result = 0; + for (int i = 0; i < reps; ++i) { + result = field; + } + return result; + } + + public static void emptyStatic() { + } + + public void emptyVirtual() { + } + + public void emptyInterface() { + } + } + + public void timeInternalGetter(int reps) { + new C().timeInternalGetter(reps); + } + + public void timeInternalFieldAccess(int reps) { + new C().timeInternalFieldAccess(reps); + } + + // Test an intrinsic. + public int timeStringLength(int reps) { + int result = 0; + for (int i = 0; i < reps; ++i) { + result = "hello, world!".length(); + } + return result; + } + + public void timeEmptyStatic(int reps) { + C c = new C(); + for (int i = 0; i < reps; ++i) { + c.emptyStatic(); + } + } + + public void timeEmptyVirtual(int reps) { + C c = new C(); + for (int i = 0; i < reps; ++i) { + c.emptyVirtual(); + } + } + + public void timeEmptyInterface(int reps) { + I c = new C(); + for (int i = 0; i < reps; ++i) { + c.emptyInterface(); + } + } + + public static class Inner { + private int i; + private void privateMethod() { ++i; } + protected void protectedMethod() { ++i; } + public void publicMethod() { ++i; } + void packageMethod() { ++i; } + final void finalPackageMethod() { ++i; } + } + + public void timePrivateInnerPublicMethod(int reps) { + Inner inner = new Inner(); + for (int i = 0; i < reps; ++i) { + inner.publicMethod(); + } + } + + public void timePrivateInnerProtectedMethod(int reps) { + Inner inner = new Inner(); + for (int i = 0; i < reps; ++i) { + inner.protectedMethod(); + } + } + + public void timePrivateInnerPrivateMethod(int reps) { + Inner inner = new Inner(); + for (int i = 0; i < reps; ++i) { + inner.privateMethod(); + } + } + + public void timePrivateInnerPackageMethod(int reps) { + Inner inner = new Inner(); + for (int i = 0; i < reps; ++i) { + inner.packageMethod(); + } + } + + public void timePrivateInnerFinalPackageMethod(int reps) { + Inner inner = new Inner(); + for (int i = 0; i < reps; ++i) { + inner.finalPackageMethod(); + } + } +} diff --git a/benchmarks/MultiplicationBenchmark.java b/benchmarks/MultiplicationBenchmark.java new file mode 100644 index 0000000..b2f945b --- /dev/null +++ b/benchmarks/MultiplicationBenchmark.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +/** + * How much do various kinds of multiplication cost? + */ +public class MultiplicationBenchmark extends SimpleBenchmark { + public int timeMultiplyIntByConstant10(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result *= 10; + } + return result; + } + public int timeMultiplyIntByConstant8(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result *= 8; + } + return result; + } + public int timeMultiplyIntByVariable10(int reps) { + int result = 1; + int factor = 10; + for (int i = 0; i < reps; ++i) { + result *= factor; + } + return result; + } + public int timeMultiplyIntByVariable8(int reps) { + int result = 1; + int factor = 8; + for (int i = 0; i < reps; ++i) { + result *= factor; + } + return result; + } +} diff --git a/benchmarks/StringIterationBenchmark.java b/benchmarks/StringIterationBenchmark.java new file mode 100644 index 0000000..22c6ae2 --- /dev/null +++ b/benchmarks/StringIterationBenchmark.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +/** + * How do the various schemes for iterating through a string compare? + */ +public class StringIterationBenchmark extends SimpleBenchmark { + public void timeStringIteration0(int reps) { + String s = "hello, world!"; + for (int rep = 0; rep < reps; ++rep) { + char ch; + for (int i = 0; i < s.length(); ++i) { + ch = s.charAt(i); + } + } + } + public void timeStringIteration1(int reps) { + String s = "hello, world!"; + for (int rep = 0; rep < reps; ++rep) { + char ch; + for (int i = 0, length = s.length(); i < length; ++i) { + ch = s.charAt(i); + } + } + } + public void timeStringIteration2(int reps) { + String s = "hello, world!"; + for (int rep = 0; rep < reps; ++rep) { + char ch; + char[] chars = s.toCharArray(); + for (int i = 0, length = chars.length; i < length; ++i) { + ch = chars[i]; + } + } + } + public void timeStringToCharArray(int reps) { + String s = "hello, world!"; + for (int rep = 0; rep < reps; ++rep) { + char[] chars = s.toCharArray(); + } + } +} diff --git a/benchmarks/VirtualVersusInterfaceBenchmark.java b/benchmarks/VirtualVersusInterfaceBenchmark.java new file mode 100644 index 0000000..f029c81 --- /dev/null +++ b/benchmarks/VirtualVersusInterfaceBenchmark.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +import java.util.Map; +import java.util.HashMap; + +/** + * Is there a performance reason to "Prefer virtual over interface", as the + * Android documentation once claimed? + */ +public class VirtualVersusInterfaceBenchmark extends SimpleBenchmark { + public void timeMapPut(int reps) { + Map<String, String> map = new HashMap<String, String>(); + for (int i = 0; i < reps; ++i) { + map.put("hello", "world"); + } + } + public void timeHashMapPut(int reps) { + HashMap<String, String> map = new HashMap<String, String>(); + for (int i = 0; i < reps; ++i) { + map.put("hello", "world"); + } + } +} diff --git a/benchmarks/XmlParseBenchmark.java b/benchmarks/XmlParseBenchmark.java new file mode 100644 index 0000000..b5e7b93 --- /dev/null +++ b/benchmarks/XmlParseBenchmark.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.util.Arrays; +import java.util.List; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; +import org.xmlpull.v1.XmlPullParser; + +public class XmlParseBenchmark extends SimpleBenchmark { + + @Param String xmlFile; + ByteArrayInputStream inputStream; + + static List<String> xmlFileValues = Arrays.asList( + "/etc/apns-conf.xml", + "/etc/media_profiles.xml", + "/etc/permissions/features.xml" + ); + + private SAXParser saxParser; + private DocumentBuilder documentBuilder; + private Constructor<? extends XmlPullParser> kxmlConstructor; + private Constructor<? extends XmlPullParser> expatConstructor; + + @SuppressWarnings("unchecked") + @Override protected void setUp() throws Exception { + byte[] xmlBytes = getXmlBytes(); + inputStream = new ByteArrayInputStream(xmlBytes); + inputStream.mark(xmlBytes.length); + + SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); + saxParser = saxParserFactory.newSAXParser(); + + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + documentBuilder = builderFactory.newDocumentBuilder(); + + kxmlConstructor = (Constructor) Class.forName("org.kxml2.io.KXmlParser").getConstructor(); + expatConstructor = (Constructor) Class.forName("org.apache.harmony.xml.ExpatPullParser") + .getConstructor(); + } + + private byte[] getXmlBytes() throws IOException { + FileInputStream fileIn = new FileInputStream(xmlFile); + ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); + int count; + byte[] buffer = new byte[1024]; + while ((count = fileIn.read(buffer)) != -1) { + bytesOut.write(buffer, 0, count); + } + fileIn.close(); + return bytesOut.toByteArray(); + } + + public int timeSax(int reps) throws IOException, SAXException { + int elementCount = 0; + for (int i = 0; i < reps; i++) { + inputStream.reset(); + ElementCounterSaxHandler elementCounterSaxHandler = new ElementCounterSaxHandler(); + saxParser.parse(inputStream, elementCounterSaxHandler); + elementCount += elementCounterSaxHandler.elementCount; + } + return elementCount; + } + + private static class ElementCounterSaxHandler extends DefaultHandler { + int elementCount = 0; + @Override public void startElement(String uri, String localName, + String qName, Attributes attributes) { + elementCount++; + } + } + + public int timeDom(int reps) throws IOException, SAXException { + int elementCount = 0; + for (int i = 0; i < reps; i++) { + inputStream.reset(); + Document document = documentBuilder.parse(inputStream); + elementCount += countDomElements(document.getDocumentElement()); + } + return elementCount; + } + + private int countDomElements(Node node) { + int result = 0; + for (; node != null; node = node.getNextSibling()) { + if (node.getNodeType() == Node.ELEMENT_NODE) { + result++; + } + result += countDomElements(node.getFirstChild()); + } + return result; + } + + public int timeExpat(int reps) throws Exception { + return testXmlPull(expatConstructor, reps); + } + + public int timeKxml(int reps) throws Exception { + return testXmlPull(kxmlConstructor, reps); + } + + private int testXmlPull(Constructor<? extends XmlPullParser> constructor, int reps) + throws Exception { + int elementCount = 0; + for (int i = 0; i < reps; i++) { + inputStream.reset(); + XmlPullParser xmlPullParser = constructor.newInstance(); + xmlPullParser.setInput(inputStream, "UTF-8"); + int type; + while ((type = xmlPullParser.next()) != XmlPullParser.END_DOCUMENT) { + if (type == XmlPullParser.START_TAG) { + elementCount++; + } + } + } + return elementCount; + } + + public static void main(String[] args) { + Runner.main(XmlParseBenchmark.class, args); + } +} diff --git a/benchmarks/regression/AnnotatedElementBenchmark.java b/benchmarks/regression/AnnotatedElementBenchmark.java new file mode 100644 index 0000000..6c33968 --- /dev/null +++ b/benchmarks/regression/AnnotatedElementBenchmark.java @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +public class AnnotatedElementBenchmark extends SimpleBenchmark { + + private Class<?> type; + private Field field; + private Method method; + + @Override protected void setUp() throws Exception { + type = Type.class; + field = Type.class.getField("field"); + method = Type.class.getMethod("method", String.class); + } + + + // get annotations by member type and method + + public void timeGetTypeAnnotations(int reps) { + for (int i = 0; i < reps; i++) { + type.getAnnotations(); + } + } + + public void timeGetFieldAnnotations(int reps) { + for (int i = 0; i < reps; i++) { + field.getAnnotations(); + } + } + + public void timeGetMethodAnnotations(int reps) { + for (int i = 0; i < reps; i++) { + method.getAnnotations(); + } + } + + public void timeGetParameterAnnotations(int reps) { + for (int i = 0; i < reps; i++) { + method.getParameterAnnotations(); + } + } + + public void timeGetTypeAnnotation(int reps) { + for (int i = 0; i < reps; i++) { + type.getAnnotation(Marker.class); + } + } + + public void timeGetFieldAnnotation(int reps) { + for (int i = 0; i < reps; i++) { + field.getAnnotation(Marker.class); + } + } + + public void timeGetMethodAnnotation(int reps) { + for (int i = 0; i < reps; i++) { + method.getAnnotation(Marker.class); + } + } + + public void timeIsTypeAnnotationPresent(int reps) { + for (int i = 0; i < reps; i++) { + type.isAnnotationPresent(Marker.class); + } + } + + public void timeIsFieldAnnotationPresent(int reps) { + for (int i = 0; i < reps; i++) { + field.isAnnotationPresent(Marker.class); + } + } + + public void timeIsMethodAnnotationPresent(int reps) { + for (int i = 0; i < reps; i++) { + method.isAnnotationPresent(Marker.class); + } + } + + // get annotations by result size + + public void timeGetAllReturnsLargeAnnotation(int reps) { + for (int i = 0; i < reps; i++) { + HasLargeAnnotation.class.getAnnotations(); + } + } + + public void timeGetAllReturnsSmallAnnotation(int reps) { + for (int i = 0; i < reps; i++) { + HasSmallAnnotation.class.getAnnotations(); + } + } + + public void timeGetAllReturnsMarkerAnnotation(int reps) { + for (int i = 0; i < reps; i++) { + HasMarkerAnnotation.class.getAnnotations(); + } + } + + public void timeGetAllReturnsNoAnnotation(int reps) { + for (int i = 0; i < reps; i++) { + HasNoAnnotations.class.getAnnotations(); + } + } + + public void timeGetAllReturnsThreeAnnotations(int reps) { + for (int i = 0; i < reps; i++) { + HasThreeAnnotations.class.getAnnotations(); + } + } + + + // get annotations with inheritance + + public void timeGetAnnotationsOnSubclass(int reps) { + for (int i = 0; i < reps; i++) { + ExtendsHasThreeAnnotations.class.getAnnotations(); + } + } + + public void timeGetDeclaredAnnotationsOnSubclass(int reps) { + for (int i = 0; i < reps; i++) { + ExtendsHasThreeAnnotations.class.getAnnotations(); + } + } + + + // the annotated elements + + @Marker + public class Type { + @Marker public String field; + @Marker public void method(@Marker String parameter) {} + } + + @Large(a = "on class", b = {"A", "B", "C" }, + c = @Small(e="E1", f=1695938256, g=7264081114510713000L), + d = { @Small(e="E2", f=1695938256, g=7264081114510713000L) }) + public class HasLargeAnnotation {} + + @Small(e="E1", f=1695938256, g=7264081114510713000L) + public class HasSmallAnnotation {} + + @Marker + public class HasMarkerAnnotation {} + + public class HasNoAnnotations {} + + @Large(a = "on class", b = {"A", "B", "C" }, + c = @Small(e="E1", f=1695938256, g=7264081114510713000L), + d = { @Small(e="E2", f=1695938256, g=7264081114510713000L) }) + @Small(e="E1", f=1695938256, g=7264081114510713000L) + @Marker + public class HasThreeAnnotations {} + + public class ExtendsHasThreeAnnotations {} + + + // the annotations + + @Retention(RetentionPolicy.RUNTIME) + public @interface Marker {} + + @Retention(RetentionPolicy.RUNTIME) + public @interface Large { + String a() default ""; + String[] b() default {}; + Small c() default @Small; + Small[] d() default {}; + } + + @Retention(RetentionPolicy.RUNTIME) + public @interface Small { + String e() default ""; + int f() default 0; + long g() default 0L; + } + + public static void main(String[] args) throws Exception { + Runner.main(AnnotatedElementBenchmark.class, args); + } +} diff --git a/benchmarks/regression/BigIntegerBenchmark.java b/benchmarks/regression/BigIntegerBenchmark.java new file mode 100644 index 0000000..841b901 --- /dev/null +++ b/benchmarks/regression/BigIntegerBenchmark.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import java.math.BigInteger; +import java.util.Random; +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; + +public class BigIntegerBenchmark extends SimpleBenchmark { + public void timeRandomDivision(int reps) throws Exception { + Random r = new Random(); + BigInteger x = new BigInteger(1024, r); + BigInteger y = new BigInteger(1024, r); + for (int i = 0; i < reps; ++i) { + x.divide(y); + } + } + + public void timeRandomGcd(int reps) throws Exception { + Random r = new Random(); + BigInteger x = new BigInteger(1024, r); + BigInteger y = new BigInteger(1024, r); + for (int i = 0; i < reps; ++i) { + x.gcd(y); + } + } + + public void timeRandomMultiplication(int reps) throws Exception { + Random r = new Random(); + BigInteger x = new BigInteger(1024, r); + BigInteger y = new BigInteger(1024, r); + for (int i = 0; i < reps; ++i) { + x.multiply(y); + } + } +} diff --git a/benchmarks/regression/BitSetBenchmark.java b/benchmarks/regression/BitSetBenchmark.java new file mode 100644 index 0000000..ee91993 --- /dev/null +++ b/benchmarks/regression/BitSetBenchmark.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; +import java.util.BitSet; + +public class BitSetBenchmark extends SimpleBenchmark { + @Param({ "1000", "10000" }) + private int size; + + private BitSet bs; + + @Override protected void setUp() throws Exception { + bs = new BitSet(size); + } + + public void timeIsEmptyTrue(int reps) { + for (int i = 0; i < reps; ++i) { + if (!bs.isEmpty()) throw new RuntimeException(); + } + } + + public void timeIsEmptyFalse(int reps) { + bs.set(bs.size() - 1); + for (int i = 0; i < reps; ++i) { + if (bs.isEmpty()) throw new RuntimeException(); + } + } + + public void timeGet(int reps) { + for (int i = 0; i < reps; ++i) { + bs.get(i % size); + } + } + + public void timeClear(int reps) { + for (int i = 0; i < reps; ++i) { + bs.clear(i % size); + } + } + + public void timeSet(int reps) { + for (int i = 0; i < reps; ++i) { + bs.set(i % size); + } + } + + public void timeSetOn(int reps) { + for (int i = 0; i < reps; ++i) { + bs.set(i % size, true); + } + } + + public void timeSetOff(int reps) { + for (int i = 0; i < reps; ++i) { + bs.set(i % size, false); + } + } +} diff --git a/benchmarks/regression/ByteBufferBenchmark.java b/benchmarks/regression/ByteBufferBenchmark.java new file mode 100644 index 0000000..7812013 --- /dev/null +++ b/benchmarks/regression/ByteBufferBenchmark.java @@ -0,0 +1,411 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +import java.io.*; +import java.nio.*; +import java.nio.channels.*; +import java.util.Arrays; +import java.util.Collection; + +public class ByteBufferBenchmark extends SimpleBenchmark { + public enum MyByteOrder { + BIG(ByteOrder.BIG_ENDIAN), LITTLE(ByteOrder.LITTLE_ENDIAN); + final ByteOrder byteOrder; + MyByteOrder(ByteOrder byteOrder) { + this.byteOrder = byteOrder; + } + } + + @Param private MyByteOrder byteOrder; + + @Param({"true", "false"}) private boolean aligned; + + enum MyBufferType { + DIRECT, HEAP, MAPPED; + } + @Param private MyBufferType bufferType; + + public static ByteBuffer newBuffer(MyByteOrder byteOrder, boolean aligned, MyBufferType bufferType) throws IOException { + int size = aligned ? 8192 : 8192 + 8 + 1; + ByteBuffer result = null; + switch (bufferType) { + case DIRECT: + result = ByteBuffer.allocateDirect(size); + break; + case HEAP: + result = ByteBuffer.allocate(size); + break; + case MAPPED: + File tmpFile = new File("/sdcard/bm.tmp"); + if (new File("/tmp").isDirectory()) { + // We're running on the desktop. + tmpFile = File.createTempFile("MappedByteBufferTest", ".tmp"); + } + tmpFile.createNewFile(); + tmpFile.deleteOnExit(); + RandomAccessFile raf = new RandomAccessFile(tmpFile, "rw"); + raf.setLength(8192*8); + FileChannel fc = raf.getChannel(); + result = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size()); + break; + } + result.order(byteOrder.byteOrder); + result.position(aligned ? 0 : 1); + return result; + } + + // + // peeking + // + + public void timeByteBuffer_getByte(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + for (int i = 0; i < 1024; ++i) { + src.get(); + } + } + } + + public void timeByteBuffer_getByteArray(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + byte[] dst = new byte[1024]; + for (int rep = 0; rep < reps; ++rep) { + for (int i = 0; i < 1024; ++i) { + src.position(aligned ? 0 : 1); + src.get(dst); + } + } + } + + public void timeByteBuffer_getByte_indexed(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + for (int i = 0; i < 1024; ++i) { + src.get(i); + } + } + } + + public void timeByteBuffer_getChar(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + for (int i = 0; i < 1024; ++i) { + src.getChar(); + } + } + } + + public void timeCharBuffer_getCharArray(int reps) throws Exception { + CharBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType).asCharBuffer(); + char[] dst = new char[1024]; + for (int rep = 0; rep < reps; ++rep) { + for (int i = 0; i < 1024; ++i) { + src.position(0); + src.get(dst); + } + } + } + + public void timeByteBuffer_getChar_indexed(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + for (int i = 0; i < 1024; ++i) { + src.getChar(i * 2); + } + } + } + + public void timeByteBuffer_getDouble(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + for (int i = 0; i < 1024; ++i) { + src.getDouble(); + } + } + } + + public void timeDoubleBuffer_getDoubleArray(int reps) throws Exception { + DoubleBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType).asDoubleBuffer(); + double[] dst = new double[1024]; + for (int rep = 0; rep < reps; ++rep) { + for (int i = 0; i < 1024; ++i) { + src.position(0); + src.get(dst); + } + } + } + + public void timeByteBuffer_getFloat(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + for (int i = 0; i < 1024; ++i) { + src.getFloat(); + } + } + } + + public void timeFloatBuffer_getFloatArray(int reps) throws Exception { + FloatBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType).asFloatBuffer(); + float[] dst = new float[1024]; + for (int rep = 0; rep < reps; ++rep) { + for (int i = 0; i < 1024; ++i) { + src.position(0); + src.get(dst); + } + } + } + + public void timeByteBuffer_getInt(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + for (int i = 0; i < 1024; ++i) { + src.getInt(); + } + } + } + + public void timeIntBuffer_getIntArray(int reps) throws Exception { + IntBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType).asIntBuffer(); + int[] dst = new int[1024]; + for (int rep = 0; rep < reps; ++rep) { + for (int i = 0; i < 1024; ++i) { + src.position(0); + src.get(dst); + } + } + } + + public void timeByteBuffer_getLong(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + for (int i = 0; i < 1024; ++i) { + src.getLong(); + } + } + } + + public void timeLongBuffer_getLongArray(int reps) throws Exception { + LongBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType).asLongBuffer(); + long[] dst = new long[1024]; + for (int rep = 0; rep < reps; ++rep) { + for (int i = 0; i < 1024; ++i) { + src.position(0); + src.get(dst); + } + } + } + + public void timeByteBuffer_getShort(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + for (int i = 0; i < 1024; ++i) { + src.getShort(); + } + } + } + + public void timeShortBuffer_getShortArray(int reps) throws Exception { + ShortBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType).asShortBuffer(); + short[] dst = new short[1024]; + for (int rep = 0; rep < reps; ++rep) { + for (int i = 0; i < 1024; ++i) { + src.position(0); + src.get(dst); + } + } + } + + // + // poking + // + + public void timeByteBuffer_putByte(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(0); + for (int i = 0; i < 1024; ++i) { + src.put((byte) 0); + } + } + } + + public void timeByteBuffer_putByteArray(int reps) throws Exception { + ByteBuffer dst = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + byte[] src = new byte[1024]; + for (int rep = 0; rep < reps; ++rep) { + for (int i = 0; i < 1024; ++i) { + dst.position(aligned ? 0 : 1); + dst.put(src); + } + } + } + + public void timeByteBuffer_putChar(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + for (int i = 0; i < 1024; ++i) { + src.putChar(' '); + } + } + } + + public void timeCharBuffer_putCharArray(int reps) throws Exception { + CharBuffer dst = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType).asCharBuffer(); + char[] src = new char[1024]; + for (int rep = 0; rep < reps; ++rep) { + for (int i = 0; i < 1024; ++i) { + dst.position(0); + dst.put(src); + } + } + } + + public void timeByteBuffer_putDouble(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + for (int i = 0; i < 1024; ++i) { + src.putDouble(0.0); + } + } + } + + public void timeDoubleBuffer_putDoubleArray(int reps) throws Exception { + DoubleBuffer dst = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType).asDoubleBuffer(); + double[] src = new double[1024]; + for (int rep = 0; rep < reps; ++rep) { + for (int i = 0; i < 1024; ++i) { + dst.position(0); + dst.put(src); + } + } + } + + public void timeByteBuffer_putFloat(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + for (int i = 0; i < 1024; ++i) { + src.putFloat(0.0f); + } + } + } + + public void timeFloatBuffer_putFloatArray(int reps) throws Exception { + FloatBuffer dst = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType).asFloatBuffer(); + float[] src = new float[1024]; + for (int rep = 0; rep < reps; ++rep) { + for (int i = 0; i < 1024; ++i) { + dst.position(0); + dst.put(src); + } + } + } + + public void timeByteBuffer_putInt(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + for (int i = 0; i < 1024; ++i) { + src.putInt(0); + } + } + } + + public void timeIntBuffer_putIntArray(int reps) throws Exception { + IntBuffer dst = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType).asIntBuffer(); + int[] src = new int[1024]; + for (int rep = 0; rep < reps; ++rep) { + for (int i = 0; i < 1024; ++i) { + dst.position(0); + dst.put(src); + } + } + } + + public void timeByteBuffer_putLong(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + for (int i = 0; i < 1024; ++i) { + src.putLong(0L); + } + } + } + + public void timeLongBuffer_putLongArray(int reps) throws Exception { + LongBuffer dst = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType).asLongBuffer(); + long[] src = new long[1024]; + for (int rep = 0; rep < reps; ++rep) { + for (int i = 0; i < 1024; ++i) { + dst.position(0); + dst.put(src); + } + } + } + + public void timeByteBuffer_putShort(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + for (int i = 0; i < 1024; ++i) { + src.putShort((short) 0); + } + } + } + + public void timeShortBuffer_putShortArray(int reps) throws Exception { + ShortBuffer dst = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType).asShortBuffer(); + short[] src = new short[1024]; + for (int rep = 0; rep < reps; ++rep) { + for (int i = 0; i < 1024; ++i) { + dst.position(0); + dst.put(src); + } + } + } + +/* + public void time_new_byteArray(int reps) throws Exception { + for (int rep = 0; rep < reps; ++rep) { + byte[] bs = new byte[8192]; + } + } + + public void time_ByteBuffer_allocate(int reps) throws Exception { + for (int rep = 0; rep < reps; ++rep) { + ByteBuffer bs = ByteBuffer.allocate(8192); + } + } + */ +} diff --git a/benchmarks/regression/ByteBufferScalarVersusVectorBenchmark.java b/benchmarks/regression/ByteBufferScalarVersusVectorBenchmark.java new file mode 100644 index 0000000..7c75deb --- /dev/null +++ b/benchmarks/regression/ByteBufferScalarVersusVectorBenchmark.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2012 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +import java.io.*; +import java.nio.*; +import java.nio.channels.*; +import java.util.Arrays; +import java.util.Collection; + +public class ByteBufferScalarVersusVectorBenchmark extends SimpleBenchmark { + @Param private ByteBufferBenchmark.MyByteOrder byteOrder; + @Param({"true", "false"}) private boolean aligned; + @Param private ByteBufferBenchmark.MyBufferType bufferType; + + public void timeManualByteBufferCopy(int reps) throws Exception { + ByteBuffer src = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + ByteBuffer dst = ByteBufferBenchmark.newBuffer(byteOrder, aligned, bufferType); + for (int rep = 0; rep < reps; ++rep) { + src.position(0); + dst.position(0); + for (int i = 0; i < 8192; ++i) { + dst.put(src.get()); + } + } + } + + public void timeByteBufferBulkGet(int reps) throws Exception { + ByteBuffer src = ByteBuffer.allocate(aligned ? 8192 : 8192 + 1); + byte[] dst = new byte[8192]; + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + src.get(dst, 0, dst.length); + } + } + + public void timeDirectByteBufferBulkGet(int reps) throws Exception { + ByteBuffer src = ByteBuffer.allocateDirect(aligned ? 8192 : 8192 + 1); + byte[] dst = new byte[8192]; + for (int rep = 0; rep < reps; ++rep) { + src.position(aligned ? 0 : 1); + src.get(dst, 0, dst.length); + } + } +} diff --git a/benchmarks/regression/CharacterBenchmark.java b/benchmarks/regression/CharacterBenchmark.java new file mode 100644 index 0000000..953513b --- /dev/null +++ b/benchmarks/regression/CharacterBenchmark.java @@ -0,0 +1,299 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +/** + * Tests various Character methods, intended for testing multiple + * implementations against each other. + */ +public class CharacterBenchmark extends SimpleBenchmark { + + @Param private CharacterSet characterSet; + + @Param private Overload overload; + + private char[] chars; + + @Override protected void setUp() throws Exception { + this.chars = characterSet.chars; + } + + public enum Overload { CHAR, INT } + + @Override public double nanosToUnits(double nanos) { + return nanos / 65536; + } + + public enum CharacterSet { + ASCII(128), + UNICODE(65536); + final char[] chars; + CharacterSet(int size) { + this.chars = new char[65536]; + for (int i = 0; i < 65536; ++i) { + chars[i] = (char) (i % size); + } + } + } + + // A fake benchmark to give us a baseline. + public boolean timeIsSpace(int reps) { + boolean dummy = false; + if (overload == Overload.CHAR) { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + dummy ^= ((char) ch == ' '); + } + } + } else { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + dummy ^= (ch == ' '); + } + } + } + return dummy; + } + + public void timeDigit(int reps) { + if (overload == Overload.CHAR) { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.digit(chars[ch], 10); + } + } + } else { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.digit((int) chars[ch], 10); + } + } + } + } + + public void timeGetNumericValue(int reps) { + if (overload == Overload.CHAR) { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.getNumericValue(chars[ch]); + } + } + } else { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.getNumericValue((int) chars[ch]); + } + } + } + } + + public void timeIsDigit(int reps) { + if (overload == Overload.CHAR) { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isDigit(chars[ch]); + } + } + } else { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isDigit((int) chars[ch]); + } + } + } + } + + public void timeIsIdentifierIgnorable(int reps) { + if (overload == Overload.CHAR) { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isIdentifierIgnorable(chars[ch]); + } + } + } else { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isIdentifierIgnorable((int) chars[ch]); + } + } + } + } + + public void timeIsJavaIdentifierPart(int reps) { + if (overload == Overload.CHAR) { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isJavaIdentifierPart(chars[ch]); + } + } + } else { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isJavaIdentifierPart((int) chars[ch]); + } + } + } + } + + public void timeIsJavaIdentifierStart(int reps) { + if (overload == Overload.CHAR) { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isJavaIdentifierStart(chars[ch]); + } + } + } else { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isJavaIdentifierStart((int) chars[ch]); + } + } + } + } + + public void timeIsLetter(int reps) { + if (overload == Overload.CHAR) { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isLetter(chars[ch]); + } + } + } else { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isLetter((int) chars[ch]); + } + } + } + } + + public void timeIsLetterOrDigit(int reps) { + if (overload == Overload.CHAR) { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isLetterOrDigit(chars[ch]); + } + } + } else { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isLetterOrDigit((int) chars[ch]); + } + } + } + } + + public void timeIsLowerCase(int reps) { + if (overload == Overload.CHAR) { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isLowerCase(chars[ch]); + } + } + } else { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isLowerCase((int) chars[ch]); + } + } + } + } + + public void timeIsSpaceChar(int reps) { + if (overload == Overload.CHAR) { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isSpaceChar(chars[ch]); + } + } + } else { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isSpaceChar((int) chars[ch]); + } + } + } + } + + public void timeIsUpperCase(int reps) { + if (overload == Overload.CHAR) { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isUpperCase(chars[ch]); + } + } + } else { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isUpperCase((int) chars[ch]); + } + } + } + } + + public void timeIsWhitespace(int reps) { + if (overload == Overload.CHAR) { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isWhitespace(chars[ch]); + } + } + } else { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.isWhitespace((int) chars[ch]); + } + } + } + } + + public void timeToLowerCase(int reps) { + if (overload == Overload.CHAR) { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.toLowerCase(chars[ch]); + } + } + } else { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.toLowerCase((int) chars[ch]); + } + } + } + } + + public void timeToUpperCase(int reps) { + if (overload == Overload.CHAR) { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.toUpperCase(chars[ch]); + } + } + } else { + for (int i = 0; i < reps; ++i) { + for (int ch = 0; ch < 65536; ++ch) { + Character.toUpperCase((int) chars[ch]); + } + } + } + } +} diff --git a/benchmarks/regression/CharsetBenchmark.java b/benchmarks/regression/CharsetBenchmark.java new file mode 100644 index 0000000..6ecada7 --- /dev/null +++ b/benchmarks/regression/CharsetBenchmark.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import java.nio.charset.Charset; +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; + +public class CharsetBenchmark extends SimpleBenchmark { + @Param({ "1", "10", "100", "1000", "10000" }) + private int length; + + // canonical => canonical charset name + // built-in => guaranteed-present charset + // special-case => libcore treats this charset specially for performance + @Param({ + "UTF-16", // canonical, built-in, non-special-case + "UTF-8", // canonical, built-in, special-case + "UTF8", // non-canonical, built-in, special-case + "ISO-8859-1", // canonical, built-in, special-case + "8859_1", // non-canonical, built-in, special-case + "ISO-8859-2", // canonical, non-built-in, non-special-case + "8859_2", // non-canonical, non-built-in, non-special-case + "US-ASCII", // canonical, built-in, special-case + "ASCII" // non-canonical, built-in, special-case + }) + private String name; + + public void time_new_String_BString(int reps) throws Exception { + byte[] bytes = makeBytes(makeString(length)); + for (int i = 0; i < reps; ++i) { + new String(bytes, name); + } + } + + public void time_new_String_BII(int reps) throws Exception { + byte[] bytes = makeBytes(makeString(length)); + for (int i = 0; i < reps; ++i) { + new String(bytes, 0, bytes.length); + } + } + + public void time_new_String_BIIString(int reps) throws Exception { + byte[] bytes = makeBytes(makeString(length)); + for (int i = 0; i < reps; ++i) { + new String(bytes, 0, bytes.length, name); + } + } + + public void time_String_getBytes(int reps) throws Exception { + String string = makeString(length); + for (int i = 0; i < reps; ++i) { + string.getBytes(name); + } + } + + // FIXME: benchmark this pure-java implementation for US-ASCII and ISO-8859-1 too! + + /** + * Translates the given characters to US-ASCII or ISO-8859-1 bytes, using the fact that + * Unicode code points between U+0000 and U+007f inclusive are identical to US-ASCII, while + * U+0000 to U+00ff inclusive are identical to ISO-8859-1. + */ + private static byte[] toDirectMappedBytes(char[] chars, int offset, int length, int maxValidChar) { + byte[] result = new byte[length]; + int o = offset; + for (int i = 0; i < length; ++i) { + int ch = chars[o++]; + result[i] = (byte) ((ch <= maxValidChar) ? ch : '?'); + } + return result; + } + + private static byte[] toUtf8Bytes(char[] chars, int offset, int length) { + UnsafeByteSequence result = new UnsafeByteSequence(length); + toUtf8Bytes(chars, offset, length, result); + return result.toByteArray(); + } + + private static void toUtf8Bytes(char[] chars, int offset, int length, UnsafeByteSequence out) { + final int end = offset + length; + for (int i = offset; i < end; ++i) { + int ch = chars[i]; + if (ch < 0x80) { + // One byte. + out.write(ch); + } else if (ch < 0x800) { + // Two bytes. + out.write((ch >> 6) | 0xc0); + out.write((ch & 0x3f) | 0x80); + } else if (ch >= Character.MIN_SURROGATE && ch <= Character.MAX_SURROGATE) { + // A supplementary character. + char high = (char) ch; + char low = (i + 1 != end) ? chars[i + 1] : '\u0000'; + if (!Character.isSurrogatePair(high, low)) { + out.write('?'); + continue; + } + // Now we know we have a *valid* surrogate pair, we can consume the low surrogate. + ++i; + ch = Character.toCodePoint(high, low); + // Four bytes. + out.write((ch >> 18) | 0xf0); + out.write(((ch >> 12) & 0x3f) | 0x80); + out.write(((ch >> 6) & 0x3f) | 0x80); + out.write((ch & 0x3f) | 0x80); + } else { + // Three bytes. + out.write((ch >> 12) | 0xe0); + out.write(((ch >> 6) & 0x3f) | 0x80); + out.write((ch & 0x3f) | 0x80); + } + } + } + + private static String makeString(int length) { + StringBuilder result = new StringBuilder(length); + for (int i = 0; i < length; ++i) { + result.append('A' + (i % 26)); + } + return result.toString(); + } + + private static byte[] makeBytes(String s) { + try { + return s.getBytes("US-ASCII"); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } +} diff --git a/benchmarks/regression/CharsetForNameBenchmark.java b/benchmarks/regression/CharsetForNameBenchmark.java new file mode 100644 index 0000000..87dfb8b --- /dev/null +++ b/benchmarks/regression/CharsetForNameBenchmark.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import java.nio.charset.Charset; +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; + +public class CharsetForNameBenchmark extends SimpleBenchmark { + // canonical => canonical charset name + // built-in => guaranteed-present charset + // special-case => libcore treats this charset specially for performance + @Param({ + "UTF-16", // canonical, built-in, non-special-case + "UTF-8", // canonical, built-in, special-case + "UTF8", // non-canonical, built-in, special-case + "ISO-8859-1", // canonical, built-in, special-case + "8859_1", // non-canonical, built-in, special-case + "ISO-8859-2", // canonical, non-built-in, non-special-case + "8859_2", // non-canonical, non-built-in, non-special-case + "US-ASCII", // canonical, built-in, special-case + "ASCII" // non-canonical, built-in, special-case + }) + private String charsetName; + + public void timeCharsetForName(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + Charset.forName(charsetName); + } + } +} diff --git a/benchmarks/regression/ChecksumBenchmark.java b/benchmarks/regression/ChecksumBenchmark.java new file mode 100644 index 0000000..0e7bf8d --- /dev/null +++ b/benchmarks/regression/ChecksumBenchmark.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; +import java.util.zip.Adler32; +import java.util.zip.CRC32; + +public class ChecksumBenchmark extends SimpleBenchmark { + public void timeAdler_block(int reps) throws Exception { + byte[] bytes = new byte[10000]; + Adler32 adler = new Adler32(); + for (int i = 0; i < reps; ++i) { + adler.update(bytes); + } + } + public void timeAdler_byte(int reps) throws Exception { + Adler32 adler = new Adler32(); + for (int i = 0; i < reps; ++i) { + adler.update(1); + } + } + public void timeCrc_block(int reps) throws Exception { + byte[] bytes = new byte[10000]; + CRC32 crc = new CRC32(); + for (int i = 0; i < reps; ++i) { + crc.update(bytes); + } + } + public void timeCrc_byte(int reps) throws Exception { + CRC32 crc = new CRC32(); + for (int i = 0; i < reps; ++i) { + crc.update(1); + } + } +} diff --git a/benchmarks/regression/CipherBenchmark.java b/benchmarks/regression/CipherBenchmark.java new file mode 100644 index 0000000..56d549b --- /dev/null +++ b/benchmarks/regression/CipherBenchmark.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2012 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.spec.AlgorithmParameterSpec; + +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import java.util.HashMap; +import java.util.Map; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; + +/** + * Cipher benchmarks. Only runs on AES currently because of the combinatorial + * explosion of the test as it stands. + */ +public class CipherBenchmark extends SimpleBenchmark { + + private static final int DATA_SIZE = 8192; + private static final byte[] DATA = new byte[DATA_SIZE]; + + private static final int IV_SIZE = 16; + + private static final byte[] IV = new byte[IV_SIZE]; + + static { + for (int i = 0; i < DATA_SIZE; i++) { + DATA[i] = (byte) i; + } + for (int i = 0; i < IV_SIZE; i++) { + IV[i] = (byte) i; + } + } + + @Param private Algorithm algorithm; + + public enum Algorithm { + AES, + }; + + @Param private Mode mode; + + public enum Mode { + CBC, + CFB, + CTR, + ECB, + OFB, + }; + + @Param private Padding padding; + + public enum Padding { + NOPADDING, + PKCS1PADDING, + }; + + @Param({"128", "192", "256"}) private int keySize; + + @Param({"16", "32", "64", "128", "1024", "8192"}) private int inputSize; + + @Param private Implementation implementation; + + public enum Implementation { OpenSSL, BouncyCastle }; + + private String providerName; + + // Key generation isn't part of the benchmark so cache the results + private static Map<Integer, SecretKey> KEY_SIZES = new HashMap<Integer, SecretKey>(); + + private String cipherAlgorithm; + private SecretKey key; + + private byte[] output = new byte[DATA.length]; + + private Cipher cipherEncrypt; + + private Cipher cipherDecrypt; + + private AlgorithmParameterSpec spec; + + @Override protected void setUp() throws Exception { + cipherAlgorithm = algorithm.toString() + "/" + mode.toString() + "/" + + padding.toString(); + + String keyAlgorithm = algorithm.toString(); + key = KEY_SIZES.get(keySize); + if (key == null) { + KeyGenerator generator = KeyGenerator.getInstance(keyAlgorithm); + generator.init(keySize); + key = generator.generateKey(); + KEY_SIZES.put(keySize, key); + } + + switch (implementation) { + case OpenSSL: + providerName = "AndroidOpenSSL"; + break; + case BouncyCastle: + providerName = "BC"; + break; + default: + throw new RuntimeException(implementation.toString()); + } + + if (mode != Mode.ECB) { + spec = new IvParameterSpec(IV); + } + + cipherEncrypt = Cipher.getInstance(cipherAlgorithm, providerName); + cipherEncrypt.init(Cipher.ENCRYPT_MODE, key, spec); + + cipherDecrypt = Cipher.getInstance(cipherAlgorithm, providerName); + cipherDecrypt.init(Cipher.DECRYPT_MODE, key, spec); + } + + public void timeEncrypt(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + cipherEncrypt.doFinal(DATA, 0, inputSize, output); + } + } + + public void timeDecrypt(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + cipherDecrypt.doFinal(DATA, 0, inputSize, output); + } + } +} diff --git a/benchmarks/regression/DateToStringBenchmark.java b/benchmarks/regression/DateToStringBenchmark.java new file mode 100644 index 0000000..15760c9 --- /dev/null +++ b/benchmarks/regression/DateToStringBenchmark.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import android.text.format.DateFormat; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +public final class DateToStringBenchmark extends SimpleBenchmark { + Date date; + Calendar calendar; + SimpleDateFormat format; + + @Override + protected void setUp() throws Exception { + date = new Date(0); + calendar = new GregorianCalendar(); + calendar.setTime(date); + format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); + } + + public void timeDateToString(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + date.toString(); + } + } + + public void timeDateToString_Formatter(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy").format(date); + } + } + + public void timeDateToString_ClonedFormatter(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + ((SimpleDateFormat) format.clone()).format(date); + } + } + + public void timeDateToString_AndroidDateFormat(int reps) { + for (int i = 0; i < reps; i++) { + DateFormat.format("EEE MMM dd kk:mm:ss zzz yyyy", calendar); + } + } + + public static void main(String[] args) throws Exception { + Runner.main(DateToStringBenchmark.class, args); + } +} diff --git a/benchmarks/regression/DefaultCharsetBenchmark.java b/benchmarks/regression/DefaultCharsetBenchmark.java new file mode 100644 index 0000000..bc7b013 --- /dev/null +++ b/benchmarks/regression/DefaultCharsetBenchmark.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import java.nio.charset.Charset; +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; + +public class DefaultCharsetBenchmark extends SimpleBenchmark { + public void time_defaultCharset(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + Charset.defaultCharset(); + } + } +} diff --git a/benchmarks/regression/DigestBenchmark.java b/benchmarks/regression/DigestBenchmark.java new file mode 100644 index 0000000..7d00fec --- /dev/null +++ b/benchmarks/regression/DigestBenchmark.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; +import com.android.org.bouncycastle.crypto.Digest; + +public class DigestBenchmark extends SimpleBenchmark { + + private static final int DATA_SIZE = 8192; + private static final byte[] DATA = new byte[DATA_SIZE]; + static { + for (int i = 0; i < DATA_SIZE; i++) { + DATA[i] = (byte)i; + } + } + + @Param private Algorithm algorithm; + + public enum Algorithm { MD5, SHA1, SHA256, SHA384, SHA512 }; + + @Param private Implementation implementation; + + public enum Implementation { OPENSSL, BOUNCYCASTLE }; + + private Class<? extends Digest> digestClass; + + @Override protected void setUp() throws Exception { + String className = "com.android.org.bouncycastle.crypto.digests."; + switch (implementation) { + case OPENSSL: + className += ("OpenSSLDigest$" + algorithm); + break; + case BOUNCYCASTLE: + className += (algorithm + "Digest"); + break; + default: + throw new RuntimeException(implementation.toString()); + } + this.digestClass = (Class<? extends Digest>)Class.forName(className); + } + + public void time(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + Digest digest = digestClass.newInstance(); + digest.update(DATA, 0, DATA_SIZE); + digest.doFinal(new byte[digest.getDigestSize()], 0); + } + } +} diff --git a/benchmarks/regression/DnsBenchmark.java b/benchmarks/regression/DnsBenchmark.java new file mode 100644 index 0000000..2a71716 --- /dev/null +++ b/benchmarks/regression/DnsBenchmark.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; +import java.net.InetAddress; +import java.net.UnknownHostException; + +public class DnsBenchmark extends SimpleBenchmark { + public void timeDns(int reps) throws Exception { + String[] hosts = new String[] { + "www.amazon.com", + "z-ecx.images-amazon.com", + "g-ecx.images-amazon.com", + "ecx.images-amazon.com", + "ad.doubleclick.com", + "bpx.a9.com", + "d3dtik4dz1nej0.cloudfront.net", + "uac.advertising.com", + "servedby.advertising.com", + "view.atdmt.com", + "rmd.atdmt.com", + "spe.atdmt.com", + "www.google.com", + "www.cnn.com", + "bad.host.mtv.corp.google.com", + }; + for (int i = 0; i < reps; ++i) { + try { + InetAddress.getByName(hosts[i % hosts.length]); + } catch (UnknownHostException ex) { + } + } + } +} diff --git a/benchmarks/regression/DoPrivilegedBenchmark.java b/benchmarks/regression/DoPrivilegedBenchmark.java new file mode 100644 index 0000000..effb284 --- /dev/null +++ b/benchmarks/regression/DoPrivilegedBenchmark.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; +import java.security.AccessController; +import java.security.PrivilegedAction; + +public class DoPrivilegedBenchmark extends SimpleBenchmark { + public void timeDirect(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + String lineSeparator = System.getProperty("line.separator"); + } + } + + public void timeFastAndSlow(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + String lineSeparator; + if (System.getSecurityManager() == null) { + lineSeparator = System.getProperty("line.separator"); + } else { + lineSeparator = AccessController.doPrivileged(new PrivilegedAction<String>() { + public String run() { + return System.getProperty("line.separator"); + } + }); + } + } + } + + public void timeNewAction(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + String lineSeparator = AccessController.doPrivileged(new PrivilegedAction<String>() { + public String run() { + return System.getProperty("line.separator"); + } + }); + } + } + + public void timeReusedAction(int reps) throws Exception { + final PrivilegedAction<String> action = new ReusableAction("line.separator"); + for (int i = 0; i < reps; ++i) { + String lineSeparator = AccessController.doPrivileged(action); + } + } + + private static final class ReusableAction implements PrivilegedAction<String> { + private final String propertyName; + + public ReusableAction(String propertyName) { + this.propertyName = propertyName; + } + + public String run() { + return System.getProperty(propertyName); + } + } +} diff --git a/benchmarks/regression/DoubleBenchmark.java b/benchmarks/regression/DoubleBenchmark.java new file mode 100644 index 0000000..aa692ac --- /dev/null +++ b/benchmarks/regression/DoubleBenchmark.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +public class DoubleBenchmark extends SimpleBenchmark { + private double d = 1.2; + private long l = 4608083138725491507L; + + public void timeDoubleToLongBits(int reps) { + long result = 123; + for (int rep = 0; rep < reps; ++rep) { + result = Double.doubleToLongBits(d); + } + if (result != l) { + throw new RuntimeException(Long.toString(result)); + } + } + + public void timeDoubleToRawLongBits(int reps) { + long result = 123; + for (int rep = 0; rep < reps; ++rep) { + result = Double.doubleToRawLongBits(d); + } + if (result != l) { + throw new RuntimeException(Long.toString(result)); + } + } + + public void timeLongBitsToDouble(int reps) { + double result = 123.0; + for (int rep = 0; rep < reps; ++rep) { + result = Double.longBitsToDouble(l); + } + if (result != d) { + throw new RuntimeException(Double.toString(result) + " " + Double.doubleToRawLongBits(result)); + } + } +} diff --git a/benchmarks/regression/EqualsHashCodeBenchmark.java b/benchmarks/regression/EqualsHashCodeBenchmark.java new file mode 100644 index 0000000..a15a41a --- /dev/null +++ b/benchmarks/regression/EqualsHashCodeBenchmark.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; +import java.net.URI; +import java.net.URL; + +public final class EqualsHashCodeBenchmark extends SimpleBenchmark { + private enum Type { + URI() { + @Override Object newInstance(String text) throws Exception { + return new URI(text); + } + }, + URL() { + @Override Object newInstance(String text) throws Exception { + return new URL(text); + } + }; + abstract Object newInstance(String text) throws Exception; + } + + @Param Type type; + + Object a1; + Object a2; + Object b1; + Object b2; + + @Override protected void setUp() throws Exception { + a1 = type.newInstance("https://mail.google.com/mail/u/0/?shva=1#inbox"); + a2 = type.newInstance("https://mail.google.com/mail/u/0/?shva=1#inbox"); + b1 = type.newInstance("http://developer.android.com/reference/java/net/URI.html"); + b2 = type.newInstance("http://developer.android.com/reference/java/net/URI.html"); + } + + public void timeEquals(int reps) { + for (int i = 0; i < reps; i+=3) { + a1.equals(b1); + a1.equals(a2); + b1.equals(b2); + } + } + + public void timeHashCode(int reps) { + for (int i = 0; i < reps; i+=2) { + a1.hashCode(); + b1.hashCode(); + } + } +} diff --git a/benchmarks/regression/ExpensiveObjectsBenchmark.java b/benchmarks/regression/ExpensiveObjectsBenchmark.java new file mode 100644 index 0000000..535e298 --- /dev/null +++ b/benchmarks/regression/ExpensiveObjectsBenchmark.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Benchmark; +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; +import java.text.*; +import java.util.*; + +/** + * Benchmarks creation and cloning various expensive objects. + */ +public class ExpensiveObjectsBenchmark extends SimpleBenchmark { + public void timeNewDateFormatTimeInstance(int reps) { + for (int i = 0; i < reps; ++i) { + DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT); + df.format(System.currentTimeMillis()); + } + } + + public void timeClonedDateFormatTimeInstance(int reps) { + DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT); + for (int i = 0; i < reps; ++i) { + ((DateFormat) df.clone()).format(System.currentTimeMillis()); + } + } + + public void timeReusedDateFormatTimeInstance(int reps) { + DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT); + for (int i = 0; i < reps; ++i) { + synchronized (df) { + df.format(System.currentTimeMillis()); + } + } + } + + public void timeNewCollator(int reps) { + for (int i = 0; i < reps; ++i) { + Collator.getInstance(Locale.US); + } + } + + public void timeClonedCollator(int reps) { + Collator c = Collator.getInstance(Locale.US); + for (int i = 0; i < reps; ++i) { + c.clone(); + } + } + + public void timeNewDateFormatSymbols(int reps) { + for (int i = 0; i < reps; ++i) { + new DateFormatSymbols(Locale.US); + } + } + + public void timeClonedDateFormatSymbols(int reps) { + DateFormatSymbols dfs = new DateFormatSymbols(Locale.US); + for (int i = 0; i < reps; ++i) { + dfs.clone(); + } + } + + public void timeNewDecimalFormatSymbols(int reps) { + for (int i = 0; i < reps; ++i) { + new DecimalFormatSymbols(Locale.US); + } + } + + public void timeClonedDecimalFormatSymbols(int reps) { + DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US); + for (int i = 0; i < reps; ++i) { + dfs.clone(); + } + } + + public void timeNewNumberFormat(int reps) { + for (int i = 0; i < reps; ++i) { + NumberFormat.getInstance(Locale.US); + } + } + + public void timeClonedNumberFormat(int reps) { + NumberFormat nf = NumberFormat.getInstance(Locale.US); + for (int i = 0; i < reps; ++i) { + nf.clone(); + } + } + + public void timeNumberFormatTrivialFormatLong(int reps) { + NumberFormat nf = NumberFormat.getInstance(Locale.US); + for (int i = 0; i < reps; ++i) { + nf.format(1024L); + } + } + + public void timeLongToString(int reps) { + for (int i = 0; i < reps; ++i) { + Long.toString(1024L); + } + } + + public void timeNumberFormatTrivialFormatDouble(int reps) { + NumberFormat nf = NumberFormat.getInstance(Locale.US); + for (int i = 0; i < reps; ++i) { + nf.format(1024.0); + } + } + + public void timeNewSimpleDateFormat(int reps) { + for (int i = 0; i < reps; ++i) { + new SimpleDateFormat(); + } + } + + public void timeClonedSimpleDateFormat(int reps) { + SimpleDateFormat sdf = new SimpleDateFormat(); + for (int i = 0; i < reps; ++i) { + sdf.clone(); + } + } + + public void timeNewGregorianCalendar(int reps) { + for (int i = 0; i < reps; ++i) { + new GregorianCalendar(); + } + } + + public void timeClonedGregorianCalendar(int reps) { + GregorianCalendar gc = new GregorianCalendar(); + for (int i = 0; i < reps; ++i) { + gc.clone(); + } + } +} diff --git a/benchmarks/regression/FloatBenchmark.java b/benchmarks/regression/FloatBenchmark.java new file mode 100644 index 0000000..a92bb69 --- /dev/null +++ b/benchmarks/regression/FloatBenchmark.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +public class FloatBenchmark extends SimpleBenchmark { + private float f = 1.2f; + private int i = 1067030938; + + public void timeFloatToIntBits(int reps) { + int result = 123; + for (int rep = 0; rep < reps; ++rep) { + result = Float.floatToIntBits(f); + } + if (result != i) { + throw new RuntimeException(Integer.toString(result)); + } + } + + public void timeFloatToRawIntBits(int reps) { + int result = 123; + for (int rep = 0; rep < reps; ++rep) { + result = Float.floatToRawIntBits(f); + } + if (result != i) { + throw new RuntimeException(Integer.toString(result)); + } + } + + public void timeIntBitsToFloat(int reps) { + float result = 123.0f; + for (int rep = 0; rep < reps; ++rep) { + result = Float.intBitsToFloat(i); + } + if (result != f) { + throw new RuntimeException(Float.toString(result) + " " + Float.floatToRawIntBits(result)); + } + } +} diff --git a/benchmarks/regression/FormatterBenchmark.java b/benchmarks/regression/FormatterBenchmark.java new file mode 100644 index 0000000..0d4cf26 --- /dev/null +++ b/benchmarks/regression/FormatterBenchmark.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; +import java.util.Formatter; +import java.util.Locale; + +/** + * Compares Formatter against hand-written StringBuilder code. + */ +public class FormatterBenchmark extends SimpleBenchmark { + public void timeFormatter_NoFormatting(int reps) { + for (int i = 0; i < reps; i++) { + Formatter f = new Formatter(); + f.format("this is a reasonably short string that doesn't actually need any formatting"); + } + } + + public void timeStringBuilder_NoFormatting(int reps) { + for (int i = 0; i < reps; i++) { + StringBuilder sb = new StringBuilder(); + sb.append("this is a reasonably short string that doesn't actually need any formatting"); + } + } + + public void timeFormatter_OneInt(int reps) { + Integer value = Integer.valueOf(1024); // We're not trying to benchmark boxing here. + for (int i = 0; i < reps; i++) { + Formatter f = new Formatter(); + f.format("this is a reasonably short string that has an int %d in it", value); + } + } + + public void timeFormatter_OneIntArabic(int reps) { + Locale arabic = new Locale("ar"); + Integer value = Integer.valueOf(1024); // We're not trying to benchmark boxing here. + for (int i = 0; i < reps; i++) { + Formatter f = new Formatter(); + f.format(arabic, "this is a reasonably short string that has an int %d in it", value); + } + } + + public void timeStringBuilder_OneInt(int reps) { + for (int i = 0; i < reps; i++) { + StringBuilder sb = new StringBuilder(); + sb.append("this is a reasonably short string that has an int "); + sb.append(1024); + sb.append(" in it"); + } + } + + public void timeFormatter_OneHexInt(int reps) { + Integer value = Integer.valueOf(1024); // We're not trying to benchmark boxing here. + for (int i = 0; i < reps; i++) { + Formatter f = new Formatter(); + f.format("this is a reasonably short string that has an int %x in it", value); + } + } + + public void timeStringBuilder_OneHexInt(int reps) { + for (int i = 0; i < reps; i++) { + StringBuilder sb = new StringBuilder(); + sb.append("this is a reasonably short string that has an int "); + sb.append(Integer.toHexString(1024)); + sb.append(" in it"); + } + } + + public void timeFormatter_OneFloat(int reps) { + Float value = Float.valueOf(10.24f); // We're not trying to benchmark boxing here. + for (int i = 0; i < reps; i++) { + Formatter f = new Formatter(); + f.format("this is a reasonably short string that has a float %f in it", value); + } + } + + public void timeFormatter_OneFloat_dot2f(int reps) { + Float value = Float.valueOf(10.24f); // We're not trying to benchmark boxing here. + for (int i = 0; i < reps; i++) { + Formatter f = new Formatter(); + f.format("this is a reasonably short string that has a float %.2f in it", value); + } + } + + public void timeFormatter_TwoFloats(int reps) { + Float value = Float.valueOf(10.24f); // We're not trying to benchmark boxing here. + for (int i = 0; i < reps; i++) { + Formatter f = new Formatter(); + f.format("this is a reasonably short string that has two floats %f and %f in it", value, value); + } + } + + public void timeStringBuilder_OneFloat(int reps) { + for (int i = 0; i < reps; i++) { + StringBuilder sb = new StringBuilder(); + sb.append("this is a reasonably short string that has a float "); + sb.append(10.24f); + sb.append(" in it"); + } + } + + public void timeFormatter_OneString(int reps) { + for (int i = 0; i < reps; i++) { + Formatter f = new Formatter(); + f.format("this is a reasonably short string that has a string %s in it", "hello"); + } + } + + public void timeStringBuilder_OneString(int reps) { + for (int i = 0; i < reps; i++) { + StringBuilder sb = new StringBuilder(); + sb.append("this is a reasonably short string that has a string "); + sb.append("hello"); + sb.append(" in it"); + } + } +} diff --git a/benchmarks/regression/HostnameVerifierBenchmark.java b/benchmarks/regression/HostnameVerifierBenchmark.java new file mode 100644 index 0000000..e9218c4 --- /dev/null +++ b/benchmarks/regression/HostnameVerifierBenchmark.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; +import java.io.ByteArrayInputStream; +import java.net.URL; +import java.security.Principal; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSessionContext; + +/** + * This benchmark makes a real HTTP connection to a handful of hosts and + * captures the served certificates as a byte array. It then verifies each + * certificate in the benchmark loop, being careful to convert from the + * byte[] to the certificate each time. Otherwise the certificate class + * caches previous results which skews the results of the benchmark: In practice + * each certificate instance is verified once and then released. + */ +public final class HostnameVerifierBenchmark extends SimpleBenchmark { + + @Param({"android.clients.google.com", + "m.google.com", + "www.google.com", + "www.amazon.com", + "www.ubs.com"}) String host; + + private String hostname; + private HostnameVerifier hostnameVerifier; + private byte[][] encodedCertificates; + + @Override protected void setUp() throws Exception { + URL url = new URL("https", host, "/"); + hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier(); + HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + connection.setHostnameVerifier(new HostnameVerifier() { + public boolean verify(String hostname, SSLSession sslSession) { + try { + encodedCertificates = certificatesToBytes(sslSession.getPeerCertificates()); + } catch (Exception e) { + throw new RuntimeException(e); + } + HostnameVerifierBenchmark.this.hostname = hostname; + return true; + } + }); + connection.getInputStream(); + connection.disconnect(); + } + + public void timeVerify(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + final Certificate[] certificates = bytesToCertificates(encodedCertificates); + FakeSSLSession sslSession = new FakeSSLSession() { + @Override public Certificate[] getPeerCertificates() { + return certificates; + } + }; + hostnameVerifier.verify(hostname, sslSession); + } + } + + private byte[][] certificatesToBytes(Certificate[] certificates) throws Exception { + byte[][] result = new byte[certificates.length][]; + for (int i = 0, certificatesLength = certificates.length; i < certificatesLength; i++) { + result[i] = certificates[i].getEncoded(); + } + return result; + } + + private Certificate[] bytesToCertificates(byte[][] encodedCertificates) throws Exception { + CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); + Certificate[] result = new Certificate[encodedCertificates.length]; + for (int i = 0; i < encodedCertificates.length; i++) { + result[i] = certificateFactory.generateCertificate( + new ByteArrayInputStream(encodedCertificates[i])); + } + return result; + } + + private static class FakeSSLSession implements SSLSession { + public int getApplicationBufferSize() { + throw new UnsupportedOperationException(); + } + public String getCipherSuite() { + throw new UnsupportedOperationException(); + } + public long getCreationTime() { + throw new UnsupportedOperationException(); + } + public byte[] getId() { + throw new UnsupportedOperationException(); + } + public long getLastAccessedTime() { + throw new UnsupportedOperationException(); + } + public Certificate[] getLocalCertificates() { + throw new UnsupportedOperationException(); + } + public Principal getLocalPrincipal() { + throw new UnsupportedOperationException(); + } + public int getPacketBufferSize() { + throw new UnsupportedOperationException(); + } + public javax.security.cert.X509Certificate[] getPeerCertificateChain() { + throw new UnsupportedOperationException(); + } + public Certificate[] getPeerCertificates() { + throw new UnsupportedOperationException(); + } + public String getPeerHost() { + throw new UnsupportedOperationException(); + } + public int getPeerPort() { + throw new UnsupportedOperationException(); + } + public Principal getPeerPrincipal() { + throw new UnsupportedOperationException(); + } + public String getProtocol() { + throw new UnsupportedOperationException(); + } + public SSLSessionContext getSessionContext() { + throw new UnsupportedOperationException(); + } + public Object getValue(String name) { + throw new UnsupportedOperationException(); + } + public String[] getValueNames() { + throw new UnsupportedOperationException(); + } + public void invalidate() { + throw new UnsupportedOperationException(); + } + public boolean isValid() { + throw new UnsupportedOperationException(); + } + public void putValue(String name, Object value) { + throw new UnsupportedOperationException(); + } + public void removeValue(String name) { + throw new UnsupportedOperationException(); + } + } + + public static void main(String[] args) { + Runner.main(HostnameVerifierBenchmark.class, args); + } +} diff --git a/benchmarks/regression/IntConstantDivisionBenchmark.java b/benchmarks/regression/IntConstantDivisionBenchmark.java new file mode 100644 index 0000000..498b783 --- /dev/null +++ b/benchmarks/regression/IntConstantDivisionBenchmark.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +public class IntConstantDivisionBenchmark extends SimpleBenchmark { + public int timeDivideIntByConstant2(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result /= 2; + } + return result; + } + public int timeDivideIntByConstant8(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result /= 8; + } + return result; + } + public int timeDivideIntByConstant10(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result /= 10; + } + return result; + } + public int timeDivideIntByConstant100(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result /= 100; + } + return result; + } + public int timeDivideIntByConstant100_HandOptimized(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result = (int) ((0x51eb851fL * result) >>> 37); + } + return result; + } + public int timeDivideIntByConstant2048(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result /= 2048; + } + return result; + } + public int timeDivideIntByVariable2(int reps) { + int result = 1; + int factor = 2; + for (int i = 0; i < reps; ++i) { + result /= factor; + } + return result; + } + public int timeDivideIntByVariable10(int reps) { + int result = 1; + int factor = 10; + for (int i = 0; i < reps; ++i) { + result /= factor; + } + return result; + } +} diff --git a/benchmarks/regression/IntConstantMultiplicationBenchmark.java b/benchmarks/regression/IntConstantMultiplicationBenchmark.java new file mode 100644 index 0000000..ca1349c --- /dev/null +++ b/benchmarks/regression/IntConstantMultiplicationBenchmark.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +public class IntConstantMultiplicationBenchmark extends SimpleBenchmark { + public int timeMultiplyIntByConstant6(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result *= 6; + } + return result; + } + public int timeMultiplyIntByConstant7(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result *= 7; + } + return result; + } + public int timeMultiplyIntByConstant8(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result *= 8; + } + return result; + } + public int timeMultiplyIntByConstant8_Shift(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result <<= 3; + } + return result; + } + public int timeMultiplyIntByConstant10(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result *= 10; + } + return result; + } + public int timeMultiplyIntByConstant10_Shift(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result = (result + (result << 2)) << 1; + } + return result; + } + public int timeMultiplyIntByConstant2047(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result *= 2047; + } + return result; + } + public int timeMultiplyIntByConstant2048(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result *= 2048; + } + return result; + } + public int timeMultiplyIntByConstant2049(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result *= 2049; + } + return result; + } + public int timeMultiplyIntByVariable10(int reps) { + int result = 1; + int factor = 10; + for (int i = 0; i < reps; ++i) { + result *= factor; + } + return result; + } + public int timeMultiplyIntByVariable8(int reps) { + int result = 1; + int factor = 8; + for (int i = 0; i < reps; ++i) { + result *= factor; + } + return result; + } +} diff --git a/benchmarks/regression/IntConstantRemainderBenchmark.java b/benchmarks/regression/IntConstantRemainderBenchmark.java new file mode 100644 index 0000000..6174721 --- /dev/null +++ b/benchmarks/regression/IntConstantRemainderBenchmark.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +public class IntConstantRemainderBenchmark extends SimpleBenchmark { + public int timeRemainderIntByConstant2(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result %= 2; + } + return result; + } + public int timeRemainderIntByConstant8(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result %= 8; + } + return result; + } +/* + public int timeRemainderIntByConstant10(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result %= 10; + } + return result; + } + public int timeRemainderIntByConstant100(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result %= 100; + } + return result; + } +*/ + public int timeRemainderIntByConstant2048(int reps) { + int result = 1; + for (int i = 0; i < reps; ++i) { + result %= 2048; + } + return result; + } + public int timeRemainderIntByVariable2(int reps) { + int result = 1; + int factor = 2; + for (int i = 0; i < reps; ++i) { + result %= factor; + } + return result; + } +/* + public int timeRemainderIntByVariable10(int reps) { + int result = 1; + int factor = 10; + for (int i = 0; i < reps; ++i) { + result %= factor; + } + return result; + } +*/ +} diff --git a/benchmarks/regression/IntegerBenchmark.java b/benchmarks/regression/IntegerBenchmark.java new file mode 100644 index 0000000..601bb5d --- /dev/null +++ b/benchmarks/regression/IntegerBenchmark.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; + +public class IntegerBenchmark extends SimpleBenchmark { + public int timeLongSignumBranch(int reps) { + int t = 0; + for (int i = 0; i < reps; ++i) { + t += signum1(-i); + t += signum1(0); + t += signum1(i); + } + return t; + } + + public int timeLongSignumBranchFree(int reps) { + int t = 0; + for (int i = 0; i < reps; ++i) { + t += signum2(-i); + t += signum2(0); + t += signum2(i); + } + return t; + } + + private static int signum1(long v) { + return v < 0 ? -1 : (v == 0 ? 0 : 1); + } + + private static int signum2(long v) { + return ((int)(v >> 63)) | (int) (-v >>> 63); // Hacker's delight 2-7 + } + + public int timeLongBitCount_BitSet(int reps) { + int t = 0; + for (int i = 0; i < reps; ++i) { + t += pop((long) i); + } + return t; + } + + private static int pop(long l) { + int count = popX(l & 0xffffffffL); + count += popX(l >>> 32); + return count; + } + + private static int popX(long x) { + // BEGIN android-note + // delegate to Integer.bitCount(i); consider using native code + // END android-note + x = x - ((x >>> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >>> 2) & 0x33333333); + x = (x + (x >>> 4)) & 0x0f0f0f0f; + x = x + (x >>> 8); + x = x + (x >>> 16); + return (int) x & 0x0000003f; + } + + public int timeLongBitCount_2Int(int reps) { + int t = 0; + for (int i = 0; i < reps; ++i) { + t += pop2((long) i); + } + return t; + } + + private static int pop2(long l) { + int count = Integer.bitCount((int) (l & 0xffffffffL)); + count += Integer.bitCount((int) (l >>> 32)); + return count; + } + + public int timeLongBitCount_Long(int reps) { + int t = 0; + for (int i = 0; i < reps; ++i) { + t += Long.bitCount((long) i); + } + return t; + } + + /** + * Table for Seal's algorithm for Number of Trailing Zeros. Hacker's Delight + * online, Figure 5-18 (http://www.hackersdelight.org/revisions.pdf) + * The entries whose value is -1 are never referenced. + */ + private static final byte[] NTZ_TABLE = { + 32, 0, 1, 12, 2, 6, -1, 13, 3, -1, 7, -1, -1, -1, -1, 14, + 10, 4, -1, -1, 8, -1, -1, 25, -1, -1, -1, -1, -1, 21, 27, 15, + 31, 11, 5, -1, -1, -1, -1, -1, 9, -1, -1, 24, -1, -1, 20, 26, + 30, -1, -1, -1, -1, 23, -1, 19, 29, -1, 22, 18, 28, 17, 16, -1 + }; + + private static int numberOfTrailingZerosHD(int i) { + // Seal's algorithm - Hacker's Delight 5-18 + i &= -i; + i = (i << 4) + i; // x *= 17 + i = (i << 6) + i; // x *= 65 + i = (i << 16) - i; // x *= 65535 + return NTZ_TABLE[i >>> 26]; + } + + private static int numberOfTrailingZerosOL(int i) { + return NTZ_TABLE[((i & -i) * 0x0450FBAF) >>> 26]; + } + + public int timeNumberOfTrailingZerosHD(int reps) { + int t = 0; + for (int i = 0; i < reps; ++i) { + t += numberOfTrailingZerosHD(i); + } + return t; + } + + public int timeNumberOfTrailingZerosOL(int reps) { + int t = 0; + for (int i = 0; i < reps; ++i) { + t += numberOfTrailingZerosOL(i); + } + return t; + } +} diff --git a/benchmarks/regression/IntegralToStringBenchmark.java b/benchmarks/regression/IntegralToStringBenchmark.java new file mode 100644 index 0000000..cab9e98 --- /dev/null +++ b/benchmarks/regression/IntegralToStringBenchmark.java @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +public class IntegralToStringBenchmark extends SimpleBenchmark { + + private static final int SMALL = 12; + private static final int MEDIUM = 12345; + private static final int LARGE = 12345678; + + public void time_IntegerToString_small(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toString(SMALL); + } + } + + public void time_IntegerToString_medium(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toString(MEDIUM); + } + } + + public void time_IntegerToString_large(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toString(LARGE); + } + } + + public void time_IntegerToString2_small(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toString(SMALL, 2); + } + } + + public void time_IntegerToString2_medium(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toString(MEDIUM, 2); + } + } + + public void time_IntegerToString2_large(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toString(LARGE, 2); + } + } + + public void time_IntegerToString10_small(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toString(SMALL, 10); + } + } + + public void time_IntegerToString10_medium(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toString(MEDIUM, 10); + } + } + + public void time_IntegerToString10_large(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toString(LARGE, 10); + } + } + + public void time_IntegerToString16_small(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toString(SMALL, 16); + } + } + + public void time_IntegerToString16_medium(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toString(MEDIUM, 16); + } + } + + public void time_IntegerToString16_large(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toString(LARGE, 16); + } + } + + public void time_IntegerToBinaryString_small(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toBinaryString(SMALL); + } + } + + public void time_IntegerToBinaryString_medium(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toBinaryString(MEDIUM); + } + } + + public void time_IntegerToBinaryString_large(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toBinaryString(LARGE); + } + } + + public void time_IntegerToHexString_small(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toHexString(SMALL); + } + } + + public void time_IntegerToHexString_medium(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toHexString(MEDIUM); + } + } + + public void time_IntegerToHexString_large(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Integer.toHexString(LARGE); + } + } + + public void time_StringBuilder_small(int reps) { + for (int rep = 0; rep < reps; ++rep) { + new StringBuilder().append(SMALL); + } + } + + public void time_StringBuilder_medium(int reps) { + for (int rep = 0; rep < reps; ++rep) { + new StringBuilder().append(MEDIUM); + } + } + + public void time_StringBuilder_large(int reps) { + for (int rep = 0; rep < reps; ++rep) { + new StringBuilder().append(LARGE); + } + } + + public void time_Formatter_small(int reps) { + for (int rep = 0; rep < reps; ++rep) { + String.format("%d", SMALL); + } + } + + public void time_Formatter_medium(int reps) { + for (int rep = 0; rep < reps; ++rep) { + String.format("%d", MEDIUM); + } + } + + public void time_Formatter_large(int reps) { + for (int rep = 0; rep < reps; ++rep) { + String.format("%d", LARGE); + } + } +} diff --git a/benchmarks/regression/JarFileBenchmark.java b/benchmarks/regression/JarFileBenchmark.java new file mode 100644 index 0000000..626ca21 --- /dev/null +++ b/benchmarks/regression/JarFileBenchmark.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import java.io.File; +import java.util.jar.*; +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; + +public class JarFileBenchmark extends SimpleBenchmark { + @Param({ + "/system/framework/bouncycastle.jar", + "/system/framework/core.jar", + "/system/framework/framework.jar" + }) + private String filename; + + public void time(int reps) throws Exception { + File f = new File(filename); + for (int i = 0; i < reps; ++i) { + JarFile jf = new JarFile(f); + Manifest m = jf.getManifest(); + jf.close(); + } + } +} diff --git a/benchmarks/regression/KeyPairGeneratorBenchmark.java b/benchmarks/regression/KeyPairGeneratorBenchmark.java new file mode 100644 index 0000000..762c935 --- /dev/null +++ b/benchmarks/regression/KeyPairGeneratorBenchmark.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2012 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.KeyPairGenerator; +import java.security.SecureRandom; +import java.util.HashMap; +import java.util.Map; + +public class KeyPairGeneratorBenchmark extends SimpleBenchmark { + @Param private Algorithm algorithm; + + public enum Algorithm { + RSA, + DSA, + }; + + @Param private Implementation implementation; + + public enum Implementation { OpenSSL, BouncyCastle }; + + private String generatorAlgorithm; + private KeyPairGenerator generator; + private SecureRandom random; + + @Override protected void setUp() throws Exception { + this.generatorAlgorithm = algorithm.toString(); + + final String provider; + if (implementation == Implementation.BouncyCastle) { + provider = "BC"; + } else { + provider = "AndroidOpenSSL"; + } + + this.generator = KeyPairGenerator.getInstance(generatorAlgorithm, provider); + this.random = SecureRandom.getInstance("SHA1PRNG"); + this.generator.initialize(1024); + } + + public void time(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + KeyPair keyPair = generator.generateKeyPair(); + } + } +} diff --git a/benchmarks/regression/LoopingBackwardsBenchmark.java b/benchmarks/regression/LoopingBackwardsBenchmark.java new file mode 100644 index 0000000..054eff9 --- /dev/null +++ b/benchmarks/regression/LoopingBackwardsBenchmark.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +/** + * Testing the old canard that looping backwards is faster. + * + * @author Kevin Bourrillion + */ +public class LoopingBackwardsBenchmark extends SimpleBenchmark { + @Param({"2", "20", "2000", "20000000"}) int max; + + public int timeForwards(int reps) { + int dummy = 0; + for (int i = 0; i < reps; i++) { + for (int j = 0; j < max; j++) { + dummy += j; + } + } + return dummy; + } + + public int timeBackwards(int reps) { + int dummy = 0; + for (int i = 0; i < reps; i++) { + for (int j = max - 1; j >= 0; j--) { + dummy += j; + } + } + return dummy; + } +} diff --git a/benchmarks/regression/MathBenchmark.java b/benchmarks/regression/MathBenchmark.java new file mode 100644 index 0000000..25a871d --- /dev/null +++ b/benchmarks/regression/MathBenchmark.java @@ -0,0 +1,368 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +/** + * Many of these tests are bogus in that the cost will vary wildly depending on inputs. + * For _my_ current purposes, that's okay. But beware! + */ +public class MathBenchmark extends SimpleBenchmark { + private final double d = 1.2; + private final float f = 1.2f; + private final int i = 1; + private final long l = 1L; + + public void timeAbsD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.abs(d); + } + } + + public void timeAbsF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.abs(f); + } + } + + public void timeAbsI(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.abs(i); + } + } + + public void timeAbsL(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.abs(l); + } + } + + public void timeAcos(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.acos(d); + } + } + + public void timeAsin(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.asin(d); + } + } + + public void timeAtan(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.atan(d); + } + } + + public void timeAtan2(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.atan2(3, 4); + } + } + + public void timeCbrt(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.cbrt(d); + } + } + + public void timeCeil(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.ceil(d); + } + } + + public void timeCopySignD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.copySign(d, d); + } + } + + public void timeCopySignF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.copySign(f, f); + } + } + + public void timeCopySignD_strict(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.copySign(d, d); + } + } + + public void timeCopySignF_strict(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.copySign(f, f); + } + } + + public void timeCos(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.cos(d); + } + } + + public void timeCosh(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.cosh(d); + } + } + + public void timeExp(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.exp(d); + } + } + + public void timeExpm1(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.expm1(d); + } + } + + public void timeFloor(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.floor(d); + } + } + + public void timeGetExponentD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.getExponent(d); + } + } + + public void timeGetExponentF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.getExponent(f); + } + } + + public void timeHypot(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.hypot(d, d); + } + } + + public void timeIEEEremainder(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.IEEEremainder(d, d); + } + } + + public void timeLog(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.log(d); + } + } + + public void timeLog10(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.log10(d); + } + } + + public void timeLog1p(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.log1p(d); + } + } + + public void timeMaxD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.max(d, d); + } + } + + public void timeMaxF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.max(f, f); + } + } + + public void timeMaxI(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.max(i, i); + } + } + + public void timeMaxL(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.max(l, l); + } + } + + public void timeMinD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.min(d, d); + } + } + + public void timeMinF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.min(f, f); + } + } + + public void timeMinI(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.min(i, i); + } + } + + public void timeMinL(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.min(l, l); + } + } + + public void timeNextAfterD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.nextAfter(d, d); + } + } + + public void timeNextAfterF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.nextAfter(f, f); + } + } + + public void timeNextUpD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.nextUp(d); + } + } + + public void timeNextUpF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.nextUp(f); + } + } + + public void timePow(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.pow(d, d); + } + } + + public void timeRandom(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.random(); + } + } + + public void timeRint(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.rint(d); + } + } + + public void timeRoundD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.round(d); + } + } + + public void timeRoundF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.round(f); + } + } + + public void timeScalbD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.scalb(d, 5); + } + } + + public void timeScalbF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.scalb(f, 5); + } + } + + public void timeSignumD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.signum(d); + } + } + + public void timeSignumF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.signum(f); + } + } + + public void timeSin(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.sin(d); + } + } + + public void timeSinh(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.sinh(d); + } + } + + public void timeSqrt(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.sqrt(d); + } + } + + public void timeTan(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.tan(d); + } + } + + public void timeTanh(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.tanh(d); + } + } + + public void timeToDegrees(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.toDegrees(d); + } + } + + public void timeToRadians(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.toRadians(d); + } + } + + public void timeUlpD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.ulp(d); + } + } + + public void timeUlpF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Math.ulp(f); + } + } +} diff --git a/benchmarks/regression/MessageDigestBenchmark.java b/benchmarks/regression/MessageDigestBenchmark.java new file mode 100644 index 0000000..c9d8074 --- /dev/null +++ b/benchmarks/regression/MessageDigestBenchmark.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; +import java.security.MessageDigest; + +public class MessageDigestBenchmark extends SimpleBenchmark { + + private static final int DATA_SIZE = 8192; + private static final byte[] DATA = new byte[DATA_SIZE]; + static { + for (int i = 0; i < DATA_SIZE; i++) { + DATA[i] = (byte)i; + } + } + + @Param private Algorithm algorithm; + + public enum Algorithm { MD5, SHA1, SHA256, SHA384, SHA512 }; + + @Param private Provider provider; + + public enum Provider { AndroidOpenSSL, BC }; + + public void time(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + MessageDigest digest = MessageDigest.getInstance(algorithm.toString(), + provider.toString()); + digest.update(DATA, 0, DATA_SIZE); + digest.digest(); + } + } +} diff --git a/benchmarks/regression/MutableIntBenchmark.java b/benchmarks/regression/MutableIntBenchmark.java new file mode 100644 index 0000000..ee4f2d9 --- /dev/null +++ b/benchmarks/regression/MutableIntBenchmark.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; +import java.util.concurrent.atomic.AtomicInteger; + +public final class MutableIntBenchmark extends SimpleBenchmark { + + enum Kind { + ARRAY() { + int[] value = new int[1]; + + @Override void timeCreate(int reps) { + for (int i = 0; i < reps; i++) { + value = new int[] { 5 }; + } + } + @Override void timeIncrement(int reps) { + for (int i = 0; i < reps; i++) { + value[0]++; + } + } + @Override int timeGet(int reps) { + int sum = 0; + for (int i = 0; i < reps; i++) { + sum += value[0]; + } + return sum; + } + }, + ATOMIC() { + AtomicInteger value = new AtomicInteger(); + + @Override void timeCreate(int reps) { + for (int i = 0; i < reps; i++) { + value = new AtomicInteger(5); + } + } + @Override void timeIncrement(int reps) { + for (int i = 0; i < reps; i++) { + value.incrementAndGet(); + } + } + @Override int timeGet(int reps) { + int sum = 0; + for (int i = 0; i < reps; i++) { + sum += value.intValue(); + } + return sum; + } + }; + + abstract void timeCreate(int reps); + abstract void timeIncrement(int reps); + abstract int timeGet(int reps); + } + + @Param Kind kind; + + public void timeCreate(int reps) { + kind.timeCreate(reps); + } + + public void timeIncrement(int reps) { + kind.timeIncrement(reps); + } + + public void timeGet(int reps) { + kind.timeGet(reps); + } + + public static void main(String[] args) { + Runner.main(MutableIntBenchmark.class, args); + } +} diff --git a/benchmarks/regression/NativeMethodBenchmark.java b/benchmarks/regression/NativeMethodBenchmark.java new file mode 100644 index 0000000..2e482ef --- /dev/null +++ b/benchmarks/regression/NativeMethodBenchmark.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.SimpleBenchmark; +import org.apache.harmony.dalvik.NativeTestTarget; + +public class NativeMethodBenchmark extends SimpleBenchmark { + public void time_emptyJniStaticSynchronizedMethod0(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + NativeTestTarget.emptyJniStaticSynchronizedMethod0(); + } + } + + public void time_emptyJniSynchronizedMethod0(int reps) throws Exception { + NativeTestTarget n = new NativeTestTarget(); + for (int i = 0; i < reps; ++i) { + n.emptyJniSynchronizedMethod0(); + } + } + + public void time_emptyJniStaticMethod0(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + NativeTestTarget.emptyJniStaticMethod0(); + } + } + + public void time_emptyJniMethod0(int reps) throws Exception { + NativeTestTarget n = new NativeTestTarget(); + for (int i = 0; i < reps; ++i) { + n.emptyJniMethod0(); + } + } + + public void time_emptyJniStaticMethod6(int reps) throws Exception { + int a = -1; + int b = 0; + for (int i = 0; i < reps; ++i) { + NativeTestTarget.emptyJniStaticMethod6(a, b, 1, 2, 3, i); + } + } + + public void time_emptyJniMethod6(int reps) throws Exception { + int a = -1; + int b = 0; + NativeTestTarget n = new NativeTestTarget(); + for (int i = 0; i < reps; ++i) { + n.emptyJniMethod6(a, b, 1, 2, 3, i); + } + } + + public void time_emptyJniStaticMethod6L(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + NativeTestTarget.emptyJniStaticMethod6L(null, null, null, null, null, null); + } + } + + public void time_emptyJniMethod6L(int reps) throws Exception { + NativeTestTarget n = new NativeTestTarget(); + for (int i = 0; i < reps; ++i) { + n.emptyJniMethod6L(null, null, null, null, null, null); + } + } + +} diff --git a/benchmarks/regression/ParseBenchmark.java b/benchmarks/regression/ParseBenchmark.java new file mode 100644 index 0000000..b44b429 --- /dev/null +++ b/benchmarks/regression/ParseBenchmark.java @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.SAXParserFactory; +import org.json.JSONArray; +import org.json.JSONObject; +import org.xml.sax.InputSource; +import org.xml.sax.helpers.DefaultHandler; +import org.xmlpull.v1.XmlPullParser; + +/** + * Measure throughput of various parsers. + * + * <p>This benchmark requires that ParseBenchmarkData.zip is on the classpath. + * That file contains Twitter feed data, which is representative of what + * applications will be parsing. + */ +public final class ParseBenchmark extends SimpleBenchmark { + + @Param Document document; + @Param Api api; + + private enum Document { + TWEETS, + READER_SHORT, + READER_LONG + } + + private enum Api { + ANDROID_STREAM("json") { + @Override Parser newParser() { + return new AndroidStreamParser(); + } + }, + ORG_JSON("json") { + @Override Parser newParser() { + return new OrgJsonParser(); + } + }, + XML_PULL("xml") { + @Override Parser newParser() { + return new GeneralXmlPullParser(); + } + }, + XML_DOM("xml") { + @Override Parser newParser() { + return new XmlDomParser(); + } + }, + XML_SAX("xml") { + @Override Parser newParser() { + return new XmlSaxParser(); + } + }; + + final String extension; + + private Api(String extension) { + this.extension = extension; + } + + abstract Parser newParser(); + } + + private String text; + private Parser parser; + + @Override protected void setUp() throws Exception { + text = resourceToString("/" + document.name() + "." + api.extension); + parser = api.newParser(); + } + + public void timeParse(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + parser.parse(text); + } + } + + public static void main(String... args) throws Exception { + Runner.main(ParseBenchmark.class, args); + } + + private static String resourceToString(String path) throws Exception { + InputStream in = ParseBenchmark.class.getResourceAsStream(path); + if (in == null) { + throw new IllegalArgumentException("No such file: " + path); + } + + Reader reader = new InputStreamReader(in, "UTF-8"); + char[] buffer = new char[8192]; + StringWriter writer = new StringWriter(); + int count; + while ((count = reader.read(buffer)) != -1) { + writer.write(buffer, 0, count); + } + reader.close(); + return writer.toString(); + } + + interface Parser { + void parse(String data) throws Exception; + } + + private static class AndroidStreamParser implements Parser { + @Override public void parse(String data) throws Exception { + android.util.JsonReader jsonReader + = new android.util.JsonReader(new StringReader(data)); + readToken(jsonReader); + jsonReader.close(); + } + + public void readObject(android.util.JsonReader reader) throws IOException { + reader.beginObject(); + while (reader.hasNext()) { + reader.nextName(); + readToken(reader); + } + reader.endObject(); + } + + public void readArray(android.util.JsonReader reader) throws IOException { + reader.beginArray(); + while (reader.hasNext()) { + readToken(reader); + } + reader.endArray(); + } + + private void readToken(android.util.JsonReader reader) throws IOException { + switch (reader.peek()) { + case BEGIN_ARRAY: + readArray(reader); + break; + case BEGIN_OBJECT: + readObject(reader); + break; + case BOOLEAN: + reader.nextBoolean(); + break; + case NULL: + reader.nextNull(); + break; + case NUMBER: + reader.nextLong(); + break; + case STRING: + reader.nextString(); + break; + default: + throw new IllegalArgumentException("Unexpected token" + reader.peek()); + } + } + } + + private static class OrgJsonParser implements Parser { + @Override public void parse(String data) throws Exception { + if (data.startsWith("[")) { + new JSONArray(data); + } else if (data.startsWith("{")) { + new JSONObject(data); + } else { + throw new IllegalArgumentException(); + } + } + } + + private static class GeneralXmlPullParser implements Parser { + @Override public void parse(String data) throws Exception { + XmlPullParser xmlParser = android.util.Xml.newPullParser(); + xmlParser.setInput(new StringReader(data)); + xmlParser.nextTag(); + while (xmlParser.next() != XmlPullParser.END_DOCUMENT) { + xmlParser.getName(); + xmlParser.getText(); + } + } + } + + private static class XmlDomParser implements Parser { + @Override public void parse(String data) throws Exception { + DocumentBuilderFactory.newInstance().newDocumentBuilder() + .parse(new InputSource(new StringReader(data))); + } + } + + private static class XmlSaxParser implements Parser { + @Override public void parse(String data) throws Exception { + SAXParserFactory.newInstance().newSAXParser().parse( + new InputSource(new StringReader(data)), new DefaultHandler()); + } + } +} diff --git a/benchmarks/regression/ParseBenchmarkData.zip b/benchmarks/regression/ParseBenchmarkData.zip Binary files differnew file mode 100644 index 0000000..7838e8a --- /dev/null +++ b/benchmarks/regression/ParseBenchmarkData.zip diff --git a/benchmarks/regression/PriorityQueueBenchmark.java b/benchmarks/regression/PriorityQueueBenchmark.java new file mode 100644 index 0000000..2fe661b --- /dev/null +++ b/benchmarks/regression/PriorityQueueBenchmark.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.PriorityQueue; +import java.util.Random; + +public class PriorityQueueBenchmark extends SimpleBenchmark { + @Param({"100", "1000", "10000"}) private int queueSize; + @Param({"0", "25", "50", "75", "100"}) private int hitRate; + + private PriorityQueue<Integer> pq; + private PriorityQueue<Integer> usepq; + private List<Integer> seekElements; + private Random random = new Random(189279387L); + + @Override protected void setUp() throws Exception { + pq = new PriorityQueue<Integer>(); + usepq = new PriorityQueue<Integer>(); + seekElements = new ArrayList<Integer>(); + List<Integer> allElements = new ArrayList<Integer>(); + int numShared = (int)(queueSize * ((double)hitRate / 100)); + // the total number of elements we require to engineer a hit rate of hitRate% + int totalElements = 2 * queueSize - numShared; + for (int i = 0; i < totalElements; i++) { + allElements.add(i); + } + // shuffle these elements so that we get a reasonable distribution of missed elements + Collections.shuffle(allElements, random); + // add shared elements + for (int i = 0; i < numShared; i++) { + pq.add(allElements.get(i)); + seekElements.add(allElements.get(i)); + } + // add priority queue only elements (these won't be touched) + for (int i = numShared; i < queueSize; i++) { + pq.add(allElements.get(i)); + } + // add non-priority queue elements (these will be misses) + for (int i = queueSize; i < totalElements; i++) { + seekElements.add(allElements.get(i)); + } + usepq = new PriorityQueue<Integer>(pq); + // shuffle again so that elements are accessed in a different pattern than they were + // inserted + Collections.shuffle(seekElements, random); + } + + public boolean timeRemove(int reps) { + boolean dummy = false; + int elementsSize = seekElements.size(); + // At most allow the queue to empty 10%. + int resizingThreshold = queueSize / 10; + for (int i = 0; i < reps; i++) { + // Reset queue every so often. This will be called more often for smaller + // queueSizes, but since a copy is linear, it will also cost proportionally + // less, and hopefully it will approximately balance out. + if (i % resizingThreshold == 0) { + usepq = new PriorityQueue<Integer>(pq); + } + dummy = usepq.remove(seekElements.get(i % elementsSize)); + } + return dummy; + } +} diff --git a/benchmarks/regression/PropertyAccessBenchmark.java b/benchmarks/regression/PropertyAccessBenchmark.java new file mode 100644 index 0000000..cabd6ed --- /dev/null +++ b/benchmarks/regression/PropertyAccessBenchmark.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.SimpleBenchmark; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +public final class PropertyAccessBenchmark extends SimpleBenchmark { + private View view = new View(); + private Method setX; + private GeneratedProperty generatedSetter = new GeneratedSetter(); + private GeneratedProperty generatedField = new GeneratedField(); + private Field x; + private Object[] argsBox = new Object[1]; + + @Override protected void setUp() throws Exception { + setX = View.class.getDeclaredMethod("setX", float.class); + x = View.class.getDeclaredField("x"); + } + + public void timeDirectSetter(int reps) { + for (int i = 0; i < reps; i++) { + view.setX(0.1f); + } + } + + public void timeDirectFieldSet(int reps) { + for (int i = 0; i < reps; i++) { + view.x = 0.1f; + } + } + + public void timeDirectSetterAndBoxing(int reps) { + for (int i = 0; i < reps; i++) { + Float value = 0.1f; + view.setX(value); + } + } + + public void timeDirectFieldSetAndBoxing(int reps) { + for (int i = 0; i < reps; i++) { + Float value = 0.1f; + view.x = value; + } + } + + public void timeReflectionSetterAndTwoBoxes(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + setX.invoke(view, 0.1f); + } + } + + public void timeReflectionSetterAndOneBox(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + argsBox[0] = 0.1f; + setX.invoke(view, argsBox); + } + } + + public void timeReflectionFieldSet(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + x.setFloat(view, 0.1f); + } + } + + public void timeGeneratedSetter(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + generatedSetter.setFloat(view, 0.1f); + } + } + + public void timeGeneratedFieldSet(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + generatedField.setFloat(view, 0.1f); + } + } + + static class View { + float x; + + public void setX(float x) { + this.x = x; + } + } + + static interface GeneratedProperty { + void setFloat(View v, float f); + } + + static class GeneratedSetter implements GeneratedProperty { + public void setFloat(View v, float f) { + v.setX(f); + } + } + + static class GeneratedField implements GeneratedProperty { + public void setFloat(View v, float f) { + v.x = f; + } + } +} diff --git a/benchmarks/regression/RandomBenchmark.java b/benchmarks/regression/RandomBenchmark.java new file mode 100644 index 0000000..0792805 --- /dev/null +++ b/benchmarks/regression/RandomBenchmark.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import java.security.SecureRandom; +import java.util.Random; +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; + +public class RandomBenchmark extends SimpleBenchmark { + public void timeNewRandom(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + Random rng = new Random(); + rng.nextInt(); + } + } + + public void timeReusedRandom(int reps) throws Exception { + Random rng = new Random(); + for (int i = 0; i < reps; ++i) { + rng.nextInt(); + } + } + + public void timeReusedSecureRandom(int reps) throws Exception { + SecureRandom rng = new SecureRandom(); + for (int i = 0; i < reps; ++i) { + rng.nextInt(); + } + } + + public void timeNewSecureRandom(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + SecureRandom rng = new SecureRandom(); + rng.nextInt(); + } + } +} diff --git a/benchmarks/regression/RealToStringBenchmark.java b/benchmarks/regression/RealToStringBenchmark.java new file mode 100644 index 0000000..8914cf6 --- /dev/null +++ b/benchmarks/regression/RealToStringBenchmark.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +public class RealToStringBenchmark extends SimpleBenchmark { + + private static final float SMALL = -123.45f; + private static final float MEDIUM = -123.45e8f; + private static final float LARGE = -123.45e36f; + + public void timeFloat_toString_NaN(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Float.toString(Float.NaN); + } + } + + public void timeFloat_toString_NEGATIVE_INFINITY(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Float.toString(Float.NEGATIVE_INFINITY); + } + } + + public void timeFloat_toString_POSITIVE_INFINITY(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Float.toString(Float.POSITIVE_INFINITY); + } + } + + public void timeFloat_toString_zero(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Float.toString(0.0f); + } + } + + public void timeFloat_toString_minusZero(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Float.toString(-0.0f); + } + } + + public void timeFloat_toString_small(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Float.toString(SMALL); + } + } + + public void timeFloat_toString_medium(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Float.toString(MEDIUM); + } + } + + public void timeFloat_toString_large(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Float.toString(LARGE); + } + } + + public void timeStringBuilder_small(int reps) { + for (int rep = 0; rep < reps; ++rep) { + new StringBuilder().append(SMALL); + } + } + + public void timeStringBuilder_medium(int reps) { + for (int rep = 0; rep < reps; ++rep) { + new StringBuilder().append(MEDIUM); + } + } + + public void timeStringBuilder_large(int reps) { + for (int rep = 0; rep < reps; ++rep) { + new StringBuilder().append(LARGE); + } + } + + public void timeFormatter_small(int reps) { + for (int rep = 0; rep < reps; ++rep) { + String.format("%f", SMALL); + } + } + + public void timeFormatter_medium(int reps) { + for (int rep = 0; rep < reps; ++rep) { + String.format("%f", MEDIUM); + } + } + + public void timeFormatter_large(int reps) { + for (int rep = 0; rep < reps; ++rep) { + String.format("%f", LARGE); + } + } + + public void timeFormatter_dot2f_small(int reps) { + for (int rep = 0; rep < reps; ++rep) { + String.format("%.2f", SMALL); + } + } + + public void timeFormatter_dot2f_medium(int reps) { + for (int rep = 0; rep < reps; ++rep) { + String.format("%.2f", MEDIUM); + } + } + + public void timeFormatter_dot2f_large(int reps) { + for (int rep = 0; rep < reps; ++rep) { + String.format("%.2f", LARGE); + } + } +} diff --git a/benchmarks/regression/ReflectionBenchmark.java b/benchmarks/regression/ReflectionBenchmark.java new file mode 100644 index 0000000..fe00fa2 --- /dev/null +++ b/benchmarks/regression/ReflectionBenchmark.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; +import java.lang.reflect.*; + +public class ReflectionBenchmark extends SimpleBenchmark { + public void timeObject_getClass(int reps) throws Exception { + C c = new C(); + for (int rep = 0; rep < reps; ++rep) { + c.getClass(); + } + } + + public void timeClass_getField(int reps) throws Exception { + Class<?> klass = C.class; + for (int rep = 0; rep < reps; ++rep) { + klass.getField("f"); + } + } + + public void timeClass_getDeclaredField(int reps) throws Exception { + Class<?> klass = C.class; + for (int rep = 0; rep < reps; ++rep) { + klass.getDeclaredField("f"); + } + } + + public void timeClass_getConstructor(int reps) throws Exception { + Class<?> klass = C.class; + for (int rep = 0; rep < reps; ++rep) { + klass.getConstructor(); + } + } + + public void timeClass_newInstance(int reps) throws Exception { + Class<?> klass = C.class; + Constructor constructor = klass.getConstructor(); + for (int rep = 0; rep < reps; ++rep) { + constructor.newInstance(); + } + } + + public void timeClass_getMethod(int reps) throws Exception { + Class<?> klass = C.class; + for (int rep = 0; rep < reps; ++rep) { + klass.getMethod("m"); + } + } + + public void timeClass_getDeclaredMethod(int reps) throws Exception { + Class<?> klass = C.class; + for (int rep = 0; rep < reps; ++rep) { + klass.getDeclaredMethod("m"); + } + } + + public void timeField_setInt(int reps) throws Exception { + Class<?> klass = C.class; + Field f = klass.getDeclaredField("f"); + C instance = new C(); + for (int rep = 0; rep < reps; ++rep) { + f.setInt(instance, 1); + } + } + + public void timeField_getInt(int reps) throws Exception { + Class<?> klass = C.class; + Field f = klass.getDeclaredField("f"); + C instance = new C(); + for (int rep = 0; rep < reps; ++rep) { + f.getInt(instance); + } + } + + public void timeMethod_invokeV(int reps) throws Exception { + Class<?> klass = C.class; + Method m = klass.getDeclaredMethod("m"); + C instance = new C(); + for (int rep = 0; rep < reps; ++rep) { + m.invoke(instance); + } + } + + public void timeMethod_invokeStaticV(int reps) throws Exception { + Class<?> klass = C.class; + Method m = klass.getDeclaredMethod("sm"); + for (int rep = 0; rep < reps; ++rep) { + m.invoke(null); + } + } + + public void timeMethod_invokeI(int reps) throws Exception { + Class<?> klass = C.class; + Method m = klass.getDeclaredMethod("setField", int.class); + C instance = new C(); + for (int rep = 0; rep < reps; ++rep) { + m.invoke(instance, 1); + } + } + + public void timeMethod_invokePreBoxedI(int reps) throws Exception { + Class<?> klass = C.class; + Method m = klass.getDeclaredMethod("setField", int.class); + C instance = new C(); + Integer one = Integer.valueOf(1); + for (int rep = 0; rep < reps; ++rep) { + m.invoke(instance, one); + } + } + + public void timeMethod_invokeStaticI(int reps) throws Exception { + Class<?> klass = C.class; + Method m = klass.getDeclaredMethod("setStaticField", int.class); + for (int rep = 0; rep < reps; ++rep) { + m.invoke(null, 1); + } + } + + public void timeMethod_invokeStaticPreBoxedI(int reps) throws Exception { + Class<?> klass = C.class; + Method m = klass.getDeclaredMethod("setStaticField", int.class); + Integer one = Integer.valueOf(1); + for (int rep = 0; rep < reps; ++rep) { + m.invoke(null, one); + } + } + + public void timeRegularMethodInvocation(int reps) throws Exception { + C instance = new C(); + for (int rep = 0; rep < reps; ++rep) { + instance.setField(1); + } + } + + public void timeRegularConstructor(int reps) throws Exception { + for (int rep = 0; rep < reps; ++rep) { + new C(); + } + } + + public static class C { + public static int sf = 0; + public int f = 0; + + public C() { + // A non-empty constructor so we don't get optimized away. + f = 1; + } + + public void m() { + } + + public static void sm() { + } + + public void setField(int value) { + f = value; + } + + public static void setStaticField(int value) { + sf = value; + } + } +} diff --git a/benchmarks/regression/SSLSocketBenchmark.java b/benchmarks/regression/SSLSocketBenchmark.java new file mode 100644 index 0000000..fd72a79 --- /dev/null +++ b/benchmarks/regression/SSLSocketBenchmark.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.Socket; +import java.net.URL; +import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; + +public class SSLSocketBenchmark extends SimpleBenchmark { + + private static final int BUFFER_SIZE = 8192; + + final byte[] buffer = new byte[BUFFER_SIZE]; + + @Param private WebSite webSite; + + public enum WebSite { + DOCS("https://docs.google.com"), + MAIL("https://mail.google.com"), + SITES("https://sites.google.com"), + WWW("https://www.google.com"); + final InetAddress host; + final int port; + final byte[] request; + WebSite(String uri) { + try { + URL url = new URL(uri); + + this.host = InetAddress.getByName(url.getHost()); + + int p = url.getPort(); + String portString; + if (p == -1) { + this.port = 443; + portString = ""; + } else { + this.port = p; + portString = ":" + port; + } + + this.request = ("GET " + uri + " HTTP/1.0\r\n" + + "Host: " + host + portString + "\r\n" + +"\r\n").getBytes(); + + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + @Param private Implementation implementation; + + public enum Implementation { OPENSSL, HARMONY }; + + private SocketFactory sf; + + @Override protected void setUp() throws Exception { + SSLContext sslContext; + switch (implementation) { + case OPENSSL: + sslContext = SSLContext.getInstance("SSL", "AndroidOpenSSL"); + break; + case HARMONY: + sslContext = SSLContext.getInstance("SSL", "HarmonyJSSE"); + break; + default: + throw new RuntimeException(implementation.toString()); + } + sslContext.init(null, null, null); + this.sf = sslContext.getSocketFactory(); + } + + public void time(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + Socket s = sf.createSocket(webSite.host, webSite.port); + OutputStream out = s.getOutputStream(); + out.write(webSite.request); + InputStream in = s.getInputStream(); + while (true) { + int n = in.read(buffer); + if (n == -1) { + break; + } + } + in.close(); + } + } +} diff --git a/benchmarks/regression/SchemePrefixBenchmark.java b/benchmarks/regression/SchemePrefixBenchmark.java new file mode 100644 index 0000000..d90fe29 --- /dev/null +++ b/benchmarks/regression/SchemePrefixBenchmark.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public final class SchemePrefixBenchmark extends SimpleBenchmark { + + enum Strategy { + JAVA() { + @Override String execute(String spec) { + int colon = spec.indexOf(':'); + + if (colon < 1) { + return null; + } + + for (int i = 0; i < colon; i++) { + char c = spec.charAt(i); + if (!isValidSchemeChar(i, c)) { + return null; + } + } + + return spec.substring(0, colon).toLowerCase(Locale.US); + } + + private boolean isValidSchemeChar(int index, char c) { + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + return true; + } + if (index > 0 && ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.')) { + return true; + } + return false; + } + }, + + REGEX() { + private final Pattern pattern = Pattern.compile("^([a-zA-Z][a-zA-Z0-9+\\-.]*):"); + + @Override String execute(String spec) { + Matcher matcher = pattern.matcher(spec); + if (matcher.find()) { + return matcher.group(1).toLowerCase(Locale.US); + } else { + return null; + } + } + }; + + + abstract String execute(String spec); + } + + @Param Strategy strategy; + + public void timeSchemePrefix(int reps) { + for (int i = 0; i < reps; i++) { + strategy.execute("http://android.com"); + } + } +} diff --git a/benchmarks/regression/SerializationBenchmark.java b/benchmarks/regression/SerializationBenchmark.java new file mode 100644 index 0000000..bc958eb --- /dev/null +++ b/benchmarks/regression/SerializationBenchmark.java @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; +import java.io.*; +import java.lang.reflect.*; +import java.util.*; + +public class SerializationBenchmark extends SimpleBenchmark { + private static byte[] bytes(Object o) throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + ObjectOutputStream out = new ObjectOutputStream(baos); + out.writeObject(o); + out.close(); + return baos.toByteArray(); + } + + public void timeReadIntArray(int reps) throws Exception { + int[] intArray = new int[256]; + readSingleObject(reps, intArray); + } + + public void timeWriteIntArray(int reps) throws Exception { + int[] intArray = new int[256]; + writeSingleObject(reps, intArray); + } + public void timeReadArrayListInteger(int reps) throws Exception { + ArrayList<Integer> object = new ArrayList<Integer>(); + for (int i = 0; i < 256; ++i) { + object.add(i); + } + readSingleObject(reps, object); + } + + public void timeWriteArrayListInteger(int reps) throws Exception { + ArrayList<Integer> object = new ArrayList<Integer>(); + for (int i = 0; i < 256; ++i) { + object.add(i); + } + writeSingleObject(reps, object); + } + + public void timeReadString(int reps) throws Exception { + readSingleObject(reps, "hello"); + } + + public void timeReadObjectStreamClass(int reps) throws Exception { + // A special case because serialization itself requires this class. + // (This should really be a unit test.) + ObjectStreamClass osc = ObjectStreamClass.lookup(String.class); + readSingleObject(reps, osc); + } + + public void timeWriteString(int reps) throws Exception { + // String is a special case that avoids JNI. + writeSingleObject(reps, "hello"); + } + + public void timeWriteObjectStreamClass(int reps) throws Exception { + // A special case because serialization itself requires this class. + // (This should really be a unit test.) + ObjectStreamClass osc = ObjectStreamClass.lookup(String.class); + writeSingleObject(reps, osc); + } + + // This is a baseline for the others. + public void timeWriteNoObjects(int reps) throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + ObjectOutputStream out = new ObjectOutputStream(baos); + for (int rep = 0; rep < reps; ++rep) { + out.reset(); + baos.reset(); + } + out.close(); + } + + private void readSingleObject(int reps, Object object) throws Exception { + byte[] bytes = bytes(object); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + for (int rep = 0; rep < reps; ++rep) { + ObjectInputStream in = new ObjectInputStream(bais); + in.readObject(); + in.close(); + bais.reset(); + } + } + + private void writeSingleObject(int reps, Object o) throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + ObjectOutputStream out = new ObjectOutputStream(baos); + for (int rep = 0; rep < reps; ++rep) { + out.writeObject(o); + out.reset(); + baos.reset(); + } + out.close(); + } + + public void timeWriteEveryKindOfField(int reps) throws Exception { + writeSingleObject(reps, new LittleBitOfEverything()); + } + public void timeWriteSerializableBoolean(int reps) throws Exception { + writeSingleObject(reps, new SerializableBoolean()); + } + public void timeWriteSerializableByte(int reps) throws Exception { + writeSingleObject(reps, new SerializableByte()); + } + public void timeWriteSerializableChar(int reps) throws Exception { + writeSingleObject(reps, new SerializableChar()); + } + public void timeWriteSerializableDouble(int reps) throws Exception { + writeSingleObject(reps, new SerializableDouble()); + } + public void timeWriteSerializableFloat(int reps) throws Exception { + writeSingleObject(reps, new SerializableFloat()); + } + public void timeWriteSerializableInt(int reps) throws Exception { + writeSingleObject(reps, new SerializableInt()); + } + public void timeWriteSerializableLong(int reps) throws Exception { + writeSingleObject(reps, new SerializableLong()); + } + public void timeWriteSerializableShort(int reps) throws Exception { + writeSingleObject(reps, new SerializableShort()); + } + public void timeWriteSerializableReference(int reps) throws Exception { + writeSingleObject(reps, new SerializableReference()); + } + + public void timeReadEveryKindOfField(int reps) throws Exception { + readSingleObject(reps, new LittleBitOfEverything()); + } + public void timeReadSerializableBoolean(int reps) throws Exception { + readSingleObject(reps, new SerializableBoolean()); + } + public void timeReadSerializableByte(int reps) throws Exception { + readSingleObject(reps, new SerializableByte()); + } + public void timeReadSerializableChar(int reps) throws Exception { + readSingleObject(reps, new SerializableChar()); + } + public void timeReadSerializableDouble(int reps) throws Exception { + readSingleObject(reps, new SerializableDouble()); + } + public void timeReadSerializableFloat(int reps) throws Exception { + readSingleObject(reps, new SerializableFloat()); + } + public void timeReadSerializableInt(int reps) throws Exception { + readSingleObject(reps, new SerializableInt()); + } + public void timeReadSerializableLong(int reps) throws Exception { + readSingleObject(reps, new SerializableLong()); + } + public void timeReadSerializableShort(int reps) throws Exception { + readSingleObject(reps, new SerializableShort()); + } + public void timeReadSerializableReference(int reps) throws Exception { + readSingleObject(reps, new SerializableReference()); + } + + public static class SerializableBoolean implements Serializable { + boolean z; + } + public static class SerializableByte implements Serializable { + byte b; + } + public static class SerializableChar implements Serializable { + char c; + } + public static class SerializableDouble implements Serializable { + double d; + } + public static class SerializableFloat implements Serializable { + float f; + } + public static class SerializableInt implements Serializable { + int i; + } + public static class SerializableLong implements Serializable { + long j; + } + public static class SerializableShort implements Serializable { + short s; + } + public static class SerializableReference implements Serializable { + Object l; + } + + public static class LittleBitOfEverything implements Serializable { + boolean z; + byte b; + char c; + double d; + float f; + int i; + long j; + short s; + Object l; + } +} diff --git a/benchmarks/regression/SignatureBenchmark.java b/benchmarks/regression/SignatureBenchmark.java new file mode 100644 index 0000000..383dcfd --- /dev/null +++ b/benchmarks/regression/SignatureBenchmark.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Signature; +import java.util.HashMap; +import java.util.Map; +import org.apache.harmony.xnet.provider.jsse.OpenSSLSignature; + +/** + * Tests RSA and DSA signature creation and verification. + */ +public class SignatureBenchmark extends SimpleBenchmark { + + private static final int DATA_SIZE = 8192; + private static final byte[] DATA = new byte[DATA_SIZE]; + static { + for (int i = 0; i < DATA_SIZE; i++) { + DATA[i] = (byte)i; + } + } + @Param private Algorithm algorithm; + + public enum Algorithm { + MD5WithRSA, + SHA1WithRSA, + SHA256WithRSA, + SHA384WithRSA, + SHA512WithRSA, + SHA1withDSA + }; + + @Param private Implementation implementation; + + public enum Implementation { OpenSSL, BouncyCastle }; + + // Key generation and signing aren't part of the benchmark for verification + // so cache the results + private static Map<String,KeyPair> KEY_PAIRS = new HashMap<String,KeyPair>(); + private static Map<String,byte[]> SIGNATURES = new HashMap<String,byte[]>(); + + private String signatureAlgorithm; + private byte[] signature; + private PrivateKey privateKey; + private PublicKey publicKey; + + @Override protected void setUp() throws Exception { + this.signatureAlgorithm = algorithm.toString(); + + String keyAlgorithm = signatureAlgorithm.substring(signatureAlgorithm.length() - 3 , + signatureAlgorithm.length()); + KeyPair keyPair = KEY_PAIRS.get(keyAlgorithm); + if (keyPair == null) { + KeyPairGenerator generator = KeyPairGenerator.getInstance(keyAlgorithm); + keyPair = generator.generateKeyPair(); + KEY_PAIRS.put(keyAlgorithm, keyPair); + } + this.privateKey = keyPair.getPrivate(); + this.publicKey = keyPair.getPublic(); + + this.signature = SIGNATURES.get(signatureAlgorithm); + if (this.signature == null) { + Signature signer = Signature.getInstance(signatureAlgorithm); + signer.initSign(keyPair.getPrivate()); + signer.update(DATA); + this.signature = signer.sign(); + SIGNATURES.put(signatureAlgorithm, signature); + } + } + + public void timeSign(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + Signature signer; + switch (implementation) { + case OpenSSL: + signer = Signature.getInstance(signatureAlgorithm, "AndroidOpenSSL"); + break; + case BouncyCastle: + signer = Signature.getInstance(signatureAlgorithm, "BC"); + break; + default: + throw new RuntimeException(implementation.toString()); + } + signer.initSign(privateKey); + signer.update(DATA); + signer.sign(); + } + } + + public void timeVerify(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + Signature verifier; + switch (implementation) { + case OpenSSL: + verifier = Signature.getInstance(signatureAlgorithm, "AndroidOpenSSL"); + break; + case BouncyCastle: + verifier = Signature.getInstance(signatureAlgorithm, "BC"); + break; + default: + throw new RuntimeException(implementation.toString()); + } + verifier.initVerify(publicKey); + verifier.update(DATA); + verifier.verify(signature); + } + } +} diff --git a/benchmarks/regression/StrictMathBenchmark.java b/benchmarks/regression/StrictMathBenchmark.java new file mode 100644 index 0000000..44c030a --- /dev/null +++ b/benchmarks/regression/StrictMathBenchmark.java @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +/** + * Many of these tests are bogus in that the cost will vary wildly depending on inputs. + * For _my_ current purposes, that's okay. But beware! + */ +public class StrictMathBenchmark extends SimpleBenchmark { + private final double d = 1.2; + private final float f = 1.2f; + private final int i = 1; + private final long l = 1L; + + public void timeAbsD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.abs(d); + } + } + + public void timeAbsF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.abs(f); + } + } + + public void timeAbsI(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.abs(i); + } + } + + public void timeAbsL(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.abs(l); + } + } + + public void timeAcos(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.acos(d); + } + } + + public void timeAsin(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.asin(d); + } + } + + public void timeAtan(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.atan(d); + } + } + + public void timeAtan2(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.atan2(3, 4); + } + } + + public void timeCbrt(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.cbrt(d); + } + } + + public void timeCeil(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.ceil(d); + } + } + + public void timeCopySignD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.copySign(d, d); + } + } + + public void timeCopySignF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.copySign(f, f); + } + } + + public void timeCos(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.cos(d); + } + } + + public void timeCosh(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.cosh(d); + } + } + + public void timeExp(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.exp(d); + } + } + + public void timeExpm1(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.expm1(d); + } + } + + public void timeFloor(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.floor(d); + } + } + + public void timeGetExponentD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.getExponent(d); + } + } + + public void timeGetExponentF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.getExponent(f); + } + } + + public void timeHypot(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.hypot(d, d); + } + } + + public void timeIEEEremainder(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.IEEEremainder(d, d); + } + } + + public void timeLog(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.log(d); + } + } + + public void timeLog10(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.log10(d); + } + } + + public void timeLog1p(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.log1p(d); + } + } + + public void timeMaxD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.max(d, d); + } + } + + public void timeMaxF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.max(f, f); + } + } + + public void timeMaxI(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.max(i, i); + } + } + + public void timeMaxL(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.max(l, l); + } + } + + public void timeMinD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.min(d, d); + } + } + + public void timeMinF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.min(f, f); + } + } + + public void timeMinI(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.min(i, i); + } + } + + public void timeMinL(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.min(l, l); + } + } + + public void timeNextAfterD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.nextAfter(d, d); + } + } + + public void timeNextAfterF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.nextAfter(f, f); + } + } + + public void timeNextUpD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.nextUp(d); + } + } + + public void timeNextUpF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.nextUp(f); + } + } + + public void timePow(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.pow(d, d); + } + } + + public void timeRandom(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.random(); + } + } + + public void timeRint(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.rint(d); + } + } + + public void timeRoundD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.round(d); + } + } + + public void timeRoundF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.round(f); + } + } + + public void timeScalbD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.scalb(d, 5); + } + } + + public void timeScalbF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.scalb(f, 5); + } + } + + public void timeSignumD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.signum(d); + } + } + + public void timeSignumF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.signum(f); + } + } + + public void timeSin(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.sin(d); + } + } + + public void timeSinh(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.sinh(d); + } + } + + public void timeSqrt(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.sqrt(d); + } + } + + public void timeTan(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.tan(d); + } + } + + public void timeTanh(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.tanh(d); + } + } + + public void timeToDegrees(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.toDegrees(d); + } + } + + public void timeToRadians(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.toRadians(d); + } + } + + public void timeUlpD(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.ulp(d); + } + } + + public void timeUlpF(int reps) { + for (int rep = 0; rep < reps; ++rep) { + StrictMath.ulp(f); + } + } +} diff --git a/benchmarks/regression/StringBenchmark.java b/benchmarks/regression/StringBenchmark.java new file mode 100644 index 0000000..e09ee8b --- /dev/null +++ b/benchmarks/regression/StringBenchmark.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; + +public class StringBenchmark extends SimpleBenchmark { + enum StringLengths { + EMPTY(""), + SHORT("short"), + EIGHTY(makeString(80)), + EIGHT_KI(makeString(8192)); + final String value; + private StringLengths(String value) { this.value = value; } + } + @Param private StringLengths s; + + private static String makeString(int length) { + StringBuilder result = new StringBuilder(length); + for (int i = 0; i < length; ++i) { + result.append((char) i); + } + return result.toString(); + } + + public void timeHashCode(int reps) { + for (int i = 0; i < reps; ++i) { + s.value.hashCode(); + } + } +} diff --git a/benchmarks/regression/StringBuilderBenchmark.java b/benchmarks/regression/StringBuilderBenchmark.java new file mode 100644 index 0000000..79eff2a --- /dev/null +++ b/benchmarks/regression/StringBuilderBenchmark.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +/** + * Tests the performance of various StringBuilder methods. + */ +public class StringBuilderBenchmark extends SimpleBenchmark { + + @Param({"1", "10", "100"}) private int length; + + public void timeAppendBoolean(int reps) { + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(true); + } + } + } + + public void timeAppendChar(int reps) { + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append('c'); + } + } + } + + public void timeAppendCharArray(int reps) { + char[] chars = "chars".toCharArray(); + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(chars); + } + } + } + + public void timeAppendCharSequence(int reps) { + CharSequence cs = "chars"; + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(cs); + } + } + } + + public void timeAppendDouble(int reps) { + double d = 1.2; + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(d); + } + } + } + + public void timeAppendFloat(int reps) { + float f = 1.2f; + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(f); + } + } + } + + public void timeAppendInt(int reps) { + int n = 123; + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(n); + } + } + } + + public void timeAppendLong(int reps) { + long l = 123; + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(l); + } + } + } + + public void timeAppendObject(int reps) { + // We don't want to time the toString, so ensure we're calling a trivial one... + Object o = new Object() { + @Override public String toString() { + return "constant"; + } + }; + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(o); + } + } + } + + public void timeAppendString(int reps) { + String s = "chars"; + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(s); + } + } + } +} diff --git a/benchmarks/regression/StringCaseMappingBenchmark.java b/benchmarks/regression/StringCaseMappingBenchmark.java new file mode 100644 index 0000000..ba5b59e --- /dev/null +++ b/benchmarks/regression/StringCaseMappingBenchmark.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import java.util.Locale; +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; + +public class StringCaseMappingBenchmark extends SimpleBenchmark { + enum Inputs { + EMPTY(""), + + // TODO: include hairy inputs like turkish and greek. + // TODO: locale makes a difference too. + + LOWER2(lower(2)), + UPPER2(upper(2)), + MIXED2(mixed(2)), + + LOWER8(lower(8)), + UPPER8(upper(8)), + MIXED8(mixed(8)), + + LOWER32(lower(32)), + UPPER32(upper(32)), + MIXED32(mixed(32)), + + LOWER512(lower(512)), + UPPER512(upper(512)), + MIXED512(mixed(512)), + + LOWER2048(lower(2048)), + UPPER2048(upper(2048)), + MIXED2048(mixed(2048)), + + LOWER_1M(lower(1024*1024)), + UPPER_1M(upper(1024*1024)), + MIXED_1M(mixed(1024*1024)); + + final String value; + private Inputs(String value) { this.value = value; } + private static String lower(int length) { + return makeString(length, "a0b1c2d3e4f5g6h7i8j9klmnopqrstuvwxyz"); + } + private static String upper(int length) { + return makeString(length, "A0B1C2D3E4F5G6H7I8J9KLMNOPQRSTUVWXYZ"); + } + private static String mixed(int length) { + return makeString(length, "Aa0Bb1Cc2Dd3Ee4Ff5Gg6Hh7Ii8Jj9KkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"); + } + private static String makeString(int length, String alphabet) { + StringBuilder sb = new StringBuilder(length); + for (int i = 0; i < length; ++i) { + sb.append(alphabet.charAt(i % alphabet.length())); + } + return sb.toString(); + } + } + @Param private Inputs s; + + public void timeToUpperCase_US(int reps) { + for (int i = 0; i < reps; ++i) { + s.value.toUpperCase(Locale.US); + } + } + + public void timeToLowerCase_US(int reps) { + for (int i = 0; i < reps; ++i) { + s.value.toUpperCase(Locale.US); + } + } + + public void timeToUpperCase_Ascii(int reps) { + for (int i = 0; i < reps; ++i) { + toUpperCaseAscii(s.value); + } + } + + public void timeToLowerCase_Ascii(int reps) { + for (int i = 0; i < reps; ++i) { + toUpperCaseAscii(s.value); + } + } + + public void timeToUpperCase_ICU(int reps) { + for (int i = 0; i < reps; ++i) { + libcore.icu.ICU.toUpperCase(s.value, Locale.US.toString()); + } + } + + public void timeToLowerCase_ICU(int reps) { + for (int i = 0; i < reps; ++i) { + libcore.icu.ICU.toLowerCase(s.value, Locale.US.toString()); + } + } + + public static String toUpperCaseAscii(String s) { + for (int i = 0, length = s.length(); i < length; i++) { + char c = s.charAt(i); + if (c < 'a' || c > 'z') { + continue; // fast path avoids allocation + } + + // slow path: s contains lower case chars + char[] result = s.toCharArray(); + for (; i < length; i++) { + c = result[i]; + if (c >= 'a' && c <= 'z') { + result[i] -= ('a' - 'A'); + } + } + return new String(result); + } + return s; + } + + public static String toLowerCaseAscii(String s) { + for (int i = 0, length = s.length(); i < length; i++) { + char c = s.charAt(i); + if (c < 'A' || c > 'Z') { + continue; // fast path avoids allocation + } + + // slow path: s contains upper case chars + char[] result = s.toCharArray(); + for (; i < length; i++) { + c = result[i]; + if (c >= 'A' && c <= 'Z') { + result[i] += ('a' - 'A'); + } + } + return new String(result); + } + return s; + } +} diff --git a/benchmarks/regression/StringIsEmptyBenchmark.java b/benchmarks/regression/StringIsEmptyBenchmark.java new file mode 100644 index 0000000..a3be80a --- /dev/null +++ b/benchmarks/regression/StringIsEmptyBenchmark.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +public class StringIsEmptyBenchmark extends SimpleBenchmark { + public void timeIsEmpty_NonEmpty(int reps) { + boolean result = true; + for (int i = 0; i < reps; ++i) { + result &= !("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".isEmpty()); + } + if (!result) throw new RuntimeException(); + } + + public void timeIsEmpty_Empty(int reps) { + boolean result = true; + for (int i = 0; i < reps; ++i) { + result &= ("".isEmpty()); + } + if (!result) throw new RuntimeException(); + } + + public void timeLengthEqualsZero(int reps) { + boolean result = true; + for (int i = 0; i < reps; ++i) { + result &= !("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".length() == 0); + } + if (!result) throw new RuntimeException(); + } + + public void timeEqualsEmpty(int reps) { + boolean result = true; + for (int i = 0; i < reps; ++i) { + result &= !"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".equals(""); + } + if (!result) throw new RuntimeException(); + } +} diff --git a/benchmarks/regression/StringLengthBenchmark.java b/benchmarks/regression/StringLengthBenchmark.java new file mode 100644 index 0000000..962e395 --- /dev/null +++ b/benchmarks/regression/StringLengthBenchmark.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +public class StringLengthBenchmark extends SimpleBenchmark { + public void timeLength(int reps) { + int length = 0; + for (int i = 0; i < reps; ++i) { + length = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".length(); + } + if (length != 51) throw new RuntimeException(); + } +} diff --git a/benchmarks/regression/StringSplitBenchmark.java b/benchmarks/regression/StringSplitBenchmark.java new file mode 100644 index 0000000..37fdf8f --- /dev/null +++ b/benchmarks/regression/StringSplitBenchmark.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.SimpleBenchmark; +import java.util.regex.Pattern; + +public class StringSplitBenchmark extends SimpleBenchmark { + public void timeStringSplitComma(int reps) { + for (int i = 0; i < reps; ++i) { + "this,is,a,simple,example".split(","); + } + } + + public void timeStringSplitLiteralDot(int reps) { + for (int i = 0; i < reps; ++i) { + "this.is.a.simple.example".split("\\."); + } + } + + public void timeStringSplitNewline(int reps) { + for (int i = 0; i < reps; ++i) { + "this\nis\na\nsimple\nexample\n".split("\n"); + } + } + + public void timePatternSplitComma(int reps) { + Pattern p = Pattern.compile(","); + for (int i = 0; i < reps; ++i) { + p.split("this,is,a,simple,example"); + } + } + + public void timePatternSplitLiteralDot(int reps) { + Pattern p = Pattern.compile("\\."); + for (int i = 0; i < reps; ++i) { + p.split("this.is.a.simple.example"); + } + } + + public void timeStringSplitHard(int reps) { + for (int i = 0; i < reps; ++i) { + "this,is,a,harder,example".split("[,]"); + } + } +} diff --git a/benchmarks/regression/StringToRealBenchmark.java b/benchmarks/regression/StringToRealBenchmark.java new file mode 100644 index 0000000..ef7a633 --- /dev/null +++ b/benchmarks/regression/StringToRealBenchmark.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +public class StringToRealBenchmark extends SimpleBenchmark { + + @Param({ + "NaN", + "-1", + "0", + "1", + "1.2", + "-123.45", + "-123.45e8", + "-123.45e36" + }) String string; + + public void timeFloat_parseFloat(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Float.parseFloat(string); + } + } + + public void timeDouble_parseDouble(int reps) { + for (int rep = 0; rep < reps; ++rep) { + Double.parseDouble(string); + } + } +} diff --git a/benchmarks/regression/SystemPropertiesBenchmark.java b/benchmarks/regression/SystemPropertiesBenchmark.java new file mode 100644 index 0000000..9c675e1 --- /dev/null +++ b/benchmarks/regression/SystemPropertiesBenchmark.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.SimpleBenchmark; + +public class SystemPropertiesBenchmark extends SimpleBenchmark { + public void timeGetProperties(int reps) throws Exception { + for (int i = 0; i < reps; ++i) { + // Force the properties to be recreated. + System.setProperties(null); + System.getProperties(); + } + } +} diff --git a/benchmarks/regression/ThreadLocalBenchmark.java b/benchmarks/regression/ThreadLocalBenchmark.java new file mode 100644 index 0000000..df0715b --- /dev/null +++ b/benchmarks/regression/ThreadLocalBenchmark.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +public class ThreadLocalBenchmark extends SimpleBenchmark { + private static final ThreadLocal<char[]> BUFFER = new ThreadLocal<char[]>() { + @Override protected char[] initialValue() { + return new char[20]; + } + }; + + public void timeThreadLocal_get(int reps) { + for (int rep = 0; rep < reps; ++rep) { + BUFFER.get(); + } + } +} diff --git a/benchmarks/regression/TimeZoneBenchmark.java b/benchmarks/regression/TimeZoneBenchmark.java new file mode 100644 index 0000000..ccef392 --- /dev/null +++ b/benchmarks/regression/TimeZoneBenchmark.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.SimpleBenchmark; +import java.util.TimeZone; + +public class TimeZoneBenchmark extends SimpleBenchmark { + public void timeTimeZone_getDefault(int reps) throws Exception { + for (int rep = 0; rep < reps; ++rep) { + TimeZone.getDefault(); + } + } + + public void timeTimeZone_getTimeZoneUTC(int reps) throws Exception { + for (int rep = 0; rep < reps; ++rep) { + TimeZone.getTimeZone("UTC"); + } + } + + public void timeTimeZone_getTimeZone_default(int reps) throws Exception { + String defaultId = TimeZone.getDefault().getID(); + for (int rep = 0; rep < reps; ++rep) { + TimeZone.getTimeZone(defaultId); + } + } + + // A time zone with relatively few transitions. + public void timeTimeZone_getTimeZone_America_Caracas(int reps) throws Exception { + for (int rep = 0; rep < reps; ++rep) { + TimeZone.getTimeZone("America/Caracas"); + } + } + + // A time zone with a lot of transitions. + public void timeTimeZone_getTimeZone_America_Santiago(int reps) throws Exception { + for (int rep = 0; rep < reps; ++rep) { + TimeZone.getTimeZone("America/Santiago"); + } + } + + public void timeTimeZone_getTimeZone_GMT_plus_10(int reps) throws Exception { + for (int rep = 0; rep < reps; ++rep) { + TimeZone.getTimeZone("GMT+10"); + } + } +} diff --git a/benchmarks/regression/URLConnectionBenchmark.java b/benchmarks/regression/URLConnectionBenchmark.java new file mode 100644 index 0000000..e5ceec4 --- /dev/null +++ b/benchmarks/regression/URLConnectionBenchmark.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import tests.http.MockResponse; +import tests.http.MockWebServer; + +public final class URLConnectionBenchmark extends SimpleBenchmark { + + @Param({"0", "1024", "1048576"}) private int bodySize; + @Param({"2048"}) private int chunkSize; + @Param({"1024"}) private int readBufferSize; + @Param private ResponseHeaders responseHeaders; + @Param private TransferEncoding transferEncoding; + private byte[] readBuffer; + + private MockWebServer server; + private URL url; + + protected void setUp() throws Exception { + readBuffer = new byte[readBufferSize]; + server = new MockWebServer(); + + MockResponse response = new MockResponse(); + responseHeaders.apply(response); + transferEncoding.setBody(response, bodySize, chunkSize); + server.enqueue(response); + + server.setContinuousServing(true); + server.play(); + + url = server.getUrl("/"); + get(); // ensure the server has started its threads, etc. + } + + protected void tearDown() throws Exception { + /* + * Entice the server to shut itself down gracefully. The shutdown method + * doesn't work on Dalvik because socket.close() doesn't release blocked + * threads. Instead, read the last continuously-served request, and then + * cause the server to close the otherwise-reusable HTTP connection. + */ + server.setContinuousServing(false); + server.enqueue(new MockResponse().setDisconnectAtEnd(true)); + get(); + get(); + server.shutdown(); + } + + public int timeGet(int reps) throws IOException { + int totalBytesRead = 0; + for (int i = 0; i < reps; i++) { + totalBytesRead += get(); + } + return totalBytesRead; + } + + private int get() throws IOException { + int totalBytesRead = 0; + URLConnection connection = url.openConnection(); + InputStream in = connection.getInputStream(); + int count; + while ((count = in.read(readBuffer)) != -1) { + totalBytesRead += count; + } + return totalBytesRead; + } + + enum TransferEncoding { + FIXED_LENGTH, + CHUNKED; + + void setBody(MockResponse response, int bodySize, int chunkSize) throws IOException { + if (this == TransferEncoding.FIXED_LENGTH) { + response.setBody(new byte[bodySize]); + } else if (this == TransferEncoding.CHUNKED) { + response.setChunkedBody(new byte[bodySize], chunkSize); + } + } + } + + enum ResponseHeaders { + MINIMAL, + TYPICAL; + + void apply(MockResponse response) { + if (this == TYPICAL) { + /* from http://api.twitter.com/1/statuses/public_timeline.json */ + response.addHeader("Date: Wed, 30 Jun 2010 17:57:39 GMT"); + response.addHeader("Server: hi"); + response.addHeader("X-RateLimit-Remaining: 0"); + response.addHeader("X-Runtime: 0.01637"); + response.addHeader("Content-Type: application/json; charset=utf-8"); + response.addHeader("X-RateLimit-Class: api_whitelisted"); + response.addHeader("Cache-Control: no-cache, max-age=300"); + response.addHeader("X-RateLimit-Reset: 1277920980"); + response.addHeader("Set-Cookie: _twitter_sess=BAh7EDoOcmV0dXJuX3RvIjZodHRwOi8vZGV2L" + + "nR3aXR0ZXIuY29tL3BhZ2Vz%250AL3NpZ25faW5fd2l0aF90d2l0dGVyOgxjc3JmX2lkIiUw" + + "ODFhNGY2NTM5NjRm%250ANjY1N2M2NzcwNWI0MDlmZGZjZjoVaW5fbmV3X3VzZXJfZmxvdzA" + + "6EXRyYW5z%250AX3Byb21wdDAiKXNob3dfZGlzY292ZXJhYmlsaXR5X2Zvcl9qZXNzZXdpbH" + + "Nv%250AbjA6E3Nob3dfaGVscF9saW5rMDoTcGFzc3dvcmRfdG9rZW4iLWUyYjlhNmM3%250A" + + "MWJiNzI3NWNlZDI1NDY3MGMzZWNmMTE0MjI4N2EyNGE6D2NyZWF0ZWRfYXRs%250AKwhiM%2" + + "52F6JKQE6CXVzZXJpA8tE3iIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxl%250Acjo6Rmxhc2" + + "g6OkZsYXNoSGFzaHsABjoKQHVzZWR7ADoHaWQiJWZmMTNhM2Qx%250AZTU1YTkzMmYyMWM0M" + + "GNhZjU4NDVjMTQz--11250628c85830219438eb7eba96a541a9af4098; domain=.twitt" + + "er.com; path=/"); + response.addHeader("Expires: Wed, 30 Jun 2010 18:02:39 GMT"); + response.addHeader("Vary: Accept-Encoding"); + } + } + } +} diff --git a/benchmarks/regression/XmlEntitiesBenchmark.java b/benchmarks/regression/XmlEntitiesBenchmark.java new file mode 100644 index 0000000..4c5cc18 --- /dev/null +++ b/benchmarks/regression/XmlEntitiesBenchmark.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; +import java.io.StringReader; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import org.xml.sax.InputSource; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserFactory; + +// http://code.google.com/p/android/issues/detail?id=18102 +public final class XmlEntitiesBenchmark extends SimpleBenchmark { + + @Param({"10", "100", "1000"}) int length; + @Param({"0", "0.5", "1.0"}) float entityFraction; + + private XmlPullParserFactory xmlPullParserFactory; + private DocumentBuilderFactory documentBuilderFactory; + + /** a string like {@code <doc>&&++</doc>}. */ + private String xml; + + @Override protected void setUp() throws Exception { + xmlPullParserFactory = XmlPullParserFactory.newInstance(); + documentBuilderFactory = DocumentBuilderFactory.newInstance(); + + StringBuilder xmlBuilder = new StringBuilder(); + xmlBuilder.append("<doc>"); + for (int i = 0; i < (length * entityFraction); i++) { + xmlBuilder.append("&"); + } + while (xmlBuilder.length() < length) { + xmlBuilder.append("+"); + } + xmlBuilder.append("</doc>"); + xml = xmlBuilder.toString(); + } + + public void timeXmlParser(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + XmlPullParser parser = xmlPullParserFactory.newPullParser(); + parser.setInput(new StringReader(xml)); + while (parser.next() != XmlPullParser.END_DOCUMENT) { + } + } + } + + public void timeDocumentBuilder(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + documentBuilder.parse(new InputSource(new StringReader(xml))); + } + } +} |