Go语言整数和浮点数运算效率实验

Go性能实验 by 达达 at 2013-10-30

我们团队使用Go来开发游戏服务端,游戏服务端的战斗逻辑避免不了各种计算,C的编程经验告诉我们整数运算效率比浮点运算高,但是在Go语言中,这两种数据类型的运算效率到底差多少呢?是否有必要把浮点数转换成整数的万分数或者千分数进行运算呢?下面通过实验来对比。

实验代码(github):

package labs05

import "testing"

func Benchmark_IntAdd(b *testing.B) {
    var a = 0

    for i := 0; i < b.N; i++ {
        a += 1
    }
}

func Benchmark_Int8Add(b *testing.B) {
    var a int8 = 0

    for i := 0; i < b.N; i++ {
        a += 1
    }
}

func Benchmark_Int16Add(b *testing.B) {
    var a int8 = 0

    for i := 0; i < b.N; i++ {
        a += 1
    }
}

func Benchmark_Int32Add(b *testing.B) {
    var a int32 = 0

    for i := 0; i < b.N; i++ {
        a += 1
    }
}

func Benchmark_Int64Add(b *testing.B) {
    var a int64 = 0

    for i := 0; i < b.N; i++ {
        a += 1
    }
}

func Benchmark_Float32Add(b *testing.B) {
    var a float32 = 0.1

    for i := 0; i < b.N; i++ {
        a += 1.0
    }
}

func Benchmark_Float64Add(b *testing.B) {
    var a float64 = 0.1

    for i := 0; i < b.N; i++ {
        a += 1.0
    }
}

func Benchmark_IntSub(b *testing.B) {
    var a = 0x7FFFFFFFFF

    for i := 0; i < b.N; i++ {
        a -= 1
    }
}

func Benchmark_Int8Sub(b *testing.B) {
    var a int8 = 0x7F

    for i := 0; i < b.N; i++ {
        a -= 1
    }
}

func Benchmark_Int16Sub(b *testing.B) {
    var a int16 = 0x7FFF

    for i := 0; i < b.N; i++ {
        a -= 1
    }
}

func Benchmark_Int32Sub(b *testing.B) {
    var a int32 = 0x7FFFFFFF

    for i := 0; i < b.N; i++ {
        a -= 1
    }
}

func Benchmark_Int64Sub(b *testing.B) {
    var a int64 = 0x7FFFFFFFFF

    for i := 0; i < b.N; i++ {
        a -= 1
    }
}

func Benchmark_Float32Sub(b *testing.B) {
    var a = float32(0x7FFFFFFF)

    for i := 0; i < b.N; i++ {
        a -= 1.0
    }
}

func Benchmark_Float64Sub(b *testing.B) {
    var a = float64(0xFFFFFFFFFF)

    for i := 0; i < b.N; i++ {
        a -= 1.0
    }
}

func Benchmark_IntMul(b *testing.B) {
    var a = 1

    for i := 0; i < b.N; i++ {
        a *= 3
    }
}

func Benchmark_Int8Mul(b *testing.B) {
    var a int8 = 1

    for i := 0; i < b.N; i++ {
        a *= 3
    }
}

func Benchmark_Int16Mul(b *testing.B) {
    var a int16 = 1

    for i := 0; i < b.N; i++ {
        a *= 3
    }
}

func Benchmark_Int32Mul(b *testing.B) {
    var a int32 = 1

    for i := 0; i < b.N; i++ {
        a *= 3
    }
}

func Benchmark_Int64Mul(b *testing.B) {
    var a int64 = 1

    for i := 0; i < b.N; i++ {
        a *= 3
    }
}

func Benchmark_Float32Mul(b *testing.B) {
    var a float32 = 1.0

    for i := 0; i < b.N; i++ {
        a *= 1.5
    }
}

func Benchmark_Float64Mul(b *testing.B) {
    var a float64 = 1.0

    for i := 0; i < b.N; i++ {
        a *= 1.5
    }
}

func Benchmark_IntDiv(b *testing.B) {
    var a = 0x7FFFFFFFFF

    for i := 0; i < b.N; i++ {
        a /= 3
    }
}

func Benchmark_Int8Div(b *testing.B) {
    var a int8 = 0x7F

    for i := 0; i < b.N; i++ {
        a /= 3
    }
}

func Benchmark_Int16Div(b *testing.B) {
    var a int16 = 0x7FFF

    for i := 0; i < b.N; i++ {
        a /= 3
    }
}

func Benchmark_Int32Div(b *testing.B) {
    var a int32 = 0x7FFFFFFF

    for i := 0; i < b.N; i++ {
        a /= 3
    }
}

func Benchmark_Int64Div(b *testing.B) {
    var a int64 = 0x7FFFFFFFFF

    for i := 0; i < b.N; i++ {
        a /= 3
    }
}

func Benchmark_Float32Div(b *testing.B) {
    var a = float32(0x7FFFFFFF)

    for i := 0; i < b.N; i++ {
        a /= 1.5
    }
}

func Benchmark_Float64Div(b *testing.B) {
    var a = float64(0x7FFFFFFFFF)

    for i := 0; i < b.N; i++ {
        a /= 1.5
    }
}

实验结果:

dada-imac:labs dada$ go test -test.bench="." labs05
testing: warning: no tests to run
PASS
Benchmark_IntAdd        2000000000           0.28 ns/op
Benchmark_Int8Add       2000000000           0.28 ns/op
Benchmark_Int16Add      2000000000           0.28 ns/op
Benchmark_Int32Add      2000000000           0.28 ns/op
Benchmark_Int64Add      2000000000           0.28 ns/op
Benchmark_Float32Add    2000000000           1.05 ns/op
Benchmark_Float64Add    2000000000           0.79 ns/op
Benchmark_IntSub        2000000000           0.28 ns/op
Benchmark_Int8Sub       2000000000           0.28 ns/op
Benchmark_Int16Sub      2000000000           0.27 ns/op
Benchmark_Int32Sub      2000000000           0.28 ns/op
Benchmark_Int64Sub      2000000000           0.28 ns/op
Benchmark_Float32Sub    2000000000           1.31 ns/op
Benchmark_Float64Sub    2000000000           0.87 ns/op
Benchmark_IntMul        2000000000           0.79 ns/op
Benchmark_Int8Mul       2000000000           0.79 ns/op
Benchmark_Int16Mul      2000000000           0.79 ns/op
Benchmark_Int32Mul      2000000000           0.79 ns/op
Benchmark_Int64Mul      2000000000           0.79 ns/op
Benchmark_Float32Mul    2000000000           1.57 ns/op
Benchmark_Float64Mul    2000000000           1.31 ns/op
Benchmark_IntDiv        2000000000           1.57 ns/op
Benchmark_Int8Div       2000000000           1.84 ns/op
Benchmark_Int16Div      1000000000           2.08 ns/op
Benchmark_Int32Div      2000000000           1.62 ns/op
Benchmark_Int64Div      2000000000           1.57 ns/op
Benchmark_Float32Div    50000000             44.3 ns/op
Benchmark_Float64Div    50000000             48.0 ns/op
ok      labs05  49.453s    

结论:浮点数除法明显更慢,尽量把除法转换为乘法运算。