Java is more than twice as fast as Go. Go claims to be close to C’s performance, isn’t it? At the end, I will share the link to the article I read. Next, listen to my analysis.
Prepare test code
Java test code
You can see that the logic is simple: sort a fixed array, execute the for loop 100 million times, record the total time, the code is the same as the code I read in the article.
Public static void main(String[] args) {long start = system.nanotime (); int num = 100000000;for(int i = 0; i < num; i++) { BubbleSort(1, 2, 3, 4, 5, 6, 7, 8, 9); } system.out.println (system.nanotime () -start); } // Sort public static void BubbleSort(int... arr) {for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if(arr[j] < arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; }}}}Copy the code
Go test code
And Java function is the same, is a hundred million sorting, code and I have seen the article code consistent.
func Sort() {
start := time.Now().UnixNano()
var arr []int
const NUM int = 100000000
fori := 0; i < NUM; i++ { arr = []int{1, 2, 3, 4, 5, 6, 7, 8, Println(time.now ().unixnano () -start)} func bubbleSort(arr []int) {for j := 0; j < len(arr)-1; j++ {
for k := 0; k < len(arr)-1-j; k++ {
if arr[k] < arr[k+1] {
temp := arr[k]
arr[k] = arr[k+1]
arr[k+1] = temp
}
}
}
}Copy the code
My local environment is as follows: Java: jdk1.8, GoLang: 1.12 i7 processor, 16G memory, Windows10 system
- Java result: 3263111300 ns = 3263 ms = 3.2s
- Go result: 7165483700 ns = 7165 ms = 7.1s
Do you believe this result? Java performs better than Go, more than twice as fast. Did all the articles I read deceive me?
Decryption began
Look at two pieces of code, there are some subtle differences, sometimes a little bit of subtle differences as a result of the differ in thousands ways, even make you a wrong conclusion to mislead you, look down the Go code, this code fragment is in the Sort method, we see a arr variables, this variable is not defined in the for loop, It’s defined outside the for loop, and it gets reassigned inside the for loop.
var arr []int
const NUM int = 100000000
for i := 0; i < NUM; i++ {
arr = []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
bubbleSort(arr)
}Copy the code
Change the above code to the following:
const NUM int = 100000000
for i := 0; i < NUM; i++ {
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
bubbleSort(arr)
}Copy the code
After that, we tested again, and the results were as follows. This made my heart a little more balanced. Otherwise, I could not bear the poor performance of Go, which I have always loved. So why change a line of code, such a big difference.
- Java result: 3263111300 ns = 3263 ms = 3.2s
- Go result: 4137247700 ns = 4137 ms = 4.1s
This actually involves the variable allocation problem of Go. Go memory is divided into two types of heap and stack. A variable is either allocated on the heap or on the stack. Heap: it is collected by the GC. Heap stack corresponding to the process address space: no GC operations are involved. Each goroutine has its own stack, which is initially allocated on the stack of the process address space, and when expanded on the heap of the process address space.
Here I recommend a Java learning exchange group. Exchange learning group number: 874811168 inside will share some senior architects recorded video video: Spring, MyBatis, Netty source code analysis, high concurrency, high performance, distributed, microservice architecture principle, JVM performance optimization, distributed architecture, and so on these become architects necessary knowledge system. Also can receive free learning resources, study together, progress together, currently benefited a lot.
Our arR variable here is a local variable, so where does Go assign it? We decompile the two pieces of code, write a main.go file, call the two sorting functions in the main function, and execute this command: Go tool compile -m main.go, where the first red circle is before the modification of the code arr variable is allocated on the heap, after the modification of the code arr variable is allocated on the stack, this is go independent optimization, how to determine? Go is obtained by doing escape analysis, and I believe you have already understood some of it. That’s all for variable allocation. This topic is very deep and can be talked about for a long time.
In fact, if you drill down a little bit, and you adjust the number of for loops for Java and Go, say, a thousand, and you compare the results, you’ll find that Go performs better than Java. Why? Let me remind you that you can think about GC and JIT optimization in Java.
How would Go perform if the bubbleSort method for Go was changed to pointer pass, as shown below?
func bubbleSort(arr *[]int) {
}Copy the code