更新:2009-05-29
感谢所有的建议和意见. 我使用你的建议使我的生产代码平均比几天前的最佳结果快2.5倍. 最后,我能够使java代码最快.
教训:
下面的示例代码显示了原始int的插入,但生产代码实际上存储了字符串(我的坏).当我纠正那个python执行时间从2.8秒变为9.6时.因此,在存储对象时,java实际上更快.
但它并不止于此.我一直在执行java程序,如下所示:
java -Xmx1024m SpeedTest
但是,如果您按如下方式设置初始堆大小,则会获得巨大的改进:
java -Xms1024m -Xmx1024m SpeedTest
Run Code Online (Sandbox Code Playgroud)
这个简单的更改将执行时间减少了50%以上.所以我的SpeedTest的最终结果是蟒蛇9.6秒.Java 6.5秒.
原始问题:
我有以下python代码:
import time
import sys
def main(args):
iterations = 10000000
counts = set()
startTime = time.time();
for i in range(0, iterations):
counts.add(i)
totalTime = time.time() - startTime
print 'total time =',totalTime
print len(counts)
if __name__ == "__main__":
main(sys.argv)
Run Code Online (Sandbox Code Playgroud)
它在我的机器上执行大约3.3秒,但我想让它更快,所以我决定用java编程.我认为因为java被编译并且通常被认为比python更快我会看到一些很大的回报.
这是java代码:
import java.util.*;
class SpeedTest
{
public static void main(String[] args)
{
long startTime;
long totalTime;
int iterations = 10000000;
HashSet counts = …Run Code Online (Sandbox Code Playgroud) 我正在使用http://openjdk.java.net/projects/code-tools/jmh/进行基准测试,我得到的结果如下:
__PRE__
"得分误差"一栏究竟是什么意思以及如何解释它?
我遇到了这个问题,它比较了各种编译器在计算斐波那契数字时的表现.
我尝试用Haskell做这个,看看它与C的比较.
C代码:
#include <stdio.h>
#include <stdlib.h>
int fib (int n) {
if (n < 2) return 1;
return fib (n-1) + fib (n-2);
}
int main (int argc, char* argv[]) {
printf ("%i\n", fib (atoi(argv[1])));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
结果:
> gcc -O3 main.c -o fib
> time ./fib 40
165580141
real 0m0.421s
user 0m0.420s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)
哈斯克尔:
module Main where
import System.Environment (getArgs)
fib :: Int -> Int
fib n | n < 2 = 1
| …Run Code Online (Sandbox Code Playgroud) 我正在玩JMH(http://openjdk.java.net/projects/code-tools/jmh/),我偶然发现了一个奇怪的结果.
我正在对数组的浅层副本进行基准测试,我可以观察到预期的结果(循环遍历数组是一个坏主意#clone(),System#arraycopy()并且在Arrays#copyOf()性能方面没有显着差异).
除了System#arraycopy()是一个季度的慢时,数组的长度是硬编码的......等等,什么?这怎么会慢?
有没有人知道可能是什么原因?
结果(吞吐量):
# JMH 1.11 (released 17 days ago)
# VM version: JDK 1.8.0_05, VM 25.5-b02
# VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_05.jdk/Contents/Home/jre/bin/java
# VM options: -Dfile.encoding=UTF-8 -Duser.country=FR -Duser.language=fr -Duser.variant
# Warmup: 20 iterations, 1 s each
# Measurement: 20 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
Benchmark Mode Cnt Score Error Units
ArrayCopyBenchmark.ArraysCopyOf thrpt …Run Code Online (Sandbox Code Playgroud) 当我测试直接java.nio.ByteBuffer的读取性能时,我注意到绝对读取的平均速度比相对读取快2倍.此外,如果我比较相对与绝对读取的源代码,除了相对读取维护和内部计数器之外,代码几乎相同.我想知道为什么我在速度上看到如此大的差异?
以下是我的JMH基准测试的源代码:
public class DirectByteBufferReadBenchmark {
private static final int OBJ_SIZE = 8 + 4 + 1;
private static final int NUM_ELEM = 10_000_000;
@State(Scope.Benchmark)
public static class Data {
private ByteBuffer directByteBuffer;
@Setup
public void setup() {
directByteBuffer = ByteBuffer.allocateDirect(OBJ_SIZE * NUM_ELEM);
for (int i = 0; i < NUM_ELEM; i++) {
directByteBuffer.putLong(i);
directByteBuffer.putInt(i);
directByteBuffer.put((byte) (i & 1));
}
}
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public long testReadAbsolute(Data d) throws InterruptedException {
long val = 0l;
for (int i = …Run Code Online (Sandbox Code Playgroud) 我遇到了一个有趣的场景.由于某种原因strip(),空格字符串(仅包含空格)明显快trim()于Java 11.
基准
public class Test {
public static final String TEST_STRING = " "; // 3 whitespaces
@Benchmark
@Warmup(iterations = 10, time = 200, timeUnit = MILLISECONDS)
@Measurement(iterations = 20, time = 500, timeUnit = MILLISECONDS)
@BenchmarkMode(Mode.Throughput)
public void testTrim() {
TEST_STRING.trim();
}
@Benchmark
@Warmup(iterations = 10, time = 200, timeUnit = MILLISECONDS)
@Measurement(iterations = 20, time = 500, timeUnit = MILLISECONDS)
@BenchmarkMode(Mode.Throughput)
public void testStrip() {
TEST_STRING.strip();
}
public static void main(String[] args) throws …Run Code Online (Sandbox Code Playgroud) 在参考这个问题时,答案指出未排序的数组花费更多时间,因为它未通过分支预测测试.但如果我们对程序进行微小改动:
import java.util.Arrays;
import java.util.Random;
public class Main{
public static void main(String[] args) {
// Generate data
int arraySize = 32768;
int data[] = new int[arraySize];
Random rnd = new Random(0);
for (int c = 0; c < arraySize; ++c) {
data[c] = rnd.nextInt() % 256;
}
// !!! With this, the next loop runs faster
Arrays.sort(data);
// Test
long start = System.nanoTime();
long sum = 0;
for (int i = 0; i < 100000; ++i) {
// …Run Code Online (Sandbox Code Playgroud) 当我运行 google基准测试时,我收到一条警告,说已启用 cpu 缩放。这是我可以在构建时通过标志或在运行时通过参数切换的功能还是系统设置?
我有一些高度敏感的代码.使用SSEn和AVX的SIMD实现使用大约30条指令,而使用4096字节查找表的版本使用大约8条指令.在微基准测试中,查找表的速度提高了40%.如果我使用microbenchmark,试图使缓存无效100次迭代,它们看起来大致相同.在我的真实程序中,看起来非加载版本更快,但是很难获得可靠的良好测量,并且我已经进行了两种测量.
我只是想知道是否有一些好方法可以考虑哪种方法更适合使用,或者用于此类决策的标准基准测试技术.
我曾尝试使用江铃控股有限公司连同SBT,但到目前为止,我还没有成功地设置正确,这样.scala基于基准的工作.
由于基于sbt + .java的组合基准测试可行,我试图从该基础开始.我正在使用sbt 0.13.1.
build.sbt
import AssemblyKeys._
name := "scala-benchmark"
version := "1.0"
scalaVersion := "2.10.3"
scalacOptions += "-deprecation"
libraryDependencies += "org.openjdk.jmh" % "jmh-core" % "0.5.5"
libraryDependencies += "org.openjdk.jmh" % "jmh-java-benchmark-archetype" % "0.5.5"
libraryDependencies += "org.openjdk.jmh" % "jmh-generator-annprocess" % "0.5.5"
libraryDependencies += "org.openjdk.jmh" % "jmh-generator-bytecode" % "0.5.5"
assemblySettings
jarName in assembly := "microbenchmarks.jar"
test in assembly := {}
mainClass in assembly := Some("org.openjdk.jmh.Main")
Run Code Online (Sandbox Code Playgroud)
要在最后获得一个"胖"jar,需要sbt-assembly插件:
项目/ assembly.sbt
addSbtPlugin("com.eed3si9n" % …Run Code Online (Sandbox Code Playgroud)