Golang 和大内存块分配
Golang and large memory chunk allocation
我有一个相当愚蠢的基准来测试内存分配的效率:
package main
import (
"time"
"fmt"
)
func main() {
size := 1024 * 1024 * 1024
t := time.Now()
for j := 0; j < 100; j += 1 {
a := make([]int, size)
for i := 0; i < size; i += 1 {
a[i] = i
}
a = nil
}
t1 := time.Now()
fmt.Printf("Duration: %1d", t1.Sub(t).Seconds())
}
使用 16GB 内存的 Mac Pro 大约需要 2-3 分钟,该过程的内存使用量保持在 5-8 GB。
Java 中非常相似的代码占用 3 GB 内存并在 30 秒内完成。
我在这里错过了什么?
What am I missing here?
在Java中,int
类型的大小固定为4字节。在 Go 中,int
是一种依赖于架构的类型,在 32 位架构上它是 32 位(4 字节),在 64 位架构上它是 64 位(8 字节)。
您很可能 运行 它在 64 位 arch 上。这意味着您分配的 Go 切片/数组的大小是 8 * 1 GB = 8 GB,而在 Java 中它只有 4 * 1 GB = 4 GB。
此外,由于您在循环中使用 int
,Java 只需递增和设置 4 字节值,而在 Go 中您递增和设置 8 字节值(i
和 j
的类型将是 int
)。
更改您的 Go 代码以使用 int32
,然后再试一次。
另请注意,您的内存使用量测量存在缺陷,因为 Java 中的数组大小在 Go 中为 4 GB 和 8 GB,因此 Java 为 3 GB 和 5-8 GB在 Go 中不是总内存使用量!
还要注意 Go 中的 []int
是一个 slice and not an array, they are not the same. Slices in Go are struct-like headers containing a pointer to a backing array (see reflect.SliceHeader
for details), so there is an implicit indirection step involved using them. For details see Also related:
最后一点:您的代码不测量内存分配,因为这只是应用程序执行时间的一小部分。大部分(如 99.99999%)的执行时间是将循环变量递增十亿次并用十亿个元素填充数组。
我有一个相当愚蠢的基准来测试内存分配的效率:
package main
import (
"time"
"fmt"
)
func main() {
size := 1024 * 1024 * 1024
t := time.Now()
for j := 0; j < 100; j += 1 {
a := make([]int, size)
for i := 0; i < size; i += 1 {
a[i] = i
}
a = nil
}
t1 := time.Now()
fmt.Printf("Duration: %1d", t1.Sub(t).Seconds())
}
使用 16GB 内存的 Mac Pro 大约需要 2-3 分钟,该过程的内存使用量保持在 5-8 GB。
Java 中非常相似的代码占用 3 GB 内存并在 30 秒内完成。
我在这里错过了什么?
What am I missing here?
在Java中,int
类型的大小固定为4字节。在 Go 中,int
是一种依赖于架构的类型,在 32 位架构上它是 32 位(4 字节),在 64 位架构上它是 64 位(8 字节)。
您很可能 运行 它在 64 位 arch 上。这意味着您分配的 Go 切片/数组的大小是 8 * 1 GB = 8 GB,而在 Java 中它只有 4 * 1 GB = 4 GB。
此外,由于您在循环中使用 int
,Java 只需递增和设置 4 字节值,而在 Go 中您递增和设置 8 字节值(i
和 j
的类型将是 int
)。
更改您的 Go 代码以使用 int32
,然后再试一次。
另请注意,您的内存使用量测量存在缺陷,因为 Java 中的数组大小在 Go 中为 4 GB 和 8 GB,因此 Java 为 3 GB 和 5-8 GB在 Go 中不是总内存使用量!
还要注意 Go 中的 []int
是一个 slice and not an array, they are not the same. Slices in Go are struct-like headers containing a pointer to a backing array (see reflect.SliceHeader
for details), so there is an implicit indirection step involved using them. For details see
最后一点:您的代码不测量内存分配,因为这只是应用程序执行时间的一小部分。大部分(如 99.99999%)的执行时间是将循环变量递增十亿次并用十亿个元素填充数组。