我一直在阅读div和mul组装操作,我决定通过在C中编写一个简单的程序来实现它们:
#include <stdlib.h>
#include <stdio.h>
int main()
{
size_t i = 9;
size_t j = i / 5;
printf("%zu\n",j);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然后生成汇编语言代码:
gcc -S division.c -O0 -masm=intel
Run Code Online (Sandbox Code Playgroud)
但是看生成的division.s文件,它不包含任何div操作!相反,它通过位移和魔术数字来做某种黑魔法.这是一个计算代码片段i/5:
mov rax, QWORD PTR [rbp-16] ; Move i (=9) to RAX
movabs rdx, -3689348814741910323 ; Move some magic number to RDX (?)
mul rdx ; Multiply 9 by magic number
mov rax, rdx ; Take only the upper 64 bits of the …Run Code Online (Sandbox Code Playgroud) 他们俩几乎都做同样的事情.确定方法很热并编译它而不是解释.使用OSR,您只需在编译后立即转移到编译版本,这与JIT不同,后者在第二次调用方法时调用编译代码.
除此之外,还有其他差异吗?
可能重复:
在Java中使用final关键字可以提高性能吗?
在最后的修改有不同的后果取决于你把它应用到什么在java中.我想知道的是,如果另外它可能有助于编译器创建更高效的字节码.我想这个问题深入探讨了JVM的工作原理以及JVM的具体情况.
那么,根据您的专业知识,请执行以下任何一项帮助编译器,或者您是否仅出于正常的java原因使用它们?
谢谢!
编辑:谢谢你的所有答案!请注意,正如@Zohaib建议的那样,我的问题与此重复.在发布之前我搜索得不够好.我不是删除它,因为你们做出了很好的贡献,但答案可以合并.除非另有说明,否则我会让"投票结束"系统决定.
我在开发用于异步消息传递的轻量级库的过程中遇到了这种情况。为了了解创建大量寿命较短的中等大小对象的成本,我编写了以下测试:
\nimport java.nio.ByteBuffer;\nimport java.util.Random;\n\n\npublic class MemPressureTest {\n static final int SIZE = 4096;\n static final class Bigish {\n final ByteBuffer b;\n\n\n public Bigish() {\n this(ByteBuffer.allocate(SIZE));\n }\n\n public Bigish(ByteBuffer b) {\n this.b = b;\n }\n\n public void fill(byte bt) {\n b.clear();\n for (int i = 0; i < SIZE; ++i) {\n b.put(bt);\n }\n }\n }\n\n\n public static void main(String[] args) {\n Random random = new Random(1);\n Bigish tmp = new Bigish();\n for (int i = 0; i < 3e7; ++i) …Run Code Online (Sandbox Code Playgroud) 我有这段代码做范围最小查询.当t = 100000时,i和j总是在每个输入行中改变,它在Java 8u60中的执行时间约为12秒.
for (int a0 = 0; a0 < t; a0++) {
String line = reader.readLine();
String[] ls = line.split(" ");
int i = Integer.parseInt(ls[0]);
int j = Integer.parseInt(ls[1]);
int min = width[i];
for (int k = i + 1; k <= j; k++) {
if (min > width[k]) {
min = width[k];
}
}
writer.write(min + "");
writer.newLine();
}
Run Code Online (Sandbox Code Playgroud)
当我提取新方法以找到最小值时,执行时间快4倍(约2.5秒).
for (int a0 = 0; a0 < t; a0++) {
String line = reader.readLine();
String[] …Run Code Online (Sandbox Code Playgroud) 我用java for循环进行了一些运行时测试,并发现了一个奇怪的行为.对于我的代码,我需要原始类型的包装器对象,如int,double等,以模拟io和输出参数,但这不是重点.只需看我的代码.具有字段访问权限的对象如何比原始类型更快?
for 具有prtimitive类型的循环:
public static void main(String[] args) {
double max = 1000;
for (int j = 1; j < 8; j++) {
double i;
max = max * 10;
long start = System.nanoTime();
for (i = 0; i < max; i++) {
}
long end = System.nanoTime();
long microseconds = (end - start) / 1000;
System.out.println("MicroTime primitive(max: ="+max + "): " + microseconds);
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
MicroTime原语(max:= 10000.0):110
MicroTime原语(max:= 100000.0):1081
MicroTime原语(max:=
1000000.0 ):2450 MicroTime原语(max:= 1.0E7):28248
MicroTime原语(max:= 1.0E8) :276205 …
我在解决Euler项目的问题205时发现了这一点.问题如下:
彼得有九个四面(金字塔)骰子,每个骰子都有编号为1,2,3,4的面孔.科林有六个六面(立方体)骰子,每个骰子都有编号为1,2,3,4,5,6的面孔.
彼得和科林掷骰子并比较总数:总得分最高.如果总数相等,结果是平局.
金字塔皮特击败立方科林的可能性是多少?将您的答案四舍五入到0.abcdefg形式的七位小数
我用Guava写了一个天真的解决方案:
import com.google.common.collect.Sets;
import com.google.common.collect.ImmutableSet;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
public class Problem205 {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
List<Integer> peter = Sets.cartesianProduct(Collections.nCopies(9, ImmutableSet.of(1, 2, 3, 4)))
.stream()
.map(l -> l
.stream()
.mapToInt(Integer::intValue)
.sum())
.collect(Collectors.toList());
List<Integer> colin = Sets.cartesianProduct(Collections.nCopies(6, ImmutableSet.of(1, 2, 3, 4, 5, 6)))
.stream()
.map(l -> l
.stream()
.mapToInt(Integer::intValue)
.sum())
.collect(Collectors.toList());
long startTime2 = System.currentTimeMillis();
// IMPORTANT BIT HERE! v
long solutions = …Run Code Online (Sandbox Code Playgroud) java ×7
jvm ×4
performance ×3
optimization ×2
assembly ×1
benchmarking ×1
c ×1
for-loop ×1
garbage ×1
gcc ×1
java-8 ×1
java-9 ×1
java-stream ×1
javacompiler ×1
jit ×1
jvm-hotspot ×1
x86-64 ×1