- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
(注意:正确答案必须超越复制)。
在数百万次调用之后,quicksort1 肯定比 quicksort2 快,除了这 1 个额外的 arg 之外,它们具有相同的代码。
代码在帖子的最后。剧透:我还发现 jit 代码胖了 224 个字节,即使它实际上应该更简单(就像字节代码大小说明的那样;请参阅下面的最新更新)。
即使在尝试使用一些微基准测试工具 (JMH) 消除这种影响之后,性能差异仍然存在。
我在问:为什么生成的 native 代码有如此大的差异,它在做什么?
通过向方法添加参数,它会使其更快......!
我知道 gc/jit/warmup/etc 的影响。您可以按原样运行代码,也可以使用更大/更小的迭代计数。实际上,您甚至应该先注释掉一个然后另一个 perf 测试并在不同的 jvm 实例中运行每个测试,以证明它不是彼此之间的干扰。
除了 sleft/sright 明显的 getstatic 以及一个奇怪的“iload 4”而不是“iload_3”(和 istore 4/istore_3)之外,字节码没有显示出太大差异
到底他妈发生了什么? iload_3/istore_3 真的比 iload 4/istore 4 慢吗?这么慢,即使添加了 getstatic 调用仍然没有使它变慢?我可以猜测静态字段未使用,因此 jit 可能会跳过它。
无论如何,我这边没有歧义,因为它总是可重现的,我正在寻找有关 javac/jit 为什么做了他们所做的事情以及为什么性能受到如此大的影响的解释。这些是具有相同数据、相同内存流失等的相同递归算法......如果我愿意,我无法进行更孤立的更改,以显示显着的可复制运行时差异。
环境:
java version "1.8.0_161"
Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)
(also tried and reproduced on java9)
on a 4 core i5 laptop 8GB ram.
windows 10 with the meltdown/specter patch.
main]: qs1: 1561.3336199999999 ms (res=null)
main]: qs2: 1749.748416 ms (res=null)
main]: qs1: 1422.0767509999998 ms (res=null)
main]: qs2: 1700.4858689999999 ms (res=null)
main]: qs1: 1519.5280269999998 ms (res=null)
main]: qs2: 1786.2206899999999 ms (res=null)
main]: qs1: 1450.0802979999999 ms (res=null)
main]: qs2: 1675.223256 ms (res=null)
main]: qs1: 1452.373318 ms (res=null)
main]: qs2: 1634.581156 ms (res=null)
[0.039s][info][gc] Using G1
main]: qs1: 1287.062819 ms (res=null)
main]: qs2: 1451.041391 ms (res=null)
main]: qs1: 1240.800305 ms (res=null)
main]: qs2: 1391.2404299999998 ms (res=null)
main]: qs1: 1257.1707159999999 ms (res=null)
main]: qs2: 1433.84716 ms (res=null)
main]: qs1: 1233.7582109999998 ms (res=null)
main]: qs2: 1394.7195849999998 ms (res=null)
main]: qs1: 1250.885867 ms (res=null)
main]: qs2: 1413.88437 ms (res=null)
main]: qs1: 1261.5805739999998 ms (res=null)
main]: qs2: 1458.974334 ms (res=null)
main]: qs1: 1237.039902 ms (res=null)
main]: qs2: 1394.823751 ms (res=null)
main]: qs1: 1255.14672 ms (res=null)
main]: qs2: 1400.693295 ms (res=null)
main]: qs1: 1293.009808 ms (res=null)
main]: qs2: 1432.430952 ms (res=null)
main]: qs1: 1262.839628 ms (res=null)
main]: qs2: 1421.376644 ms (res=null)
import java.util.Random;
import java.util.concurrent.Callable;
public class QuicksortTrimmed {
static void p(Object msg) {
System.out.println(Thread.currentThread().getName()+"]: "+msg);
}
static void perf(int N, String msg, Callable c) throws Exception {
Object res = null;
long t = System.nanoTime();
for(int i=0; i<N; i++) {
res = c.call();
}
Double d = 1e-6*(System.nanoTime() - t);
p(msg+": "+d+" ms (res="+res+")");
}
static String und = "__________";//10
static {
und += und;//20
und += und;//40
und += und;//80
und += und;//160
}
static String sleft = "//////////";//10
static {
sleft += sleft;//20
sleft += sleft;//40
sleft += sleft;//80
sleft += sleft;//160
}
static String sright= "\\\\\\\\\\\\\\\\\\\\";//10
static {
sright += sright;//20
sright += sright;//40
sright += sright;//80
sright += sright;//160
}
//============
public static void main(String[] args) throws Exception {
int N = 20000;
int n = 1000;
int bound = 10000;
Random r = new Random(1);
for(int i=0; i<5; i++) {
testperf(N, r, n, bound);
//System.gc();
}
}
static void testperf(int N, Random r, int n, int bound) throws Exception {
final int[] orig = r.ints(n, 0, bound).toArray();
final int[] a = orig.clone();
perf(N, "qs1", () -> {
System.arraycopy(orig, 0, a, 0, orig.length);
quicksort1(a, 0, a.length-1, und);
return null;
});
perf(N, "qs2", () -> {
System.arraycopy(orig, 0, a, 0, orig.length);
quicksort2(a, 0, a.length-1);
return null;
});
System.out.println();
}
private static void quicksort1(int[] a, final int _from, final int _to, String mode) {
int len = _to - _from + 1;
if(len==2) {
if(a[_from] > a[_to]) {
int tmp = a[_from];
a[_from] = a[_to];
a[_to] = tmp;
}
} else { //len>2
int mid = _from+len/2;
final int pivot = a[mid];
a[mid] = a[_to];
a[_to] = pivot; //the pivot value is the 1st high value
int i = _from;
int j = _to;
while(i < j) {
if(a[i] < pivot)
i++;
else if(i < --j) { //j is the index of the leftmost high value
int tmp = a[i];
a[i] = a[j]; //THIS IS HARMFUL: maybe a[j] was a high value too.
a[j] = tmp;
}
}
//swap pivot in _to with other high value in j
int tmp = a[j];
a[j] = a[_to];
a[_to] = tmp;
if(_from < j-1)
quicksort1(a, _from, j-1, sleft);
if(j+1 < _to)
quicksort1(a, j+1, _to, sright);
}
}
private static void quicksort2(int[] a, final int _from, final int _to) {
int len = _to - _from + 1;
if(len==2) {
if(a[_from] > a[_to]) {
int tmp = a[_from];
a[_from] = a[_to];
a[_to] = tmp;
}
} else { //len>2
int mid = _from+len/2;
final int pivot = a[mid];
a[mid] = a[_to];
a[_to] = pivot; //the pivot value is the 1st high value
int i = _from;
int j = _to;
while(i < j) {
if(a[i] < pivot)
i++;
else if(i < --j) { //j is the index of the leftmost high value
int tmp = a[i];
a[i] = a[j]; //THIS IS HARMFUL: maybe a[j] was a high value too.
a[j] = tmp;
}
}
//swap pivot in _to with other high value in j
int tmp = a[j];
a[j] = a[_to];
a[_to] = tmp;
if(_from < j-1)
quicksort2(a, _from, j-1);
if(j+1 < _to)
quicksort2(a, j+1, _to);
}
}
}
# Run complete. Total time: 00:13:38
Benchmark Mode Cnt Score Error Units
MyBenchmark.testQuickSort1 thrpt 200 14861.437 ± 86.707 ops/s
MyBenchmark.testQuickSort2 thrpt 200 13097.209 ± 46.178 ops/s
package org.sample;
import java.util.Random;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.infra.Blackhole;
public class MyBenchmark {
static String und = "__________";//10
static {
und += und;//20
und += und;//40
und += und;//80
und += und;//160
}
static String sleft = "//////////";//10
static {
sleft += sleft;//20
sleft += sleft;//40
sleft += sleft;//80
sleft += sleft;//160
}
static String sright= "\\\\\\\\\\\\\\\\\\\\";//10
static {
sright += sright;//20
sright += sright;//40
sright += sright;//80
sright += sright;//160
}
static final int n = 1000;
static final int bound = 10000;
static Random r = new Random(1);
static final int[] orig = r.ints(n, 0, bound).toArray();
@State(Scope.Thread)
public static class ThrState {
int[] a;
@Setup(Level.Invocation)
public void setup() {
a = orig.clone();
}
}
//============
@Benchmark
public void testQuickSort1(Blackhole bh, ThrState state) {
int[] a = state.a;
quicksort1(a, 0, a.length-1, und);
bh.consume(a);
}
@Benchmark
public void testQuickSort2(Blackhole bh, ThrState state) {
int[] a = state.a;
quicksort2(a, 0, a.length-1);
bh.consume(a);
}
private static void quicksort1(int[] a, final int _from, final int _to, String mode) {
int len = _to - _from + 1;
if(len==2) {
if(a[_from] > a[_to]) {
int tmp = a[_from];
a[_from] = a[_to];
a[_to] = tmp;
}
} else { //len>2
int mid = _from+len/2;
final int pivot = a[mid];
a[mid] = a[_to];
a[_to] = pivot; //the pivot value is the 1st high value
int i = _from;
int j = _to;
while(i < j) {
if(a[i] < pivot)
i++;
else if(i < --j) { //j is the index of the leftmost high value
int tmp = a[i];
a[i] = a[j]; //THIS IS HARMFUL: maybe a[j] was a high value too.
a[j] = tmp;
}
}
//swap pivot in _to with other high value in j
int tmp = a[j];
a[j] = a[_to];
a[_to] = tmp;
if(_from < j-1)
quicksort1(a, _from, j-1, sleft);
if(j+1 < _to)
quicksort1(a, j+1, _to, sright);
}
}
private static void quicksort2(int[] a, final int _from, final int _to) {
int len = _to - _from + 1;
if(len==2) {
if(a[_from] > a[_to]) {
int tmp = a[_from];
a[_from] = a[_to];
a[_to] = tmp;
}
} else { //len>2
int mid = _from+len/2;
final int pivot = a[mid];
a[mid] = a[_to];
a[_to] = pivot; //the pivot value is the 1st high value
int i = _from;
int j = _to;
while(i < j) {
if(a[i] < pivot)
i++;
else if(i < --j) { //j is the index of the leftmost high value
int tmp = a[i];
a[i] = a[j]; //THIS IS HARMFUL: maybe a[j] was a high value too.
a[j] = tmp;
}
}
//swap pivot in _to with other high value in j
int tmp = a[j];
a[j] = a[_to];
a[_to] = tmp;
if(_from < j-1)
quicksort2(a, _from, j-1);
if(j+1 < _to)
quicksort2(a, j+1, _to);
}
}
}
-verbose:gc
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
-Xloggc:"./gc.log"
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=1M
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintCompilation
-XX:+PrintSafepointStatistics
-XX:PrintSafepointStatisticsCount=1
-XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation -XX:+PrintInlining
最佳答案
复制与分析
我能够重现你的结果。机器数据:
Linux #143-Ubuntu x86_64 GNU/Linux
java version "1.8.0_171"
Java(TM) SE Runtime Environment (build 1.8.0_171-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)
System.arraycopy()
调用。我创建了一个 400Mb 的数组结构并保存了它:
int[][][] data = new int[iterations][testCases][];
for (int iteration = 0; iteration < data.length; iteration++) {
for (int testcase = 0; testcase < data[iteration].length; testcase++) {
data[iteration][testcase] = random.ints(numberCount, 0, bound).toArray();
}
}
FileOutputStream fos = new FileOutputStream("test_array.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(data);
{
FileInputStream fis = new FileInputStream(fileName);
ObjectInputStream iis = new ObjectInputStream(fis);
int[][][] data = (int[][][]) iis.readObject();
perf("qs2", () -> {
for (int iteration = 0; iteration < data.length; iteration++) {
for (int testCase = 0; testCase < data[iteration].length; testCase++) {
quicksort2(data[iteration][testCase], 0, data[iteration][testCase].length - 1);
}
}
return null;
});
}
{
FileInputStream fis = new FileInputStream(fileName);
ObjectInputStream iis = new ObjectInputStream(fis);
int[][][] data = (int[][][]) iis.readObject();
perf("qs1", () -> {
for (int iteration = 0; iteration < data.length; iteration++) {
for (int testCase = 0; testCase < data[iteration].length; testCase++) {
quicksort1(data[iteration][testCase], 0, data[iteration][testCase].length - 1, und);
}
}
return null;
});
}
main]: qs1: 6646.219874 ms (res=null)
main]: qs2: 7418.376646 ms (res=null)
main]: qs2: 7526.215395 ms (res=null)
main]: qs1: 6624.261529 ms (res=null)
main]: qs1: 6592.699738 ms (res=null)
main]: qs2: 7456.326028 ms (res=null)
-Djava.compiler=NONE
main]: qs1: 56547.589942 ms (res=null)
main]: qs2: 53585.909246 ms (res=null)
Q1: 505
Q2: 480
53585.909246×505÷480 = 56376.842019229
-XX:+PrintCompilation
)我有这些行
1940 257 2 QS1::sort (185 bytes)
1953 258 % 4 QS1::sort @ 73 (185 bytes)
1980 259 4 QS1::sort (185 bytes)
1991 257 2 QS1::sort (185 bytes) made not entrant
9640 271 3 QS2::sort (178 bytes)
9641 272 4 QS2::sort (178 bytes)
9654 271 3 QS2::sort (178 bytes) made not entrant
-Xcomp -XX:+PrintCompilation -Xbatch
时,输出如下:
6408 3254 b 3 QS1::sort (185 bytes)
6409 3255 b 4 QS1::sort (185 bytes)
6413 3254 3 QS1::sort (185 bytes) made not entrant
14580 3269 b 3 QS2::sort (178 bytes)
14580 3270 b 4 QS2::sort (178 bytes)
14584 3269 3 QS2::sort (178 bytes) made not entrant
main]: qs1: 6982.721328 ms (res=null)
main]: qs2: 7606.077812 ms (res=null)
String
。如果我将额外的(未使用的)参数更改为
int
,它的处理速度始终会稍慢(使用先前的优化参数运行):
main]: qs1: 7925.472909 ms (res=null)
main]: qs2: 7727.628422 ms (res=null)
关于java - 通过简单地添加方法参数(更精简的 jit 代码),无法解释的 10% 以上的性能提升,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49754232/
我在一个项目中工作,该项目需要 SQL 结果的最佳性能,并且希望优化查询,但经过反复试验后,我在 IN 方面遇到了一些问题。 -- THIS RETURNS NO RESULTS AT ALL. SE
在尝试创建一个实际上非常简单的 SQL 语句时,我发现自己迷失了方向。 我有一个包含 3 个表的数据库: 食谱 - 存储一些用于 cooking 的食谱名称 配料食谱 - 将配料与食谱链接 成分 -
我正在尝试理解 PHP 中的 Hebrev 函数。 https://php.net/manual/en/function.hebrevc.php 它说:“将逻辑希伯来语文本转换为视觉文本”。但我不明白
嗨,我在 Grid view 的 android 文档中发现了一段代码对于以下代码。 gridview.setOnItemClickListener(new OnItemClickListener()
谁能解释一下 InfiniBand 是什么?与以太网相比的主要区别是什么,这些差异如何使其比以太网更快? 在官方description从 mellanox 写到 Introduce InfiniBan
这个问题已经有答案了: How are java increment statements evaluated in complex expressions (1 个回答) 已关闭 8 年前。 我知道
我正在阅读 MySQL 教程,我遇到了这个: SELECT /*! SQL_NO_CACHE */ user FROM users; 为什么优化提示 SQL_NO_CACHE 包含在: /*!
我无法理解$(this),我做了一个剪刀石头布的版本,并应用了 jQuery 让用户在计算机上选择按钮选项。我希望有人能解释一下 $(this) 指的是什么,它是 btn-primary 吗?该函数在
我不是很确定 while(choice == 1 || choice ==2);谁能解释一下。我明白这一点 if(choice ==1) displayMonthly(rainfall); e
let flyRight = CABasicAnimation(keyPath: "position.x") flyRight.toValue = view.bounds.size.width/2 f
目录 解释:int型默认值为0 但我们尝试发现并不能通过: 原因: int的默认值为0,而Integer的默认值为null
我正在处理一个查询,自从一个 SSRS 服务器传输到另一个服务器后,它似乎没有按预期执行,并且 where 语句的一部分中出现了以下行 找出不同之处,或者至少从我能找到的地方来看。 where COA
我正在制作一个退回检测程序,读取退回邮件。我们的设置是发送电子邮件,在发送的邮件中添加一个 noreply@domain.tl。一些收件人不再存在,因此我们想要读取退回邮件,并检测它发送给谁。我已经崩
我有一个关于公式通过控制点弯曲的问题。 如您所知,HTML Canvas 有 quadraticCurveTo(x1, y1, x2, y2)与 x1 and x2作为控制点。 但是,当您尝试使用它绘
我有一个 Emakefile看起来像: %% -- %% %% -- {'/Users/user/projects/custom_test/trunk/*', [debug_info, {out
我有一个非常简单的问题。这不仅适用于 spray-json,而且我已经阅读了 argonaut 和 circe 的类似声明。所以请赐教。 在 spray-json 中,我遇到了 There is no
我正在为视频添加水印。我试图让水印与视频尺寸成比例。我已经使用 scale2ref 看到了十几个不同的答案,但没有解释实际发生了什么,所以我发现很难知道如何实现/更改配置以适应我的情况。 当前覆盖命令
因为我正在学习语言,所以我在玩 Haskell,我只是发现了一些我不理解的东西,我找不到解释。如果我尝试运行此代码: map (`div` 0) [1,2,3,4] 我得到一个除以 0 的异常,这是预
我正在寻找解决错误对象引用未设置到对象实例的步骤/指南。以及问题发生原因的解释。 我正在寻找更一般的解释,所以如果我收到错误,我应该采取什么步骤来查找问题。我经常看到有人提供特定代码段的帖子,而其他人
我最近想升级我的知识React ,所以我从组件生命周期方法开始。让我好奇的第一件事是这个componentWillReceiveProps .所以,文档说当组件接收新的(不一定是更新的) Prop 时
我是一名优秀的程序员,十分优秀!